一、Android多功能键功能概述:
在每个APP打开后会创建新的进程并运行,同时在SystemUI中存在taskList,将打开的应用存储在tasklist中,在打开多功能键时,便会展示出来。
要实现一键清理历史任务功能:
- 一方面清除tasklist中的数据,
- 另一方面依据packagesname关闭对应的进程两个功能。
public void killBackgroundProcesses(Context mContext){
ActivityManager mActivityManager = (ActivityManager) mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> mTaskInfoList = mActivityManager.getRecentTasks(100, 0);
try {
Method method = Class.forName("android.app.ActivityManager").getMethod("forceStopPackage", String.class);
for (ActivityManager.RecentTaskInfo mTaskInfo : mTaskInfoList) {
method.invoke(mActivityManager, mTaskInfo.baseIntent.getComponent().getPackageName());
ActivityManager.getService().removeTask(mTaskInfo.persistentId);
}
} catch (Exception e){
e.printStackTrace();
}
}
二、相关的实现接口
2.1killBackgroundProcess(packagename name)函数
该函数为Activitymanager类下的函数,其作用为依据packagename结束传入该函数的进程;
一般使用流程如下:
1.在androidmainfest.xml文件中添加如下权限:
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
2.获取正在运行的进程列表
这个方法返回一个runningAppProcessinfo的列表,每个runningAppProcessinfo对象代表一个正在运行的进程。
// 获取所有后台进程
List<ActivityManager.RunningAppProcessInfo> processes = am.getRunningAppProcesses();
3.指定进程的包名
String packageName =“com.”;//要杀死的应用程序的包名
for (ActivityManager.RunningAppProcessInfo process : processes) {
if(process.processName.equals(packageName)){
activityManager.killBackgroundProecss(packageName);
Break;
}
}
4. 依据进程的重要性进行选择结束进程
// 一般情况下,这里不会杀死系统进程,因为系统进程的importance大于或等于Service类
//importance 该进程的重要程度 分为几个级别,数值越低就越重要。
// 一般数值大于RunningAppProcessInfo.IMPORTANCE_SERVICE的进程都长时间没用或者空进程了
// 一般数值大于RunningAppProcessInfo.IMPORTANCE_VISIBLE的进程都是非可见进程,也就是在后台运行着
Log.d("knight", "clearBackgroundProcesses: "+process.processName);
if (process.importance >= ActivityManager.RunningAppProcessInfo.IMPORTANCE_SERVICE) {
// 杀死进程
am.killBackgroundProcesses(process.processName);
}
}
***注:该函数在杀死进程之后会依据系统的调度进行进程的再次启动,所以杀死进程经常无效。可以使用ActivityManager的killBackgroundProcesses方法,需要权限android.permission.KILL_BACKGROUND_PROCESSES。但使用此方法杀死进程后,进程会重启。源码中解释如下:
2.2 forceStopPackage()函数
forceStopPackage并不能被第三方程序调用,只能随系统build。使用条件:
1)权限:
`<uses-permission android:name="android.permission.FORCE_STOP_PACKAGES"/>`
2)只能运行在系统进程:android:sharedUserId="android.uid.system"因为该方法需要配合platform签名一起使用,所以需要在application中加入系统级权限来共享系统进程属性:
android:sharedUserId="android.uid.system"
<application
android:allowBackup="true"
android:icon="@mipmap/ic_launcher"
android:label="@string/app_name"
android:sharedUserId="android.uid.system"
android:roundIcon="@mipmap/ic_launcher_round"
android:supportsRtl="true"
android:theme="@style/AppTheme">
<activity android:name=".MainActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
3)使用反射机制
private void stopAppByForce(Context context , String packageName) {
ActivityManager mActivityManager = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);
Method method = null;
try {
method = Class.forName("android.app.ActivityManager").getMethod("forceStopPackage", String.class);
method.invoke(mActivityManager, packageName);
} catch (Exception e) {
e.printStackTrace();
}
}
经常配合如下的代码进行使用:
/**
* 查询当前进程列表 (含系统应用)
*/
private void queryFilterAppInfo() {
PackageManager pm = this.getPackageManager();
List<ApplicationInfo> appInfos= pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
List<ApplicationInfo> applicationInfos=new ArrayList<>();
Intent resolveIntent = new Intent(Intent.ACTION_MAIN, null);
resolveIntent.addCategory(Intent.CATEGORY_LAUNCHER);
List<ResolveInfo> resolveinfoList = getPackageManager()
.queryIntentActivities(resolveIntent, 0);
Set<String> allowPackages=new HashSet();
for (ResolveInfo resolveInfo:resolveinfoList){
allowPackages.add(resolveInfo.activityInfo.packageName);
}
for (ApplicationInfo app:appInfos) {
String name = app.processName;
// 这里是你需要保留的程序或进程的包名 com.xxx.xxx
if(name.equals("com.xxx.xxx")||
name.equals("com.xxxx.xxxx")) continue;
if((app.flags & ApplicationInfo.FLAG_SYSTEM) <= 0)
{
applicationInfos.add(app);
}
if(app.uid > 10000){
applicationInfos.add(app);
}
if (allowPackages.contains(app.packageName)){
applicationInfos.add(app);
}
}
for (ApplicationInfo applicationInfo : applicationInfos) {
System.out.println(applicationInfo.packageName);
stopAppByForce(this, applicationInfo.packageName);
}
}
在系统中通过mk脚本编译时
5)android.uid.system属性的进程 须要在android.mk里这样设置:
LOCAL_CERTIFICATE := platform
另外,我在实现的时候,有出于这样的考虑:因为我的taskmanager需要进行的操作太多,把它放到system进程里是不是太危险了?于是,我把forceStopPackage部分分离出来,定义到一个service里,仅仅这个service跑在system进程下,我的tm需要关闭程序的时候再去startservice,当service执行完毕后,更新界面。当然,我要先知道service执行完毕。
2.3最近taskactivity进程信息获取
Android系统中,在RecentActivity界面添加“一键删除最近应用列表”按钮,其实现分两个部分:
1.在RecentActivity界面添加一个button,点击该button触发一键删除功能。
2.在button的onclick()方法中,通过调用AMS接口来删除AMS记录的recent list。
通过如下方式来实现:
final ActivityManager am = (ActivityManager)mContext.getSystemService(Context.ACTIVITY_SERVICE);
List<ActivityManager.RecentTaskInfo> recentTasks =am.getRecentTasks(MAX_TASKS, ctivityManager.RECENT_IGNORE_UNAVAILABLE );
for(ActivityManager.RecentTaskInfo rt:recentTasks ) {
if (am != null)
am.removeTask(rt.persistentId,ActivityManager.REMOVE_TASK_KILL_PROCESS);
}