【用戶交互】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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM