Android任务管理器

时间:2022-09-04 14:20:54

最近参考系统源代码,做了一个任务管理器。具体功能是获取用户的任务列表、活动图标、Activity的缩略图以及恢复任务、关闭任务。

完整的demo已上传到github,代码拙劣,将就看看:https://github.com/Ade8018/TaskManager

首先声明,任务管理器基本上的功能都会要求系统级权限。即你手中需要有系统签名文件。

以下代码在4.4.2及5.1.1系统上亲测可用。


一、获取任务列表

获取任务列表需要系统使用系统UIDandroid:sharedUserId="android.uid.system"及添加权限<uses-permission android:name="android.permission.GET_TASKS" />

然后调用ActivityManager的getRecentTasks(MAX_TASK_COUNT,ActivityManager.RECENT_IGNORE_UNAVAILABLE)方法可以获取到任务列表。

示例:

public TaskList(ActivityManager am, PackageManager pm) {
if (am == null || pm == null)
throw new NullPointerException();
mAm = am;
mPm = pm;
mInfos = am.getRecentTasks(MAX_TASK_COUNT,
ActivityManager.RECENT_IGNORE_UNAVAILABLE);
dofilter();
}


二、获取活动图标

ActivityInfo类中有个loadIcon方法可以获取图标。而通过PackageManager中则有getActivityInfo可以根据组件名获取ActivityInfo。RecentTask中baseIntent.getComponent()可以获取到组件名。这样我们就可以根据任务列表获取活动的图标。

示例:

<span style="white-space:pre"></span>public ComponentName getBaseActivityByIndex(int index) {
return mInfos.get(index).baseIntent.getComponent();
}

public Drawable getIconDrawable(int index) {
ComponentName cn = getBaseActivityByIndex(index);
try {
return mPm.getActivityInfo(cn, PackageManager.GET_INTENT_FILTERS)
.loadIcon(mPm);
} catch (NameNotFoundException e) {
return null;
}
}

三、获取Activity缩略图

此功能需要权限:<uses-permission android:name="android.permission.READ_FRAME_BUFFER" />

4.4.2版本与5.1.1版本的获取方法不同。分别如下:

4.4.2:

<span style="white-space:pre"></span>public static Bitmap getTaskTopThumbnail(Context context,int persistentTaskId) {
try {
Method method_getTaskTopThumbnail = ActivityManager.class
.getDeclaredMethod("getTaskTopThumbnail", int.class);
method_getTaskTopThumbnail.setAccessible(true);
return (Bitmap) method_getTaskTopThumbnail.invoke(
context.getSystemService(Context.ACTIVITY_SERVICE),
persistentTaskId);
} catch (NoSuchMethodException | IllegalAccessException
| IllegalArgumentException | InvocationTargetException e) {
e.printStackTrace();
}
return null;
}
5.1.1:

<span style="white-space:pre"></span>public static Bitmap getThumbnail(ActivityManager activityManager,int persistentTaskId) {
Bitmap thumbnail = null;
try {
Class cls_TaskThumbnail = Class
.forName("android.app.ActivityManager$TaskThumbnail");
Method m_getTaskThumbnail = ActivityManager.class
.getDeclaredMethod("getTaskThumbnail", int.class);
m_getTaskThumbnail.setAccessible(true);
Object obj_TaskThumbnail = m_getTaskThumbnail.invoke(
activityManager, persistentTaskId);
if (obj_TaskThumbnail == null)
return null;
Field f_mainThumbnail = cls_TaskThumbnail.getField("mainThumbnail");
Field f_thumbnailFileDescriptor = cls_TaskThumbnail
.getField("thumbnailFileDescriptor");
thumbnail = (Bitmap) f_mainThumbnail.get(obj_TaskThumbnail);
ParcelFileDescriptor descriptor = (ParcelFileDescriptor) f_thumbnailFileDescriptor
.get(obj_TaskThumbnail);
if (thumbnail == null && descriptor != null) {
thumbnail = BitmapFactory.decodeFileDescriptor(
descriptor.getFileDescriptor(), null, sBitmapOptions);
}
if (descriptor != null) {
try {
descriptor.close();
} catch (IOException e) {
}
}
} catch (Exception e) {
}
return thumbnail;
}
两个方法中需要的persistentTaskId参数都是RecentTask类中的属性persistentTaskId。


四、移除任务(移除后就不能再在任务列表中获取到这个活动)

此功能需要权限:<uses-permission android:name="android.permission.REMOVE_TASKS" />

4.4.2:

<span style="white-space:pre"></span>public static boolean removeTask(ActivityManager am, int taskId, int flags) {
try {
Method method_removeTask = ActivityManager.class.getDeclaredMethod(
"removeTask", int.class, int.class);
method_removeTask.setAccessible(true);
return (boolean) method_removeTask.invoke(am, taskId, flags);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
5.1.1:

<span style="white-space:pre"></span>public static boolean removeTask(ActivityManager am, int taskId) {
try {
Method method_removeTask = ActivityManager.class.getDeclaredMethod(
"removeTask", int.class);
method_removeTask.setAccessible(true);
return (boolean) method_removeTask.invoke(am, taskId);
} catch (Exception e) {
e.printStackTrace();
}
return false;
}
以上两个方法中的taskId都是RecentTask类中的属性--id。


五、恢复任务

此功能需要权限:<uses-permission android:name="android.permission.REORDER_TASKS" />

参考源码得知,系统采用的方法是:如果该任务还没别杀掉,则恢复该任务即将该任务从后台移动到前台。如果该任务已经被杀掉了,就重新启动该任务。当该任务的id<=0的时候表示该任务已经被傻掉了。方法如下:

<span style="white-space:pre"></span>public void resumeTask(Context context, int position) {
if (mInfos.get(position).id > 0) {
mAm.moveTaskToFront(getPersistentIdByIndex(position), 0);
} else {
Intent intent = mInfos.get(position).baseIntent;
intent.addFlags(Intent.FLAG_ACTIVITY_LAUNCHED_FROM_HISTORY
| Intent.FLAG_ACTIVITY_TASK_ON_HOME
| Intent.FLAG_ACTIVITY_NEW_TASK);
try {
context.startActivity(intent);
} catch (Exception e) {
}
}
}