前日,一小伙伴問我一個問題,說它解決了半天都沒解決這個問題,截圖如下:
大概樓主理解如下:
如果在應用中有一個判斷wifi的開關和一個當前音量大小的seekbar以及一個獲取當前電量多少的按鈕,想知道如果按home鍵后調整了wifi開關信息以及媒體音量信息,再切換到前台UI如何才會實時刷新。其實這個問題不難解決,如果你了解activity的生命周期,只需要把設置開關和seekbar的信息放在onResume中就好了,因為無論是鎖屏后打開或者是切換后台再前台都是會調用onResume的。但不由得滋生一個問題,大家都知道APP在前台的情況下用戶依然是可以下拉狀態欄設置Wifi開關信息的,對於音量信息也是可以側邊增減,那APP一直在前台,生命周期明顯是無法實時更新了,那我們應該如何解決呢?沒錯,沒當改變系統屬性的時候,都會發出系統廣播,我們只需要去寫一個接收器,並根據它做響應的操作就好了。
分析至此,樓主就把給這位小伙伴寫的一些代碼分享給大家,也可以幫助不太熟悉的小伙伴更加了解android的廣播以及回調機制。對於還不太明白java的回調是什么意思的小伙伴,也可以看看。
1)由於要使用到系統屬性,所以先申明權限。
1 <!--wifi管理必備權限--> 2 <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/> 3 <uses-permission android:name="android.permission.CHANGE_WIFI_STATE"/> 4 5 <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/> 6 7 <!--操作音頻需要權限--> 8 <uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
2)然后寫一個廣播接收器,做好過濾,並申明一個回調接口,用於當廣播接收到的時候提醒主線程更新UI。
1 package com.example.nanchen.maweinaitest; 2 3 import android.content.BroadcastReceiver; 4 import android.content.Context; 5 import android.content.Intent; 6 import android.media.AudioManager; 7 import android.net.wifi.WifiManager; 8 import android.util.Log; 9 10 import static android.content.Intent.ACTION_BATTERY_CHANGED; 11 12 /** 13 * @author nanchen 14 * @fileName MaWeiNaiTest 15 * @packageName com.example.nanchen.maweinaitest 16 * @date 2016/11/05 21:35 17 */ 18 19 public class MyStatusReceiver extends BroadcastReceiver { 20 21 private static final String TAG = "MyStatusReceiver"; 22 private StatusCallback mStatusCallback = MainActivity.callback; 23 24 public MyStatusReceiver(){ 25 } 26 27 @Override 28 public void onReceive(Context context, Intent intent) { 29 30 String action = intent.getAction(); 31 Log.e(TAG,action); 32 Log.e(TAG,intent.getAction()+" ==== "); 33 34 35 // 首先判斷它是否是電量變化的Broadcast Action 36 if (ACTION_BATTERY_CHANGED.equals(action)) {//如果監聽到電量改變廣播 37 // 獲取當前電量 38 int level = intent.getIntExtra("level", 0); 39 // 電量的總刻度 40 int scale = intent.getIntExtra("scale", 100); 41 // 把它轉換為百分比 42 // mActivity.mTextView.setText(level * 100 / scale + "%"); 43 String str = level * 100 / scale + "%"; 44 45 Log.e(TAG,level+""); 46 Log.e(TAG,scale+""); 47 Log.e(TAG,str+""); 48 49 mStatusCallback.onPowerChanged(level * 100 / scale + "%"); 50 } 51 // 監聽一下音量 52 if ("android.media.VOLUME_CHANGED_ACTION".equals(action)){ 53 // mActivity.mSeekBar.setProgress(mActivity.mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM)); 54 AudioManager audioManager = (AudioManager) context.getSystemService(Context.AUDIO_SERVICE); 55 int progress = audioManager.getStreamVolume(AudioManager.STREAM_SYSTEM); 56 Log.e(TAG,progress+""); 57 mStatusCallback.onAudioChanged(audioManager.getStreamVolume(AudioManager.STREAM_SYSTEM)); 58 } 59 if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action)){ 60 WifiManager wifiManager = (WifiManager) context.getSystemService(Context.WIFI_SERVICE); 61 mStatusCallback.onWifiChanged(wifiManager.isWifiEnabled()); 62 } 63 } 64 65 /** 66 * 一個回調接口 67 */ 68 public interface StatusCallback { 69 /** 70 * 當電量改變時應該調用的回調接口 71 * @param status 當前電量百分比 72 */ 73 void onPowerChanged(String status); 74 75 /** 76 * 當音頻音量改變時會調用的回調接口 77 * @param status 當前音量數值 78 */ 79 void onAudioChanged(int status); 80 81 /** 82 * 當wifi改變時會調用的回調接口 83 * @param status wifi的開關 true-開 false - 關 84 */ 85 void onWifiChanged(boolean status); 86 } 87 }
3)別忘了在mainfest申明
1 <receiver android:name=".MyStatusReceiver"> 2 <intent-filter> 3 <action android:name="android.intent.action.BATTERY_CHANGED"/> 4 <action android:name="android.media.VOLUME_CHANGED_ACTION"/> 5 <action android:name="android.net.wifi.WIFI_STATE_CHANGED_ACTION"/> 6 </intent-filter> 7 </receiver>
4)布局就采用的這位小伙伴的布局
1 <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 2 xmlns:tools="http://schemas.android.com/tools" 3 android:layout_width="match_parent" 4 android:layout_height="match_parent" 5 android:orientation="vertical"> 6 7 8 9 <Switch 10 android:id="@+id/wifi" 11 android:layout_width="wrap_content" 12 android:layout_height="wrap_content" 13 android:textOn="開" 14 android:textOff="關" 15 android:text="WiFi"/> 16 17 <SeekBar 18 android:id="@+id/seekBar" 19 android:layout_width="match_parent" 20 android:layout_height="wrap_content" 21 android:layout_marginTop="16dp"/> 22 23 <Button 24 android:id="@+id/btn" 25 android:layout_width="match_parent" 26 android:layout_height="wrap_content" 27 android:layout_marginTop="16dp" 28 android:text="當前電量百分比" /> 29 30 31 <LinearLayout 32 android:orientation="horizontal" 33 android:layout_width="match_parent" 34 android:layout_height="wrap_content"> 35 36 <TextView 37 android:layout_width="wrap_content" 38 android:layout_height="wrap_content" 39 android:text="當前電量百分比為:"/> 40 41 <TextView 42 android:layout_width="wrap_content" 43 android:layout_height="wrap_content" 44 android:text="0%" 45 android:id="@+id/text"/> 46 </LinearLayout> 47 48 49 </LinearLayout>
5)最后是MainActivity,注意廣播注銷,否則造成內存泄漏!
1 package com.example.nanchen.maweinaitest; 2 3 import android.content.Context; 4 import android.content.IntentFilter; 5 import android.media.AudioManager; 6 import android.net.wifi.WifiManager; 7 import android.os.Bundle; 8 import android.view.View; 9 import android.view.View.OnClickListener; 10 import android.widget.CompoundButton; 11 import android.widget.CompoundButton.OnCheckedChangeListener; 12 import android.widget.SeekBar; 13 import android.widget.SeekBar.OnSeekBarChangeListener; 14 import android.widget.Switch; 15 import android.widget.TextView; 16 import android.widget.Toast; 17 18 import com.example.nanchen.maweinaitest.MyStatusReceiver.StatusCallback; 19 20 import static android.content.Intent.ACTION_BATTERY_CHANGED; 21 22 23 public class MainActivity extends ActivityBase implements StatusCallback { 24 25 public static StatusCallback callback; 26 27 private static final String TAG = "MainActivity"; 28 private Switch mSwitchWifi; 29 private SeekBar mSeekBar; 30 private WifiManager mWifiManager; 31 private AudioManager mAudioManager; 32 private TextView mTextView; 33 private MyStatusReceiver mMyStatusReceiver; 34 35 @Override 36 protected void onCreate(Bundle savedInstanceState) { 37 super.onCreate(savedInstanceState); 38 setContentView(R.layout.activity_main); 39 callback = this; 40 41 bindView(); 42 43 initManager(); 44 45 bindListener(); 46 47 } 48 49 private void initManager() { 50 // 獲取Wifi管理器 51 mWifiManager = (WifiManager) getSystemService(Context.WIFI_SERVICE); 52 // 把動態獲取的信息放在onResume設置 避免按home鍵后再把APP切換到前台獲取不到正常的數據 53 54 55 // 獲取音頻管理器 56 mAudioManager = (AudioManager) getSystemService(Context.AUDIO_SERVICE); 57 } 58 59 /** 60 * 綁定監聽 61 */ 62 private void bindListener() { 63 // 為wifi開關事件設置監聽 64 mSwitchWifi.setOnCheckedChangeListener(new OnCheckedChangeListener() { 65 @Override 66 public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { 67 if (!isChecked) { 68 buttonView.setChecked(false); 69 mWifiManager.setWifiEnabled(false); 70 Toast.makeText(MainActivity.this, "wifi關閉成功!", Toast.LENGTH_SHORT).show(); 71 } else { 72 buttonView.setChecked(true); 73 mWifiManager.setWifiEnabled(true); 74 Toast.makeText(MainActivity.this, "wifi開啟成功!", Toast.LENGTH_SHORT).show(); 75 } 76 } 77 }); 78 79 // 再動態監聽SeekBar 80 mSeekBar.setOnSeekBarChangeListener(new OnSeekBarChangeListener() { 81 @Override 82 public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { 83 // 停止滑動 84 mSeekBar.setProgress(progress); 85 // 三個參數一次是 模式,值,標志位 86 mAudioManager.setStreamVolume(AudioManager.STREAM_SYSTEM, progress, 0); 87 } 88 89 @Override 90 public void onStartTrackingTouch(SeekBar seekBar) { 91 92 } 93 94 @Override 95 public void onStopTrackingTouch(SeekBar seekBar) { 96 97 } 98 }); 99 100 // 注冊廣播,添加三個Action 101 IntentFilter intentFilter = new IntentFilter(); 102 intentFilter.addAction(ACTION_BATTERY_CHANGED); 103 intentFilter.addAction(AudioManager.RINGER_MODE_CHANGED_ACTION); 104 intentFilter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION); 105 mMyStatusReceiver = new MyStatusReceiver(); 106 registerReceiver(mMyStatusReceiver, intentFilter); // 注冊監聽廣播 107 } 108 109 110 private int max; 111 private int current; 112 113 /** 114 * 設置wifi開關 115 */ 116 private void setWifiSwitch() { 117 if (mWifiManager.isWifiEnabled()) { 118 mSwitchWifi.setChecked(true); 119 } else { 120 mSwitchWifi.setChecked(false); 121 } 122 } 123 124 @Override 125 protected void onResume() { 126 super.onResume(); 127 // 先動態設置wifi 128 setWifiSwitch(); 129 130 // 再動態設置音頻音量 參數為音量模式 131 max = mAudioManager.getStreamMaxVolume(AudioManager.STREAM_SYSTEM); // 最大音量 132 current = mAudioManager.getStreamVolume(AudioManager.STREAM_SYSTEM); // 當前音量 133 134 mSeekBar.setMax(max);// 設置seekBar 135 mSeekBar.setProgress(current); 136 } 137 138 @Override 139 protected void onPause() { 140 super.onPause(); 141 // 一定記得注銷廣播,否則會造成內存泄漏 142 unregisterReceiver(mMyStatusReceiver); 143 } 144 145 @SuppressWarnings("ConstantConditions") 146 private void bindView() { 147 mSwitchWifi = (Switch) findViewById(R.id.wifi); 148 mSeekBar = (SeekBar) findViewById(R.id.seekBar); 149 mTextView = (TextView) findViewById(R.id.text); 150 findViewById(R.id.btn).setOnClickListener(new OnClickListener() { 151 @Override 152 public void onClick(View v) { 153 // 在這里獲取當前電量信息 154 155 // 這里就不寫了,實際上監聽系統廣播,它會自動實時獲取電量信息 156 } 157 }); 158 } 159 160 161 @Override 162 public void onPowerChanged(String status) { 163 mTextView.setText(status); 164 } 165 166 @Override 167 public void onAudioChanged(final int status) { 168 mSeekBar.setProgress(status); 169 } 170 171 @Override 172 public void onWifiChanged(boolean status) { 173 mSwitchWifi.setChecked(status); 174 } 175 176 }
大概運行圖如下:
代碼已上傳至github:https://github.com/nanchen2251/ReceiverDemo