预期效果
用户正在与本应用程序界面交互时,或本应用程序退到后台时,只要检测wifi被关闭,都能弹出相应对话框提示用户“请打开wifi”,用户必须点击对话框中的确定按钮跳转到“网络设置界面”。
请打开wifi.png
思路
1. 监听wifi开关状态改变广播、在广播接收器中进行逻辑判断
想要实现上述效果的话,存在这样一个问题,因为当我们被通知需要打开wifi时可能处于任何一个界面,难道要为每个界面上都编写一个弹出对话框的逻辑吗?
不能呀!借助广播的知识,当wifi开关状态改变时会收到一条系统广播,这条广播就是用于进行处理弹框逻辑的通知。所以“请打开wifi”弹框的逻辑写在接收这条广播的广播接收器中。这样该逻辑判断不会依附于任何界面,不管在程序的任何地方,只要发出这样一条广播,就可以完成这个逻辑判断。
系统广播WifiManager.WIFI_STATE_CHANGED_ACTION
,通过监听wifi开关状态变化的广播,
wifi开关状态
WifiManager.WIFI_STATE_DISABLED ; (1) 关闭
WifiManager..WIFI_STATE_ENABLED ; (3) 打开
WifiManager..WIFI_STATE_DISABLING ;(0) 关闭中
WifiManager..WIFI_STATE_ENABLING ; (2) 打开中
WifiManager..WIFI_STATE_UNKONW ; (4) 未知
2. 广播接收器注册、取消注册的地方
一般广播接收器是在onResume()中注册,onPause()中取消注册。从Activity的生命周期特点可知,onResume()方法被回调后Activity可与用户交互,onPause()被回调后Activity不可与用户交互。这样的做法:保证了始终只有栈顶的活动才能接收到广播,非栈顶的活动不应该也没必要去接收这条广播,当一个活动失去栈顶位置时自动取消广播接收器的注册。
但现在,我们的需求是,在Activity可与用户交互,或不可与用户交互时都可弹框提示用户。故选择在onCreate()中注册广播接收器(Activity始终可以接收这条广播),在onDestroy()中取消注册。
3.广播接收器onReceive()方法中的逻辑
onReceive()方法中的逻辑.pngpublic class WifiListenerReceiver extends BroadcastReceiver {
public static final String MY_WIFI_BROADCAST="MY_WIFI_BROADCAST";
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action) || Constant.WIFI_LISTENER_ACTION.equals(action)) {
int wifiState = DeviceInfoUtil.getWifiState(context);
Log.e("LoginActivity", "收到wifi广播"+wifiState);
switch (wifiState) {
case WifiManager.WIFI_STATE_DISABLED:
case WifiManager.WIFI_STATE_DISABLING:
case WifiManager.WIFI_STATE_UNKNOWN:
/*
* wifi处于关闭状态:若“请打开wifi对话框”正在显示,将该对话框显示在前台;
* 未正在显示:创建新的并显示
*/
Intent intent1 = new Intent(context, OpenWifiActivity.class);
// 以SingleTask的模式启动(栈内复用)
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
break;
case WifiManager.WIFI_STATE_ENABLED:
case WifiManager.WIFI_STATE_ENABLING:
/*
* wifi处于开启状态:若“请打开wifi对话框”正在显示,将该对话框关闭;
* 未正在显示:Nothing
*/
OpenWifiActivityCollector.finishAll();
break;
}
}
}
}
3.1“请打开wifi”框的制作:用Activity做成Dialog的样式
将OpenWifiActivity主题设置为
<style name="FDialogStyle" parent="AlertDialog.AppCompat">
<item name="android:windowBackground">@android:color/transparent</item> 设置dialog的背景,此处为系统给定的透明值
<item name="android:windowFrame">@null</item> Dialog的windowFrame框为无
<item name="android:windowNoTitle">true</item> 是否显示标题
<item name="android:windowIsFloating">true</item> 是否浮现在activity之上
<item name="android:windowIsTranslucent">true</item> 是否半透明
<item name="android:windowContentOverlay">@null</item> 是否有覆盖
<item name="android:windowAnimationStyle">@android:style/Animation.Dialog</item> 设置Activity出现方式
<item name="android:backgroundDimEnabled">true</item> 背景是否模糊显示
</style>
3.2可能会出现:连续弹出多个“请打开wifi”框
此处是将Activity做成Dialog的效果显示出来。故将Activity的启动模式设置成SingleTask,就可保证栈内复用,始终只有一个弹框
<activity
android:name=".module.wifi.OpenWifiActivity"
android:theme="@style/FDialogStyle"
android:launchMode="singleTask"></activity>
3.3会出现的情况:“请打开wifi”框正在显示,通过通知栏打开wifi,但该框未被销毁
如何销毁打开的Activity?此处参考郭霖-第一行代码-随时随地退出程序功能的实现。
用一个专门的集合类对所有打开的OpenWifiActivity实例进行存储。当需要关闭OpenWifiActivity时,finish掉集合中保存的该活动的所有实例
public class OpenWifiActivity extends Activity {
@BindView(R.id.btn_openwifi_sure)
Button btn_sure;
@BindView(R.id.btn_openwifi_cancel)
Button btn_cancel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_openwifi);
KnifeKit.bind(this);
// 加入到ActivityCollector中
OpenWifiActivityCollector.addActivity(this);
btn_sure.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DeviceInfoUtil.openWifiSetting(getApplicationContext());
finish();
}
});
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// 从管理类中移除实例
OpenWifiActivityCollector.removeActivity(this);
}
}
public class OpenWifiActivityCollector {
public static List<Activity> sActivities = new ArrayList<>();
public static void addActivity(Activity activity) {
sActivities.add(activity);
}
public static void removeActivity(Activity activity) {
sActivities.remove(activity);
}
public static void finishAll() {
for (Activity activity : sActivities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}
代码实现【下面给出相关代码文件】
1.base
base.pngMyBaseActivity
public abstract class MyBaseActivity extends AppCompatActivity implements MyUiCallback {
public static AlertDialog mAlertDialog;
protected Activity context;
private Unbinder unbinder;
// GPS检测监听
private GPSListenerRecevicer receiver;
// Wifi状态改变监听
private WifiListenerReceiver mWifiListenerReceiver;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
Log.e(getClass().getSimpleName(), "onCreate");
this.context = this;
beforeSetConentView(savedInstanceState);
if (getLayoutId() > 0) {
setContentView(getLayoutId());
unbinder = KnifeKit.bind(this);
}
setListener();
initData(savedInstanceState);
/*
* 在onCreate中注册WiFi广播监听,在onDestroy中取消注册
* ylj
*/
registerWifiReceiver();
}
/**
* 注册wifi状态改变广播接收器
*/
protected void registerWifiReceiver(){
mWifiListenerReceiver = new WifiListenerReceiver();
IntentFilter filter = new IntentFilter();
filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
filter.addAction(Constant.WIFI_LISTENER_ACTION);
registerReceiver(mWifiListenerReceiver, filter);
}
@Override
public void beforeSetConentView(Bundle savedInstanceState) {
}
@Override
public void setListener() {
}
@Override
protected void onResume() {
super.onResume();
Log.e(getClass().getSimpleName(), "onResume");
/*
*
* 在每次resume中,发送一条检测wifi状态的广播
*/
sendCheckWifiStateBroadcast();
}
protected void sendCheckWifiStateBroadcast(){
Intent intent = new Intent();
intent.setAction(Constant.WIFI_LISTENER_ACTION);
sendBroadcast(intent);
Log.e(getClass().getSimpleName(), "发出MY_WIFI_BROADCAST广播");
}
@Override
protected void onDestroy() {
super.onDestroy();
Log.e(getClass().getSimpleName(), "onDestroy");
/*
* 取消注册wifi状态改变广播接收器
* ylj
*/
unregisterWifiReceiver();
}
/**
* 取消注册wifi状态改变广播接收器
* ylj
*/
private void unregisterWifiReceiver() {
if (mWifiListenerReceiver != null) {
unregisterGPSListener();
mWifiListenerReceiver = null;
}
}
}
MyUiCallback
/**
* <pre>
* author : 杨丽金
* time : 2018/03/23
* desc :
* </pre>
*/
public interface MyUiCallback {
// 在setContentView()之前调用的方法
void beforeSetConentView(Bundle savedInstanceState);
// 下面的三个方法都是在setContentView()之后调用的
void initData(Bundle savedInstanceState);
void setListener();
int getLayoutId();
}
2.wifi
wifi.pngOpenWifiActivity
public class OpenWifiActivity extends Activity {
@BindView(R.id.btn_openwifi_sure)
Button btn_sure;
@BindView(R.id.btn_openwifi_cancel)
Button btn_cancel;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_openwifi);
KnifeKit.bind(this);
// 加入到ActivityCollector中
OpenWifiActivityCollector.addActivity(this);
btn_sure.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
DeviceInfoUtil.openWifiSetting(getApplicationContext());
finish();
}
});
btn_cancel.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
finish();
}
});
}
@Override
protected void onDestroy() {
super.onDestroy();
// 从管理类中移除实例
OpenWifiActivityCollector.removeActivity(this);
}
}
OpenWifiActivityCollector
/**
* <pre>
* author : 杨丽金
* time : 2018/06/05
* desc : 管理OPENWiFiActivity实例
* </pre>
*/
public class OpenWifiActivityCollector {
public static List<Activity> sActivities = new ArrayList<>();
public static void addActivity(Activity activity) {
sActivities.add(activity);
}
public static void removeActivity(Activity activity) {
sActivities.remove(activity);
}
public static void finishAll() {
for (Activity activity : sActivities) {
if (!activity.isFinishing()) {
activity.finish();
}
}
}
}
WifiListenerBroadcast
public class WifiListenerReceiver extends BroadcastReceiver {
public static final String MY_WIFI_BROADCAST="MY_WIFI_BROADCAST";
@Override
public void onReceive(Context context, Intent intent) {
String action=intent.getAction();
if (WifiManager.WIFI_STATE_CHANGED_ACTION.equals(action) || Constant.WIFI_LISTENER_ACTION.equals(action)) {
int wifiState = DeviceInfoUtil.getWifiState(context);
Log.e("LoginActivity", "收到wifi广播"+wifiState);
switch (wifiState) {
case WifiManager.WIFI_STATE_DISABLED:
case WifiManager.WIFI_STATE_DISABLING:
case WifiManager.WIFI_STATE_UNKNOWN:
/*
* wifi处于关闭状态:若“请打开wifi对话框”正在显示,将该对话框显示在前台;
* 未正在显示:创建新的并显示
*/
Intent intent1 = new Intent(context, OpenWifiActivity.class);
// 以SingleTask的模式启动(栈内复用)
intent1.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(intent1);
break;
case WifiManager.WIFI_STATE_ENABLED:
case WifiManager.WIFI_STATE_ENABLING:
/*
* wifi处于开启状态:若“请打开wifi对话框”正在显示,将该对话框关闭;
* 未正在显示:Nothing
*/
OpenWifiActivityCollector.finishAll();
break;
}
}
}
}
网友评论