【Android 基础】任务列表上小程序独立显示原理浅析

Android小程序独立显示任务列表解析
本文分析了微信小程序在任务列表中独立显示的原理,指出小程序通过设置FLAG_ACTIVITY_NEW_TASK和taskAffinity实现类似独立应用的效果。通过修改AndroidManifest.xml和启动Activity的方式,可以控制程序是否出现在任务列表。

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

如下:

这里写图片描述

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

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

点击“开启一个小程序吧”按钮,就打开了新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(注意同一个应用程序中默认所有activity 的taskAffinity是一样的)。如果有,就直接把这个栈整体移动到前台,并保持栈中的状态不变,即栈中的activity顺序不变,如果没有,则新建一个栈来存放被启动的activity.
也就是说,如果App已经启动,即使用FLAG_ACTIVITY_NEW_TASK新启动一个Activity, 因为taskAffinity默认相同,也会被压到一个task中, 自然recent panel 就看不到两个入口了.
要实现预设的效果还需要为目标activity设置一个参数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介绍

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值