当你的才华还撑不起你的梦想时,你只能一直前进!

【用户交互】APP没有退出前台但改变系统属性如何实时更新UI?监听系统广播,让用户交互更舒心~

前日,一小伙伴问我一个问题,说它解决了半天都没解决这个问题,截图如下:

 

大概楼主理解如下:

如果在应用中有一个判断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

posted @ 2016-11-07 13:32  南尘  阅读(1699)  评论(4编辑  收藏  举报

写不完的矫情,做不完的开源

点击进入我的GitHub页
南 尘
主 页
优美钢琴曲合集-南尘.mp3                    感谢您阅读我的博客,如果您现在工作、学习累了或者疲惫了,不妨聆听一下音乐,它能够减轻你的疲劳,还能够带给您一种舒适愉悦的心情。(样式取自博客园-欲泪成雪)