Android全局性的Dialog

有时候,一个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。

如果还有其他方法,欢迎大家分享!


评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值