有时候,一个APP要求同时只能登陆一在一台设备,就如同QQ一样,当有其他人登你的qq时,你自己的app就会弹出一个对话,并提示你重新登录,就如下图所示:
因为在弹出这个对话框时,用户所在的Activity是不一定的,然而我们也不可能在每一个Activity都new一个新的AlertDialog,这样操作很不现实。最近的公司项目要求实现这个功能,在网上翻了翻大都写的不详细,因此便自己写了一个。同时也遇到了一个问题。
方法一:谈到全局性的dialog,大家第一反应,肯定是使用service,通过service来检测是否需要弹窗。
加入权限 <span style="color:#FF0000;"><uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/></span>
public class LoginCheckService extends Service{
Handler handler;
Runnable runnable;
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onCreate() {
super.onCreate();
final MyAlertDialog remindDialog = new MyAlertDialog(this, R.style.MyAlertDialog, "提醒",
String.format("您的账号%s已绑定在其他设备上,将在此设备上自动注销!", App.Cellphone));
remindDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
remindDialog.setTitleColor(getResources().getColor(R.color.black));
remindDialog.setSingleSelect();
remindDialog.setOKBtn(new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
}
});
handler = new Handler();
runnable = new Runnable() {
@Override
public void run() {
if(App.NeedOffLine){
if(!remindDialog.isShowing()){
remindDialog.show();
}
}
handler.postDelayed(runnable, 500);
}
};
handler.post(runnable);
}
}
上面的代码很简单,其实就是一个service,每隔5秒通过全局变量App.NeedOffLine来判断一下是否需要弹出窗口。
最关键的部分便是:
<uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
remindDialog.getWindow().setType(WindowManager.LayoutParams.TYPE_SYSTEM_ALERT);
这句话是为了使dialog获取系统优先级,需要申请权限。
但是,实际使用的时候发现使用service弹出dialog的方式在小米手机和三星上并不能实现,而需要其开启悬浮窗功能才能这些,这样是不能满足我们的要求的,因此我便想出了方法二:使用BroadcastReceiver实现。
方法二:使用BroadcastReceiver实现:
这个方法需要我们实现一个基类BaseActivity,以后每个新的Activity都继承BaseActivity,这样就不需要在每个Activity都写一个广播。
public class BaseActivity extends Activity{
DialogReceiver dialogReceiver;
MyAlertDialog remindDialog;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
remindDialog = new MyAlertDialog(this, R.style.MyDialogTheme);
dialogReceiver = new DialogReceiver();
}
class DialogReceiver extends BroadcastReceiver{
@Override
public void onReceive(Context context, Intent intent) {
if(!remindDialog.isShowing()){
remindDialog.show();
}
}
}
@Override
protected void onResume() {
IntentFilter filter = new IntentFilter("com.fooww.soft.android.Presentation.LoginCheck");
registerReceiver(dialogReceiver, filter);
super.onResume();
}
@Override
protected void onPause() {
unregisterReceiver(dialogReceiver);
super.onStop();
}
}
其实这个方法的关键便在于,在onResume中注册广播,在onPause中便解绑。一开始我并没有这么做,发现,每启动一个Activity便注册一个新的广播,而每个广播的名字又是一样的,这样广播便产生了冲突,导致APP报错。于是,我便这么写了。每次进入一个Activity在onResume中注册广播,当进入另一个Activity的时候,将后台的Activity解绑,也就是onPause中解绑,新的前台Activity中注册了新的广播,这样广播便会一直保存,并且有且只有一个,满足了我们需求。因此,一旦接收到要弹出dialog的广播信息,前台总有一个广播在接受,并弹出dialog。
如果还有其他方法,欢迎大家分享!