天天看點

Android全局性的Dialog

有時候,一個APP要求同時隻能登陸一在一台裝置,就如同QQ一樣,當有其他人登你的qq時,你自己的app就會彈出一個對話,并提示你重新登入,就如下圖所示:

Android全局性的Dialog

因為在彈出這個對話框時,使用者所在的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。

如果還有其他方法,歡迎大家分享!