要实现卸载程序、清除数据、停止正在执行的服务这几大模块,如今将代码粗略总结例如以下:

  主要运用到的类有

  PackageManager

  ActivityManager

  ApplicationInfo

  RunningServiceInfo

  Method

  还有两个android.pm下的源文件用于生成桩,IPackageStatsObserver.java
和 IPackageDataObserver.java,由名字能够看出,他们是跟包的状态和大小有关的,在网上找到这两个文件的源代码后,把他们放在projectsrc文件夹下的android.pm包下,自己建包。

  首先要获得系统中已经装了的apk,apk分为两类第一是系统的apk,第二是第三方的apk,所以在获取apk时能够指定一个过滤器,见例如以下代码:

  java代码

  1. // 加入过滤 ,得到所有程序,系统程序,用户自己安装的程序
  2.   private List queryFilterAppInfo(int filter) {
  3.   // 查询全部已经安装的应用程序
  4.   List listAppcations =
  5. pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
  6.   Collections.sort(listAppcations,new
  7. ApplicationInfo.DisplayNameComparator(pm));// 排序
  8.   List appInfos = new ArrayList(); // 保存过滤查到的AppInfo
  9.   // 依据条件来过滤
  10.   switch (filter) {
  11.   case FILTER_ALL_APP: // 全部应用程序
  12.   appInfos.clear();
  13.   for (ApplicationInfo app : listAppcations) {
  14.   if (app.packageName.equals("com.android.appmanager")) { // 过滤自己
  15.   continue;
  16.   }
  17.   appInfos.add(getAppInfo(app));
  18.   }
  19.   return appInfos;
  20.   case FILTER_SYSTEM_APP: // 系统程序
  21.   appInfos.clear();
  22.   for (ApplicationInfo app : listAppcations) {
  23.   if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
  24.   if (app.packageName.equals("com.android.appmanager""font-family:Arial,
  25. Helvetica, sans-serif;">)// wifi { // 过滤自己
  26.   continue;
  27.   }
  28.   appInfos.add(getAppInfo(app));
  29.   }
  30.   }
  31.   return appInfos;
  32.   case FILTER_THIRD_APP: // 第三方应用程序
  33.   appInfos.clear();
  34.   for (ApplicationInfo app : listAppcations) {
  35.   // 非系统程序
  36.   if ((app.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
  37.   if (app.packageName.equals("com.android.appmanager"))
  38.   continue;
  39.   }
  40.   appInfos.add(getAppInfo(app));
  41.   }
  42.   // 本来是系统程序,被用户手动更新后,该系统程序也成为第三方应用程序了
  43.   else if ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)
  44. {
  45.   if (app.packageName.equals("geeya.android.appmanage")) { // 过滤自己
  46.   continue;
  47.   }
  48.   appInfos.add(getAppInfo(app));
  49.   }
  50.   }
  51.   break;
  52.   default:
  53.   return null;
  54.   }
  55.   return appInfos;
  56.   }

