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

  主要运用到的类有

  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;

复制代码

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

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

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

最新文章

  1. 2016HUAS_ACM暑假集训3F - Jungle Roads
  2. 关键词提取1-C#
  3. 解决PHP下导出csv乱码小记
  4. Effective Java 47 Know and use the libraries
  5. jsp学习(四)
  6. android 开发如何做内存优化
  7. 【转】Android自定义Adapter的ListView的思路及代码
  8. sqlserver2008附加数据库——错误3415
  9. ios文本常见属性
  10. python 爬一下
  11. Qt原始资源形象问题后删除
  12. homebrew 更改镜像,进行成功安装
  13. Javascript 跨域知识详细介绍
  14. Umbraco 7 支持Microsoft Word 2013 发布内容
  15. eclipse项目两个红点
  16. gNewSense 3.0 Beta 2 发布
  17. Android中为图标加上数字
  18. MATLAB中-27开3次方得不到-3的原因
  19. JS学习 - offset家族(一)
  20. ECHO不换行

热门文章

  1. hdu 4454 Stealing a Cake(三分之二)
  2. Hadoop之—— CentOS Warning: $HADOOP_HOME is deprecated解
  3. ubuntu 在下面 hadoop 安装
  4. sql 添加用户
  5. SVN命令汇总
  6. table在 点击线条颜色
  7. 通过gradle运行测试脚本(转)
  8. hdu3480二维斜率优化DP
  9. SVD奇异值分解的几何物理意义资料汇总
  10. SSH深度历险(三) EJB Session Bean有状态和无状态的差别与联系