前日,一小伙伴问我一个问题,说它解决了半天都没解决这个问题,截图如下:
大概楼主理解如下:
如果在应用中有一个判断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