程序员人生 网站导航

任务列表上小程序独立显示原理浅析

栏目:综合技术时间:2017-03-18 08:17:37

在1月9号晚体验了小程序以后,我使用魅族手机清除当前已开启的利用(多任务列表)的时候,我惊奇发现小程序竟然“独立”于微信有自己的“生命周期”。

以下:

这里写图片描述

图中的 查地铁,摩拜单车 都是开启的小程序。这样的效果是否是和独立的app1样呢!我是觉得简直1模1样!

出于好奇,查阅相干资料(见文末参考文献)
初步分析以下:
小程序和微信就是显示在系统的任务列表也就是开启的任务缩略图那里,如上图列出的就是最近启动过的任务缩略图。那末研究思路就有了:找出这个缩略图的构成进程就可以找到答案了。其中有两个重要的类以下:
// Recent apps

private RecentsPanelView mRecentsPanel;
private RecentTasksLoader mRecentTasksLoader;

RecentTasksLoader.java 部分代码以下


        // return a snapshot of the current list of recent apps  
    ArrayList<TaskDescription> getRecentTasks() {  
        cancelLoadingThumbnails();  

        ArrayList<TaskDescription> tasks = new ArrayList<TaskDescription>();  
        final PackageManager pm = mContext.getPackageManager();  
        final ActivityManager am = (ActivityManager)  
                mContext.getSystemService(Context.ACTIVITY_SERVICE);  

        final List<ActivityManager.RecentTaskInfo> recentTasks =  
                am.getRecentTasks(MAX_TASKS, ActivityManager.RECENT_IGNORE_UNAVAILABLE);  

        ActivityInfo homeInfo = new Intent(Intent.ACTION_MAIN).addCategory(Intent.CATEGORY_HOME)  
                    .resolveActivityInfo(pm, 0);  

        HashSet<Integer> recentTasksToKeepInCache = new HashSet<Integer>();  
        int numTasks = recentTasks.size();  

        // skip the first task - assume it's either the home screen or the current activity.  
        final int first = 1;  
        recentTasksToKeepInCache.add(recentTasks.get(0).persistentId);  
        for (int i = first, index = 0; i < numTasks && (index < MAX_TASKS); ++i) {  
            final ActivityManager.RecentTaskInfo recentInfo = recentTasks.get(i);  

            TaskDescription item = createTaskDescription(recentInfo.id,  
                    recentInfo.persistentId, recentInfo.baseIntent,  
                    recentInfo.origActivity, recentInfo.description, homeInfo);  

            if (item != null) {  
                tasks.add(item);  
                ++index;  
            }  
        }  

        // when we're not using the TaskDescription cache, we load the thumbnails in the  
        // background  
        loadThumbnailsInBackground(new ArrayList<TaskDescription>(tasks));  
        return tasks;  
    }  

缩略图的核心获得方法:

RecentsPanelView.java 中 调用
refreshRecentTasksList(recentTaskDescriptions);
而终究得调用getRecentTasks()方法
mRecentTaskDescriptions = mRecentTasksLoader.getRecentTasks();

通过源码分析,不难得出Android系统中,显示最近程序列表的View是 RecentsPanelView类,通过refreshRecentTasksList()方法加载程序列表,其中RecentTasksLoader 负责最后的加载.
分析到这里,已明白是怎样回事了,小程序其实不是完全和微信独立(只是看起来独立了).”小程序”要实现和独立app那样有独立的任务缩略图(也就是入口), 只需要把目标activity设置为 新Task 方式启动就能够了。

演示demo

点击“开启1个小程序吧”按钮,就打开了新activity(小程序),去任务列表中查看,果然假想以下图所示。
这里写图片描述

如何实现:

实现上面的效果,只是需要两步:
1. AndroidManifest.xml中为 目标Activity 设置taskAffinity

  <activity android:name=".MiniActivity"
                  android:label="小程序"
                  android:taskAffinity=".NewTask">
        </activity>

2.以NEW_TASK方式启动Activity

    @Override
    public void onClick(View v) {
        Intent intent = new Intent(MainActivity.this,MiniActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        startActivity(intent);
    }

ps:原来开启的小程序都在新的task里面而已

FLAG_ACTIVITY_NEW_TASK的介绍:

设置此状态,首先会查找是不是存在和被启动的Activity具有相同的taskAffinity的task(注意同1个利用程序中默许所有activity 的taskAffinity是1样的)。如果有,就直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建1个栈来寄存被启动的activity.
也就是说,如果App已启动,即便用FLAG_ACTIVITY_NEW_TASK新启动1个Activity, 由于taskAffinity默许相同,也会被压到1个task中, 自然recent panel 就看不到两个入口了.
要实现预设的效果还需要为目标activity设置1个参数taskAffinity=“.NewTask”,简单的说就是设置(新建)该activity自己的启动方式。

如何让你的程序不出现在任务列表呢?

目前有两种方式:
1.在AndroidManifest.xml目标Activity添加 android:excludeFromRecents属性:

  android:excludeFromRecents="true"

2.在启动Activity的时候设置FLAG: Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS

intent.setFlags(Intent.FLAG_ACTIVITY_EXCLUDE_FROM_RECENTS);

参考文献:
1.系统UI介绍
2.关于如何让利用程序不显示在“最近利用程序”的列表中
3.taskAffinity介绍

------分隔线----------------------------
------分隔线----------------------------

最新技术推荐