1. 程式人生 > >Android 實現微信,QQ的程式前後臺切換 back鍵切換後臺 點選通知欄恢復前臺

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的官方文件很多問題都可以迎刃而解。