Android基础【1】杀死进程(强行停止)应用程序的方法

写在前面:
进入手机ODM已经很久,经历过几个项目项目下来,对高通、展讯、Marvell平台都进行了接触,对于我个人来说,参与手机系统项目的开发与维护,最明显的好处是可以深入的了解某一功能的具体实现过程,以及Android的设计框架,能够以框架的思维去修改代码添加功能。入行这么久,越来越觉得有必要将自己在实际工作过程中看到的,领悟到的一些东西能够记忆下来,并分享出来。
        从这篇开始我将会筛选出一些常用功能在Google源码中的标准方法与大家一起分享,对于我个人来讲,比较喜欢按照源码中已经存在了的标准方法去coding。


首先共享的是 杀死进程的方法, 一般手机管家类应用最基本的就是清理进程的功能。其实这个功能在源码里面来看是很简单的,主要有两步骤:1.获取正在运行的进程列表;2.根据packageName选择怎样去杀掉。

2015.05.06 更新一种方法,利用反射机制调用ActivityManagerService::forceStopPackage来杀掉进程(适用于usr组,但仍然不一定成功)。

这部分的功能主要参考了
    1. 设置--应用--正在运行--停止所有进程 
    2. 任意界面--长按Home--清理最近进程

设置中获取所用应用程序的做法:
主要使用PackageManager::getInstalledApplications(int flags){} 方法
[java] view plaincopy
final int mRetrieveFlags;  
  
List<ApplicationInfo> mApplications = new ArrayList<ApplicationInfo>();  
  
        // Only the owner can see all apps.  
        if (UserHandle.myUserId() == 0) {  
            mRetrieveFlags = PackageManager.GET_UNINSTALLED_PACKAGES |  
                    PackageManager.GET_DISABLED_COMPONENTS |  
                    PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;  
        } else {  
            mRetrieveFlags = PackageManager.GET_DISABLED_COMPONENTS |  
                    PackageManager.GET_DISABLED_UNTIL_USED_COMPONENTS;  
        }  
        // 获取系统中的所有包  
        <strong>mApplications = mPm.getInstalledApplications(mRetrieveFlags);</strong>  
        if (mApplications == null) {  
            mApplications = new ArrayList<ApplicationInfo>();  
        }  
  
        for (int i=0; i<mApplications.size(); i++) {  
            final ApplicationInfo info = mApplications.get(i);  
            // Need to trim out any applications that are disabled by  
            // something different than the user.  
            if (!info.enabled) { //此处很有必要,获取未被禁止的且允许被操作的包  
                if (info.enabledSetting != PackageManager.COMPONENT_ENABLED_STATE_DISABLED_USER) {  
                    mApplications.remove(i);  
                    i--;  
                    continue;  
                }  
                mHaveDisabledApps = true;  
            }  
        }  

标准方法获取正在运行的进程:
主要使用ActivityManagerService::getRunningAppProcesses(){} 方法
[java] view plaincopy
// Temporary structure used when updating above information.  
final SparseArray<AppProcessInfo> mTmpAppProcesses = new SparseArray<AppProcessInfo>();  
  
  
    // Retrieve list of running processes, organizing them into a sparse  
    // array for easy retrieval.  
    List<ActivityManager.RunningAppProcessInfo> processes  
            = am.getRunningAppProcesses(); // 获取正在运行的进程  
    final int NP = processes != null ? processes.size() : 0;  
    mTmpAppProcesses.clear();  
    for (int i=0; i<NP; i++) {  
        ActivityManager.RunningAppProcessInfo pi = processes.get(i);  
        mTmpAppProcesses.put(pi.pid, new AppProcessInfo(pi));  
    }  

杀死正在运行进程的方法:

适合api LEVEL <= 7
权限 android.permission.RESTART_PACKAGE
[java] view plaincopy
private void killPackage(String pkgName) {  
    ActivityManager am = (ActivityManager)getActivity().getSystemService(  
            Context.ACTIVITY_SERVICE);  
    am.restartPackage(pkgName);  
  
}  

适合api LEVEL >=8
权限 android.permission.KILL_BACKGORUND_PROCESSES
[java] view plaincopy
private void killPackage(String pkgName) {  
    ActivityManager am = (ActivityManager)getActivity().getSystemService(  
            Context.ACTIVITY_SERVICE);  
    am.killBackgroundProcesses(pkgName);  
  
}  


