Android以後臺服務判斷本應用Activity是否處於棧頂

在Android開發中,咱們常常想知道是否本身的服務處於後臺運行中,由於在後臺運行的服務器優先級會下降,也就極有可能會被系統給回收掉,有什麼好辦法呢?Google推薦咱們將服務運行到前臺,如何知道服務是否處於後臺運行呢?能夠經過獲取堆棧信息中棧頂的Activity是否爲本應用便可。java

1。下面是關健部分代碼:android

(記得加上權限:<uses-permission android:name="android.permission.GET_TASKS"/>)服務器

mPackageName爲本應用包名,mActivityManager爲Activity管理對象app

 

mActivityManager = ((ActivityManager) getSystemService(Context.ACTIVITY_SERVICE));函數

mPackageName = getPackageName();post

 

	public boolean isAppOnForeground() {
		List<RunningTaskInfo> tasksInfo = mActivityManager.getRunningTasks(1);
		if (tasksInfo.size() > 0) {
			L.i("top Activity = "
					+ tasksInfo.get(0).topActivity.getPackageName());
			// 應用程序位於堆棧的頂層
			if (mPackageName.equals(tasksInfo.get(0).topActivity
					.getPackageName())) {
				return true;
			}
		}
		return false;
	}


2。下面又會有一個新問題,咱們何時調用這個函數呢?有兩個辦法,一個是主動,一個是被動,this

 

①.主動辦法:在服務中開啓一個線程,每隔一段時間調用一下這個函數便可。spa

②.被動辦法:自定義一個BaseActivity繼承Activity,而後在onPause函數中回調通知一下服務中的此函數,而後應用中的每一個Activity都繼承BaseActivity,便可知道棧頂中是否還有本應用的Activity。線程


3.當咱們知道棧頂中的Activity不是本應用的了,咱們的服務也就相應的下降了優先級,也就說系統須要內存的時候,首先就會回收此服務消耗的內存。此時,咱們只需將服務設置爲前臺運行便可:code

①.設置爲前臺:第一個參數是通知ID,第二個參數是Notification對象

startForeground(SERVICE_NOTIFICATION, n);

②.中止前臺服務可調用:true表明清除通知欄

stopForeground(true);

 

public void updateServiceNotification(String message) {
		if (!PreferenceUtils.getPrefBoolean(this,
				PreferenceConstants.FOREGROUND, true))
			return;
		String title = PreferenceUtils.getPrefString(this,
				PreferenceConstants.ACCOUNT, "");
		Notification n = new Notification(R.drawable.login_default_avatar,
				title, System.currentTimeMillis());
		n.flags = Notification.FLAG_ONGOING_EVENT | Notification.FLAG_NO_CLEAR;

		Intent notificationIntent = new Intent(this, MainActivity.class);
		notificationIntent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
		n.contentIntent = PendingIntent.getActivity(this, 0,
				notificationIntent, PendingIntent.FLAG_UPDATE_CURRENT);

		n.setLatestEventInfo(this, title, message, n.contentIntent);
		startForeground(SERVICE_NOTIFICATION, n);
	}

	// 判斷程序是否在後臺運行的任務,其實我的以爲這個辦法並不太好,
	Runnable monitorStatus = new Runnable() {
		public void run() {
			try {
				L.i("monitorStatus is running... " + mPackageName);
				mMainHandler.removeCallbacks(monitorStatus);
				// 若是在後臺運行而且鏈接上了
				if (!isAppOnForeground()) {
					L.i("app run in background...");
					// if (isAuthenticated())//不判斷是否鏈接上了。
					updateServiceNotification(getString(R.string.run_bg_ticker));
					return;// 服務已在前臺運行,能夠中止重複執行此任務
				} else {
					stopForeground(true);
				}
				mMainHandler.postDelayed(monitorStatus, 1000L);
			} catch (Exception e) {
				e.printStackTrace();
				L.i("monitorStatus:"+e.getMessage());
			}
		}
	};


 

OK,以上僅是本人的一點心得體會,可能有不正確的地方,請你們甄別使用,謝謝!

相關文章
相關標籤/搜索