Android 實現微信,QQ的程式前後臺切換 back鍵切換後臺 點選通知欄恢復前臺
實現類似微信,QQ的前後臺切換:back鍵切換後臺;點選通知欄恢復前臺。
1、back鍵切換後臺的實現:
這個實現需要在主activity重寫onbackpressed()方法。程式碼如下:
@Override public void onBackPressed() { Intent intent= new Intent(Intent.ACTION_MAIN); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); intent.addCategory(Intent.CATEGORY_HOME); startActivity(intent); }
實現原理其實很簡單,本來系統按back鍵的話是會destroy activity的,在這裡,我們重寫,改為使用intent啟動HOME桌面public static final String CATEGORY_HOME:
This is the home activity, that is the first activity that is displayed when the device boots. Constant Value: "android.intent.category.HOME"
谷歌的官方文件寫的很清楚,這會啟動home activity,也就是手機的桌面程式。這樣,我們應用的主activity不會destroy,而只是stop。實現了按home鍵相同的效果。
2、點選通知欄恢復前臺:
在我們收到訊息時,會在通知欄顯示訊息,並且點選通知欄訊息後,程式可以切換到前臺。下面是程式的結構:
程式結構如上圖所示:MainActivity為主Activity,類似於微信,QQ的主介面;ShowPushActivity顯示訊息內容,類似於微信,QQ的聊天activity;MyApplication繼承Application,實現通知欄的顯示等操作;BringToFrontReceiver接受通知欄廣播,將程式切換至前臺。
/** * Created by neal on 2014/11/18. */public class MyApplication extends Application { @Override public void onCreate() { super.onCreate(); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(this) .setSmallIcon(R.drawable.ic_launcher) .setContentTitle("QQ") .setContentText("您收到了一條新訊息"); Intent intent=new Intent(BringToFrontReceiver.ACTION_BRING_TO_FRONT); mBuilder.setContentIntent(PendingIntent.getBroadcast(getApplicationContext(), 0, intent, PendingIntent.FLAG_UPDATE_CURRENT)); mBuilder.setAutoCancel(true); NotificationManager mNotificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); // mId allows you to update the notification later on. Notification notification=mBuilder.build(); mNotificationManager.notify(1, notification); }}
上述程式碼實現應用啟動後通知欄的顯示,使用者點選後傳送廣播到BringToFrontReceiver。模擬收到push訊息。如果我們只是單純的實現此時將程式切換到前臺,我自己想出如下兩種實現方式:
1、利用activitymanager的 moveTaskToFront 方法:
下面是接受到廣播後的程式碼:
public class BringToFrontReceiver extends BroadcastReceiver { public static final String ACTION_BRING_TO_FRONT ="neal.pushtest.action.BringToFront"; public BringToFrontReceiver() { } @Override public void onReceive(Context context, Intent intent) { //獲取ActivityManager ActivityManager mAm = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE); //獲得當前執行的task List<ActivityManager.RunningTaskInfo> taskList = mAm.getRunningTasks(100); for (ActivityManager.RunningTaskInfo rti : taskList) { //找到當前應用的task,並啟動task的棧頂activity,達到程式切換到前臺 if(rti.topActivity.getPackageName().equals(context.getPackageName())) { mAm.moveTaskToFront(rti.id,0); return; } } //若沒有找到執行的task,使用者結束了task或被系統釋放,則重新啟動mainactivity Intent resultIntent = new Intent(context, MainActivity.class); resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP); context.startActivity(resultIntent); }}
<uses-permission android:name="android.permission.GET_TASKS"/> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/> <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"/> <uses-permission android:name="android.permission.REORDER_TASKS"/>
原理就是首先獲取當前應用的task,然後利用moveTaskToFront,將該task切換到前臺。若是沒有活動的task,則重新啟動程式。
但是moveTaskToFront只支援到3.0,那麼3.0一下怎麼實現呢,看方法2
2、自己利用startactivity實現:
除了moveTaskToFront,我們也可以自己利用task與back stack的一些性質來實現,如果對於task與back stack不是特別瞭解,可以看一下我寫的這兩篇文章
下面是接受到廣播後的程式碼:
public class BringToFrontReceiver extends BroadcastReceiver { public static final String ACTION_BRING_TO_FRONT ="neal.pushtest.action.BringToFront"; public BringToFrontReceiver() { } @Override public void onReceive(Context context, Intent intent) { //獲取ActivityManager ActivityManager mAm = (ActivityManager) context.getSystemService(context.ACTIVITY_SERVICE); //獲得當前執行的task List<ActivityManager.RunningTaskInfo> taskList = mAm.getRunningTasks(100); for (ActivityManager.RunningTaskInfo rti : taskList) { //找到當前應用的task,並啟動task的棧頂activity,達到程式切換到前臺 if(rti.topActivity.getPackageName().equals(context.getPackageName())) { try { Intent resultIntent = new Intent(context, Class.forName(rti.topActivity.getClassName())); resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP); context.startActivity(resultIntent); }catch (ClassNotFoundException e) { e.printStackTrace(); } return; } } //若沒有找到執行的task,使用者結束了task或被系統釋放,則重新啟動mainactivity Intent resultIntent = new Intent(context, MainActivity.class); resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP); context.startActivity(resultIntent); }}
許可權
<uses-permission android:name="android.permission.GET_TASKS"/> <uses-permission android:name="android.permission.INTERACT_ACROSS_USERS_FULL"/> <uses-permission android:name="android.permission.GET_TOP_ACTIVITY_INFO"/>
首先獲取當前應用的task,然後獲得task的棧頂activity,也就是最後開啟的activity的名稱,然後啟動它,既可以切換到前臺了。核心是這句話:
resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
因為是singletop,所以activity不會重新建立,而是呼叫onnewintent方法。若是沒有活動的task,則重新啟動程式。這種方法不存在版本相容問題,需要的許可權還要少一個。然而當我們觀察微信,QQ的話,其點選通知欄不僅僅是將程式切換到前臺,而且還會開啟訊息的對話activity。這個實現其實比只是切換到前臺簡單多了:
接收到廣播後的處理:
public class BringToFrontReceiver extends BroadcastReceiver { public static final String ACTION_BRING_TO_FRONT ="neal.pushtest.action.BringToFront"; public BringToFrontReceiver() { } @Override public void onReceive(Context context, Intent intent) { Intent resultIntent = new Intent(context, ShowPushActivity.class); resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP); context.startActivity(resultIntent); }}
假設我們這裡的ShowPushActivity為聊天的activity,那麼只需要啟動這個activity,並且加上flag:resultIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK|Intent.FLAG_ACTIVITY_SINGLE_TOP);就可以實現目的了。這樣ShowPushActivity會在後臺的task啟動,並且會將task帶入前臺。如果已經有一個ShowPushActivity,不會重新建立,而是呼叫onnewintent啟動activity。
通過上面的介紹我們實現了類似微信,QQ的前後臺切換:back鍵切換後臺;點選通知欄恢復前臺。其中恢復前臺提供了兩種方法,是我自己看官方文件,得到的啟發,得到了實現。我覺得只要自己肯於靜下心來研究Android的官方文件很多問題都可以迎刃而解。