设置--应用--详细--强制停止:
对于非System组进程,无法调用ActivityManager::forceStopPackage(String){}方法,只能尝试使用ActivityManagerService::forceStopPackage(final String packageName, int userId) 并且不一定能成功,设置中的逻辑大致如下:

[java] view plaincopy
private DevicePolicyManager mDpm = (DevicePolicyManager)getActivity().getSystemService(Context.DEVICE_POLICY_SERVICE);  
  
private final BroadcastReceiver mCheckKillProcessesReceiver = new BroadcastReceiver() {  
    @Override  
    public void onReceive(Context context, Intent intent) {  
        updateForceStopButton(getResultCode() != Activity.RESULT_CANCELED);  
    }  
};  
  
private void updateForceStopButton(boolean enabled) {  
    mForceStopButton.setEnabled(enabled);  
    mForceStopButton.setOnClickListener(InstalledAppDetails.this);  
}  
  
private void checkForceStop() {  
    if (mDpm.packageHasActiveAdmins(mPackageInfo.packageName)) {  
        // User can't force stop device admin.  
        updateForceStopButton(false);  
    } else if ((mAppEntry.info.flags&ApplicationInfo.FLAG_STOPPED) == 0) {  
        // If the app isn't explicitly stopped, then always show the  
        // force stop button.  
        updateForceStopButton(true);  
    } else {  
        Intent intent = new Intent(Intent.ACTION_QUERY_PACKAGE_RESTART,  
                Uri.fromParts("package", mAppEntry.info.packageName, null));  
        intent.putExtra(Intent.EXTRA_PACKAGES, new String[] { mAppEntry.info.packageName });  
        intent.putExtra(Intent.EXTRA_UID, mAppEntry.info.uid);  
        intent.putExtra(Intent.EXTRA_USER_HANDLE, UserHandle.getUserId(mAppEntry.info.uid));  
        getActivity().sendOrderedBroadcastAsUser(intent, UserHandle.CURRENT, null,  
                mCheckKillProcessesReceiver, null, Activity.RESULT_CANCELED, null, null);  
    }  
}  
[java] view plaincopy
private void forceStopPackage(String pkgName) {  
    ActivityManager am = (ActivityManager)getActivity().getSystemService(  
            Context.ACTIVITY_SERVICE);  
    am.forceStopPackage(pkgName); // 不一定成功  
    mState.invalidatePackage(pkgName); // 强制停止后重新获取一下包信息  
    ApplicationsState.AppEntry newEnt = mState.getEntry(pkgName);  
    if (newEnt != null) {  
        mAppEntry = newEnt;  
    }  
    checkForceStop(); // 最后检验是否强停成功(体现在“强行停止”按钮是否置灰)  
}  



在调试过程中,强行停止某一进程的方法是:
adb shell  am force-stop <package>
比如: am force-stop com.android.launcher

另外 am kill <package> 安全模式下杀死进程,不影响体验

附:
am force-stop: force stop everything associated with <PACKAGE>.

    --user <USER_ID> | all | current: Specify user to force stop;

        all users if not specified.


am kill: Kill all processes associated with <PACKAGE>.  Only kills.

  processes that are safe to kill -- that is, will not impact the user

  experience.

    --user <USER_ID> | all | current: Specify user whose processes to kill;

        all users if not specified.


am kill-all: Kill all background processes.

第三种方法:
        通过反射机制,杀死进程

[java] view plaincopy
package com.example.androidtest;  
  
import android.app.ActivityManager;  
import android.content.Context;  
  
import java.lang.reflect.InvocationTargetException;  
import java.lang.reflect.Method;  
  
/** 
 * 通过Java的反射机制强制杀死进程 
 * @author hanhao 
 * 
 */  
public class ForceKillProgress {  
      
    public static void forceStopProgress(Context context, String pkgName) {  
        ActivityManager am = (ActivityManager) context.getSystemService(Context.ACTIVITY_SERVICE);  
          
        try {  
            Method forceStopPackage = am.getClass().getDeclaredMethod("forceStopPackage", String.class);  
            forceStopPackage.setAccessible(true);  
            forceStopPackage.invoke(am, pkgName);  
        } catch (NoSuchMethodException e) {  
            e.printStackTrace();  
        } catch (IllegalAccessException e) {  
            e.printStackTrace();  
        } catch (IllegalArgumentException e) {  
            e.printStackTrace();  
        } catch (InvocationTargetException e) {  
            e.printStackTrace();  
        }  
    }  
} 

 

posted @ 2015-06-16 14:04  brave-sailor  阅读(14444)  评论(0编辑  收藏  举报