复制代码

  AppInfo是我自定义的一个类,里面包括了应用程序的包名、数据区大小、代码区大小、等等一些属性。

  好,如今我们来获取app包的数据区大小、缓存区大小、代码区大小,这里要用反射的机制去获取PackageManager类的隐藏方法getPackageSizeInfo(),这种方法的详细实现是通过回调函数来实现的,这里要用到IPackageStatsObserver这个类生成的桩。

  java代码

  1. // aidl文件形成的Bindler机制服务类
  2.   public class PkgSizeObserver extends IPackageStatsObserver.Stub {
  3.   /***
  4.   * 回调函数,
  5.   *
  6.   * @param pStatus
  7.   * ,返回数据封装在PackageStats对象中
  8.   * @param succeeded
  9.   * 代表回调成功
  10.   */
  11.   @Override
  12.   public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
  13. throws RemoteException {
  14.   long cachesize; // 缓存大小
  15.   long datasize; // 数据大小
  16.   long codesize; // 应用程序大小
  17.   long totalsize; // 总大小
  18.   // System.out.println("data start init!");
  19.   synchronized (Integer.class) {
  20.   cachesize = pStats.cacheSize; // 缓存大小
  21.   datasize = pStats.dataSize; // 数据大小
  22.   codesize = pStats.codeSize; // 应用程序大小
  23.   totalsize = cachesize + datasize + codesize;
  24.   Message msg = mHandler.obtainMessage();
  25.   msg.what = MSG_SIZE_CHANGE;
  26.   Bundle bundle = new Bundle();
  27.   bundle.putLong("cachesize", cachesize);
  28.   bundle.putLong("datasize", datasize);
  29.   bundle.putLong("codesize", codesize);
  30.   bundle.putLong("totalsize", totalsize);
  31.   bundle.putString("packageName", pStats.packageName);
  32.   msg.obj = bundle;
  33.   mHandler.sendMessage(msg);
  34.   }
  35.   }
  36.   }
  37.   //获取每一个apk的大小信息,包含数据区、代码区、缓存区
  38.   // 查询包的大小信息
  39.   public void queryPacakgeSize(String pkgName) throws Exception {
  40.   if (pkgName != null) {
  41.   // 使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
  42.   PackageManager pm = getPackageManager(); // 得到pm对象
  43.   try {
  44.   // 通过反射机制获得该隐藏函数
  45.   Method getPackageSizeInfo =
  46. pm.getClass().getDeclaredMethod("getPackageSizeInfo", String.class,
  47.   IPackageStatsObserver.class);
  48.   getPackageSizeInfo.invoke(pm, pkgName, new PkgSizeObserver());
  49.   } catch (Exception ex) {
  50.   // Log.e(TAG, "NoSuchMethodException");
  51.   ex.printStackTrace();
  52.   throw ex; // 抛出异常
  53.   }
  54.   }
  55.   }

复制代码

  或得到app的大小数据后,封装成消息发送出去,这是最好的方法!!

  这里也介绍一个将long型数据转换成文件大小格式的数据。

  java代码

  1. // 系统函数,字符串转换 long -String (kb)
  2.   private String formateFileSize(long size) {
  3.   return Formatter.formatFileSize(MainActivity.this, size);
  4.   }

复制代码

  好,如今我们来清除用户数据,这里要用到之前下载的那个文件IPackageDataObserver,跟获取app大小一样的,通过回调来实现。

  java代码

  1. // 清除用户数据的操作
  2.   class ClearUserDataObserver extends IPackageDataObserver.Stub {
  3.   public void onRemoveCompleted(final String packageName,final boolean
  4. succeeded) {
  5.   final Message msg = mHandler.obtainMessage();
  6.   if (succeeded) {
  7.   msg.what = CLEAR_USER_DATA;
  8.   } else {
  9.   msg.what = NOT_CLEAR_USER_DATA;
  10.   }
  11.   mHandler2.sendMessage(msg);
  12.   }
  13.   }
  14.   // 清除apk的数据
  15.   public void clearAppUserData(String pkgname){
  16.   // 经測试,该方法不能用反射得到,没办法,我仅仅好这样写,仅仅能在源代码下编译。
  17.   pm.clearApplicationUserData(pkgname, new ClearUserDataObserver());
  18.   }

