今天被小程序刷屏了^^ 我也來湊湊熱鬧.
談談微信是怎么實現(xiàn)在任務列表中顯示"小程序"的.
效果
微信中打開了"滴滴(小程序)"后,
可以看到,任務列表不僅顯示了"微信", 還顯示了"滴滴(小程序)"的人口.
通過這個入口,就可以很方面的切換小程序了, 體驗和原生程序也一樣一樣的.
分析
下面簡單分析一下他的實現(xiàn).
1.Android系統(tǒng)中,顯示最近程序列表的View是 RecentsPanelView
.
他通過 refreshRecentTasksList()
加載程序列表,我們來看看代碼:
可以看到 RecentTasksLoader mRecentTasksLoader
負責真正處理數(shù)據(jù)加載.
RecentsPanelView.java
private RecentTasksLoader mRecentTasksLoader; * * * private void refreshRecentTasksList( ArrayList<TaskDescription> recentTasksList, boolean firstScreenful) { if (mRecentTaskDescriptions == null && recentTasksList != null){ onTasksLoaded(recentTasksList, firstScreenful); } else { //加載最近的列表 mRecentTasksLoader.loadTasksInBackground(); } }
2.順著看看RecentTasksLoader的實現(xiàn):
這里可以清楚看到,加載的數(shù)據(jù)是 ActivityManager.getRecentTasks()
.
也就是說顯示的是Task列表.
RecentTasksLoader.java
ArrayList<TaskDescription> getRecentTasks() { cancelLoadingThumbnails(); ArrayList<TaskDescription> tasks = new ArrayList<TaskDescription>(); final PackageManager pm = mContext.getPackageManager(); final ActivityManager am = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE); //獲取最近的Task final List<ActivityManager.RecentTaskInfo> recentTasks = am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE); * * * return tasks; }
到這里,已經(jīng)很清楚了. 要顯示"小程序"入口, 只需要新建一個Task啟動就好了~
是不是很簡單啊.
來來來驗證一下我們的想法.
這里使用 adb shell dumpsys activity activities
查看一下Task狀態(tài)
1. 只開啟微信
2. 開啟小程序
如下圖所示, 微信新開啟了一個.AppBrandUI的task棧

實現(xiàn)
知道原理,實現(xiàn)就很簡單了.
假設(shè)小程序的Activity是 TaskTestActivity,整個實現(xiàn)分兩步:
1. AndroidManifest.xml中為Activity設(shè)置taskAffinity
<activity android:icon="@drawable/didi" android:name=".TaskTestActivity" android:label="小程序測試" android:taskAffinity=".NewTask" />
2. 以NEW_TASK方式啟動Activity
//以Intent.FLAG_ACTIVITY_NEW_TASK方式啟動Activity Intent intent = new Intent(this, TaskTestActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK); startActivity(intent);
為什么要設(shè)置taskAffinity呢,
這和 FLAG_ACTIVITY_NEW_TASK
的特性有關(guān):
FLAG_ACTIVITY_NEW_TASK:設(shè)置此狀態(tài),首先會查找是否存在和被啟動的Activity具有相同的taskAffinity的task(注意同一個應用程序中默認所有activity 的taskAffinity是一樣的),如果有,剛直接把這個棧整體移動到前臺,并保持棧中的狀態(tài)不變,即棧中的activity順序不變,如果沒有,則新建一個棧來存放被啟動的activity.
也就是說,如果App已經(jīng)啟動,即使用 FLAG_ACTIVITY_NEW_TASK
新起Activity, 因為taskAffinity相同,也會被壓到一個task中, 自然recent panel 就看不到兩個入口了.
所以我們需要為小程序設(shè)置一個新的taskAffinity
下面是demo效果
拓展
讓自己的程序不顯示在任務列表中
有時候我們做一個工具, 或者后臺界面, 不希望顯示在程序列表中.
也很簡單,只要設(shè)置task的屬性就好了
方法1:
在AndroidManifest.xml設(shè)置Activity的 android:excludeFromRecents
為true
<activity android:excludeFromRecents="true" android:icon="@drawable/didi" android:name=".TaskTestActivity" android:label="小程序測試" />
方法2:
在啟動Activity的時候加上 Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS
FLAG
//Activity不顯示在recent列表中. Intent intent = new Intent(this, TaskTestActivity.class); intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS); startActivity(intent);