需求背景
根据客户需求,需要提供一个一键结束所有应用并排除白名单的功能,效果类似 Android SystemUI 里「近期任务」界面的清理/结束任务按钮:
点击后清空近期任务,但对于指定的白名单应用,需要继续保持运行,不被杀掉。
在网上搜索后,并没有找到现成可用的实现方案,只能基于源码自行实现。
实现原理
既然 SystemUI 自身已经有「清理近期任务」的功能,就说明系统内部一定已经提供了相关接口,只是没有对外暴露。
通过调试 frameworks/base/packages/SystemUI 源码,可以看到:当按下近期任务按钮、执行清理操作时,会调用:
SystemServicesProxy#getRecentTasks(...):获取近期任务列表
- 最终通过
ActivityManager.removeTask(int taskId) 来真正清理任务
思路就很明确了:
- 复用
SystemServicesProxy#getRecentTasks(...) 拿到当前所有近期任务列表;
- 根据白名单列表,将需要保留的应用从任务列表中移除;
- 对剩余任务逐个调用
ActivityManager.removeTask(...),完成清理。
为方便在系统中统一调用,这里通过自定义广播的方式来触发清理逻辑。
新增广播 KillProcessesReceiver
在 frameworks/base/packages/SystemUI/src/com/android/systemui/receiver/ 下新增文件:
KillProcessesReceiver.java
示例代码如下(去掉了多余的高亮标签,保留核心逻辑):
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
| package com.android.systemui.receiver;
import android.app.ActivityManager; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; import android.os.UserHandle; import android.util.ArraySet; import android.util.Log;
import com.android.systemui.recents.Recents; import com.android.systemui.recents.misc.SystemServicesProxy;
import java.util.ArrayList; import java.util.Iterator; import java.util.List;
public class KillProcessesReceiver extends BroadcastReceiver {
public static final String ACTION = "con.yt.kill.processes"; private static final String TAG = "recent";
@Override public void onReceive(Context context, Intent intent) { if (!ACTION.equals(intent.getAction())) { return; }
PackageManager pm = context.getPackageManager(); ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
try { SystemServicesProxy ssp = Recents.getSystemServices(); int currentUserId = UserHandle.USER_CURRENT;
List<ActivityManager.RecentTaskInfo> tasks = ssp.getRecentTasks( ActivityManager.getMaxRecentTasksStatic(), currentUserId, false, new ArraySet<>() );
if (tasks == null || tasks.size() == 0) { Log.e(TAG, "tasks Empty"); return; }
ArrayList<String> whiteApp = intent.getStringArrayListExtra("whiteApp");
if (whiteApp != null && !whiteApp.isEmpty()) { Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator(); while (iter.hasNext()) { ActivityManager.RecentTaskInfo t = iter.next(); for (String s : whiteApp) { if (s.equals(t.realActivity.getClassName()) || s.equals(t.realActivity.getPackageName())) { iter.remove(); Log.i(TAG, "package is in white list, id=" + t.id + ", package=" + s); break; } } } }
if (tasks.size() == 0) { Log.e(TAG, "tasks Empty"); return; }
Iterator<ActivityManager.RecentTaskInfo> iter = tasks.iterator(); while (iter.hasNext()) { ActivityManager.RecentTaskInfo t = iter.next(); Log.i(TAG, "RecentTaskInfo stackId: " + t.stackId + ", baseActivity: " + t.baseActivity);
am.removeTask(t.persistentId); } } catch (Exception e) { Log.e(TAG, "Failed to get recent tasks", e); } } }
|
核心逻辑说明:
- 通过
Recents.getSystemServices() 拿到 SystemServicesProxy;
- 调用
getRecentTasks(...) 获取当前用户的所有近期任务;
- 从 Intent 中取出白名单列表
whiteApp,按包名 / 类名过滤;
- 对过滤后的任务使用
ActivityManager#removeTask(persistentId) 逐个移除。
注册广播(SystemUI AndroidManifest.xml)
文件位置:
frameworks/base/packages/SystemUI/AndroidManifest.xml
在 application 节点中增加广播注册(示例):
1 2 3 4 5 6 7
| <receiver android:name=".receiver.KillProcessesReceiver" android:exported="false"> <intent-filter> <action android:name="con.yt.kill.processes" /> </intent-filter> </receiver>
|
保护广播(系统 AndroidManifest.xml)
文件位置:
frameworks/base/core/res/AndroidManifest.xml
为防止普通应用随意发送该广播,需要将其声明为受保护广播:
1
| <protected-broadcast android:name="con.yt.kill.processes" />
|
这样,只有具有系统权限的组件才能正常发送此广播。
调用方式示例
上层只需要构造相应的 Intent,并携带白名单列表即可。例如:
1 2 3 4 5 6 7 8
| public static final String ACTION_KILL_PROCESSES = "con.yt.kill.processes";
@Override public void killBackgroundProcesses(Context context, ArrayList<String> whiteApp) { Intent intent = new Intent(ACTION_KILL_PROCESSES); intent.putStringArrayListExtra("whiteApp", whiteApp); context.sendBroadcast(intent); }
|
其中:
whiteApp:白名单列表,可填入包名或具体 Activity 类名;
- 不在白名单中的近期任务,会被统一通过
removeTask(...) 清理掉。
至此,就实现了在 Android 7 平台上,一键清理近期任务且保留白名单应用的系统级方案。
本文链接:
http://longzhiye.top/2025/11/23/2025-11-23/