复制代码

  好,如今到卸载程序的时候了,看代码

  java代码

  1. // 卸载apk
  2.   ublic void unInstallApp(String pkgname) {
  3.   Log.e("unInstallApp(String pkgname)","pkgname is"+ pkgname);
  4.   Intent intent = new Intent();
  5.   // 该动作是我在android框架层自定义的一个动作,DELETE.HIDE,表明直接就卸载了。不经过系统原生的那一个对话。
  6.   intent.setAction("android.intent.action.DELETE.HIDE"); //
  7. 自定义的动作,DELETE.HIDE,不须要经过系统的确认卸载界面。直接卸载!
  8.   Uri packageURI = Uri.parse("package:" + pkgname);
  9.   intent.setData(packageURI);
  10.   startActivity(intent);

复制代码

  关于apk的管理就差点儿相同了,如今来看看正在执行的服务的管理

  首先,获取正在执行的服务:

  这里我的RunningInfo是我自定义的一个类,主要服务的一些属性,比方包名、uid、pid等等那些

  java代码

  1. // 得到正在执行的服务
  2.   public List getRunningService() {
  3.   List runServiceList = am.getRunningServices(30);
  4.   List Services_List = new ArrayList(); //
  5. 保存过滤查到的AppInfo
  6.   Log.e("getRunningService.size = ",
  7.   new Integer(runServiceList.size()).toString());
  8.   String pkgname = "";
  9.   ApplicationInfo appByPkgName = null;
  10.   for (RunningServiceInfo info : runServiceList) {
  11.   pkgname = info.service.getPackageName();
  12.   // System.out.println("service package is :" + pkgname +
  13.   // " pid = "+ info.pid); // 程序的ID号
  14.   // 过滤掉这些系统本身的服务。仅仅显示用户安装的服务
  15.   if (pkgname.equals("com.android.appmanager") ) { // 过滤自己
  16.   continue;
  17.   }
  18.   try {
  19.   appByPkgName = pm.getApplicationInfo(pkgname,
  20.   PackageManager.GET_UNINSTALLED_PACKAGES); // 最后一个參数一般为0
  21.   // 就好。
  22.   } catch (NameNotFoundException e) {
  23.   // Log.e("MainActivity 841 line","appByPkgName =
  24. pm.getApplicationInfo(pkgname, PackageManager.GET_UNINSTALLED_PACKAGES)
  25. Exception !");
  26.   e.printStackTrace();
  27.   }
  28.   Services_List.add(getRunningInfo(appByPkgName)); //
  29. 里面含有同样的包的服务。这里哦我们仅仅要求显示一个就可以。
  30.   }
  31.   // 放入set中过滤同样包名的, 这里我复写了RunningInfo 的compareTo方法你 规则是
  32. pkgName相等两个对象就算相等!
  33.   Set set = new HashSet();
  34.   for (RunningInfo x : Services_List) {
  35.   set.add(x);
  36.   }
  37.   for (RunningInfo y : set) {
  38.   Services_List.add(y);
  39.   }
  40.   return Services_List;
  41.   }

复制代码

  好,获取到了正在执行的服务之后,就能够任意停止服务了,停止服务的代码是:

  java代码

  1. // 强行停止一个app
  2.   ublic boolean stopApp(String pkgname) {
  3.   boolean flag = false;
  4.   ActivityManager am = (ActivityManager)
  5. mContext.getSystemService(Context.ACTIVITY_SERVICE);
  6.   try {
  7.   Method forceStopPackage;
  8.   forceStopPackage = am.getClass().getDeclaredMethod("forceStopPackage",
  9. String.class); // 反射得到隐藏方法(hide)
  10.   forceStopPackage.setAccessible(true);//获取私有成员变量的值
  11.   forceStopPackage.invoke(am, pkgname);
  12.   flag = true;
  13.   } catch (IllegalArgumentException e) {
  14.   e.printStackTrace();
  15.   flag = false;
  16.   } catch (IllegalAccessException e) {
  17.   e.printStackTrace();
  18.   flag = false;
  19.   } catch (InvocationTargetException e) {
  20.   e.printStackTrace();
  21.   flag = false;
  22.   } catch (SecurityException e) {
  23.   e.printStackTrace();
  24.   flag = false;
  25.   } catch (NoSuchMethodException e) {
  26.   e.printStackTrace();
  27.   flag = false;
  28.   }
  29.   return flag;

复制代码

  相同也是用反射的机制来得到隐藏类。

  到这里,应用程序管理的功能就差点儿相同了,

  剩下就仅仅是界面上的事情和程序的处理流程上的事情,应该还好!

android 卸载程序、清除数据、停止服务用法的更多相关文章

  1. Android卸载程序之后跳转到指定的反馈页面

    一个应用被用户卸载肯定是有理由的,而开发者却未必能得知这一重要的理由,毕竟用户很少会主动反馈建议,多半就是用得不爽就卸,如果能在被卸载后获取到用户的一些反馈,那对开发者进一步改进应用是非常有利的.目前 ...

  2. android的程序运行数据存放在哪里?

    Android应用开发中,给我们提供了5种数据的存储方式1 使用SharedPreferences存储数据2 文件存储数据3 SQLite数据库存储数据4 使用ContentProvider存储数据5 ...

  3. 【转】Android应用程序的数据存放目录解说

    Android的每个应用程序,都有自己的可控的目录. 在Setting/Application info里面,可以看到每个应用程序,都有Clear data和Clear cache选项. 具体这些目录 ...

  4. Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7932268 在前面一篇文章中,我们分析了And ...

  5. [转] Android应用程序与SurfaceFlinger服务的关系概述和学习计划

    转自:Android应用程序与SurfaceFlinger服务的关系概述和学习计划 SurfaceFlinger服务负责绘制Android应用程序的UI,它的实现相当复杂,要从正面分析它的实现不是一件 ...

  6. Android应用程序与SurfaceFlinger服务的关系概述和学习计划

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7846923 SurfaceFlinger服务负 ...

  7. Android应用程序请求SurfaceFlinger服务创建Surface的过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7884628 前面我们已经学习过Android应 ...

  8. Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析

    文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7867340 在前面一篇文章中,我们分析了And ...

  9. Android应用程序窗口(Activity)与WindowManagerService服务的连接过程分析

    在前两文中,我们分析了Activity组件的窗口对象和视图对象的创建过程.Activity组件在其窗口对象和视图对象创建完成之后,就会请求与WindowManagerService建立一个连接,即请求 ...

随机推荐

  1. ios 多线程开发(二)线程管理

    线程管理 iOS和OS X中每一个进程(或程序)由一个或多个线程组成.程序由一个运行main方法的线程开始,中间可以产生其他线程来执行一些指定的功能. 当程序产生一个新线程后,这个线程在程序进程空间内 ...

  2. Xcode_6.3_beta_4 官方 下载地址

    http://adcdownload.apple.com//Developer_Tools/Xcode_6.3_beta_4/Xcode_6.3_beta_4.dmg

  3. iOS 在下面 AOP 程序

    iOS 在下面 AOP 程序 概念 在软件业.AOP对于Aspect Oriented Programming缩写,手段:面向方面的编程.它是一种函数式编程张燕生风扇类型.通过这样一个技术方案功能的预 ...

  4. [ACM] POJ 3686 The Windy&#39;s (二分图最小权匹配,KM算法,特殊建图)

    The Windy's Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 4158   Accepted: 1777 Descr ...

  5. C++该函数隐藏

    只有基类成员函数的定义已声明virtualkeyword,当在派生类中的时间,以支付功能实现,virtualkeyword可以从时间被添加以增加.它不影响多状态. easy混淆视听,掩盖: ,规则例如 ...

  6. GIF/PNG/JPG和WEBP/base64/apng图片优点和缺点整理(转)

    如何获取图片对应的base64字符串呢? 1:使用代码获取: 运行下面代码 var reader = new FileReader(), htmlImage; reader.onload = func ...

  7. Oracle中merge into的使用 (转)

    http://blog.csdn.net/yuzhic/article/details/1896878 http://blog.csdn.net/macle2010/article/details/5 ...

  8. 创建在SQLServer 和 Oracle的 DBLINK

    dblink 当我们要跨本地数据库.訪问另外一个数据库表中的数据时,本地数据库中就必需要创建远程数据库的dblink,通过dblink本地数据库能够像訪问本地数据库一样訪问远程数据库表中的数据. 一 ...

  9. 超过lua上帝的语言

    上帝的语言(god)它是基于lua和RPP新一代编程语言 为什么需要它? 1.好多人不喜欢lua语法,god的语法更像C 2.god支持元编程.闭包.协程 3.凡是lua支持的特性god也支持,lua ...

  10. PE文件结构(四) 输出表

    PE文件结构(四) 參考 书:<加密与解密> 视频:小甲鱼 解密系列 视频 输出表 一般来说输出表存在于dll中.输出表提供了 文件里函数的名字跟这些函数的地址, PE装载器通过输出表来改 ...