Android 一键清除后台进程实现详解

一、Android多功能键功能概述:

在每个APP打开后会创建新的进程并运行,同时在SystemUI中存在taskList,将打开的应用存储在tasklist中,在打开多功能键时,便会展示出来。
要实现一键清理历史任务功能:

  1. 一方面清除tasklist中的数据,
  2. 另一方面依据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);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值