zoukankan      html  css  js  c++  java
  • 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();  
            }  
        }  
    } 
  • 相关阅读:
    python ddt 传多个参数值示例
    Appium 输入 & 符号,实际输入&-
    curl 调用jenkins的api
    Android WebView的Js对象注入漏洞解决方案
    Could not find com.android.tools.build:gradle:1.3.0.
    react-native疑难
    win上搭建react-native android环境
    gradle大体内容
    android studio This client is too old to work with the working copy at
    sharedPreference
  • 原文地址:https://www.cnblogs.com/Free-Thinker/p/4580617.html
Copyright © 2011-2022 走看看