android 卸载程序、清除数据、停止服务用法
要实现卸载程序、清除数据、停止正在执行的服务这几大模块,如今将代码粗略总结例如以下:
主要运用到的类有
PackageManager
ActivityManager
ApplicationInfo
RunningServiceInfo
Method
还有两个android.pm下的源文件用于生成桩,IPackageStatsObserver.java
和 IPackageDataObserver.java,由名字能够看出,他们是跟包的状态和大小有关的,在网上找到这两个文件的源代码后,把他们放在projectsrc文件夹下的android.pm包下,自己建包。
首先要获得系统中已经装了的apk,apk分为两类第一是系统的apk,第二是第三方的apk,所以在获取apk时能够指定一个过滤器,见例如以下代码:
java代码
- // 加入过滤 ,得到所有程序,系统程序,用户自己安装的程序
- private List queryFilterAppInfo(int filter) {
- // 查询全部已经安装的应用程序
- List listAppcations =
- pm.getInstalledApplications(PackageManager.GET_UNINSTALLED_PACKAGES);
- Collections.sort(listAppcations,new
- ApplicationInfo.DisplayNameComparator(pm));// 排序
- List appInfos = new ArrayList(); // 保存过滤查到的AppInfo
- // 依据条件来过滤
- switch (filter) {
- case FILTER_ALL_APP: // 全部应用程序
- appInfos.clear();
- for (ApplicationInfo app : listAppcations) {
- if (app.packageName.equals("com.android.appmanager")) { // 过滤自己
- continue;
- }
- appInfos.add(getAppInfo(app));
- }
- return appInfos;
- case FILTER_SYSTEM_APP: // 系统程序
- appInfos.clear();
- for (ApplicationInfo app : listAppcations) {
- if ((app.flags & ApplicationInfo.FLAG_SYSTEM) != 0) {
- if (app.packageName.equals("com.android.appmanager""font-family:Arial,
- Helvetica, sans-serif;">)// wifi { // 过滤自己
- continue;
- }
- appInfos.add(getAppInfo(app));
- }
- }
- return appInfos;
- case FILTER_THIRD_APP: // 第三方应用程序
- appInfos.clear();
- for (ApplicationInfo app : listAppcations) {
- // 非系统程序
- if ((app.flags & ApplicationInfo.FLAG_SYSTEM) <= 0) {
- if (app.packageName.equals("com.android.appmanager"))
- continue;
- }
- appInfos.add(getAppInfo(app));
- }
- // 本来是系统程序,被用户手动更新后,该系统程序也成为第三方应用程序了
- else if ((app.flags & ApplicationInfo.FLAG_UPDATED_SYSTEM_APP) != 0)
- {
- if (app.packageName.equals("geeya.android.appmanage")) { // 过滤自己
- continue;
- }
- appInfos.add(getAppInfo(app));
- }
- }
- break;
- default:
- return null;
- }
- return appInfos;
- }
复制代码
AppInfo是我自定义的一个类,里面包括了应用程序的包名、数据区大小、代码区大小、等等一些属性。
好,如今我们来获取app包的数据区大小、缓存区大小、代码区大小,这里要用反射的机制去获取PackageManager类的隐藏方法getPackageSizeInfo(),这种方法的详细实现是通过回调函数来实现的,这里要用到IPackageStatsObserver这个类生成的桩。
java代码
- // aidl文件形成的Bindler机制服务类
- public class PkgSizeObserver extends IPackageStatsObserver.Stub {
- /***
- * 回调函数,
- *
- * @param pStatus
- * ,返回数据封装在PackageStats对象中
- * @param succeeded
- * 代表回调成功
- */
- @Override
- public void onGetStatsCompleted(PackageStats pStats, boolean succeeded)
- throws RemoteException {
- long cachesize; // 缓存大小
- long datasize; // 数据大小
- long codesize; // 应用程序大小
- long totalsize; // 总大小
- // System.out.println("data start init!");
- synchronized (Integer.class) {
- cachesize = pStats.cacheSize; // 缓存大小
- datasize = pStats.dataSize; // 数据大小
- codesize = pStats.codeSize; // 应用程序大小
- totalsize = cachesize + datasize + codesize;
- Message msg = mHandler.obtainMessage();
- msg.what = MSG_SIZE_CHANGE;
- Bundle bundle = new Bundle();
- bundle.putLong("cachesize", cachesize);
- bundle.putLong("datasize", datasize);
- bundle.putLong("codesize", codesize);
- bundle.putLong("totalsize", totalsize);
- bundle.putString("packageName", pStats.packageName);
- msg.obj = bundle;
- mHandler.sendMessage(msg);
- }
- }
- }
- //获取每一个apk的大小信息,包含数据区、代码区、缓存区
- // 查询包的大小信息
- public void queryPacakgeSize(String pkgName) throws Exception {
- if (pkgName != null) {
- // 使用放射机制得到PackageManager类的隐藏函数getPackageSizeInfo
- PackageManager pm = getPackageManager(); // 得到pm对象
- try {
- // 通过反射机制获得该隐藏函数
- Method getPackageSizeInfo =
- pm.getClass().getDeclaredMethod("getPackageSizeInfo", String.class,
- IPackageStatsObserver.class);
- getPackageSizeInfo.invoke(pm, pkgName, new PkgSizeObserver());
- } catch (Exception ex) {
- // Log.e(TAG, "NoSuchMethodException");
- ex.printStackTrace();
- throw ex; // 抛出异常
- }
- }
- }
复制代码
或得到app的大小数据后,封装成消息发送出去,这是最好的方法!!
这里也介绍一个将long型数据转换成文件大小格式的数据。
java代码
- // 系统函数,字符串转换 long -String (kb)
- private String formateFileSize(long size) {
- return Formatter.formatFileSize(MainActivity.this, size);
- }
复制代码
好,如今我们来清除用户数据,这里要用到之前下载的那个文件IPackageDataObserver,跟获取app大小一样的,通过回调来实现。
java代码
- // 清除用户数据的操作
- class ClearUserDataObserver extends IPackageDataObserver.Stub {
- public void onRemoveCompleted(final String packageName,final boolean
- succeeded) {
- final Message msg = mHandler.obtainMessage();
- if (succeeded) {
- msg.what = CLEAR_USER_DATA;
- } else {
- msg.what = NOT_CLEAR_USER_DATA;
- }
- mHandler2.sendMessage(msg);
- }
- }
- // 清除apk的数据
- public void clearAppUserData(String pkgname){
- // 经測试,该方法不能用反射得到,没办法,我仅仅好这样写,仅仅能在源代码下编译。
- pm.clearApplicationUserData(pkgname, new ClearUserDataObserver());
- }
复制代码
好,如今到卸载程序的时候了,看代码
java代码
- // 卸载apk
- ublic void unInstallApp(String pkgname) {
- Log.e("unInstallApp(String pkgname)","pkgname is"+ pkgname);
- Intent intent = new Intent();
- // 该动作是我在android框架层自定义的一个动作,DELETE.HIDE,表明直接就卸载了。不经过系统原生的那一个对话。
- intent.setAction("android.intent.action.DELETE.HIDE"); //
- 自定义的动作,DELETE.HIDE,不须要经过系统的确认卸载界面。直接卸载!
- Uri packageURI = Uri.parse("package:" + pkgname);
- intent.setData(packageURI);
- startActivity(intent);
复制代码
关于apk的管理就差点儿相同了,如今来看看正在执行的服务的管理
首先,获取正在执行的服务:
这里我的RunningInfo是我自定义的一个类,主要服务的一些属性,比方包名、uid、pid等等那些
java代码
- // 得到正在执行的服务
- public List getRunningService() {
- List runServiceList = am.getRunningServices(30);
- List Services_List = new ArrayList(); //
- 保存过滤查到的AppInfo
- Log.e("getRunningService.size = ",
- new Integer(runServiceList.size()).toString());
- String pkgname = "";
- ApplicationInfo appByPkgName = null;
- for (RunningServiceInfo info : runServiceList) {
- pkgname = info.service.getPackageName();
- // System.out.println("service package is :" + pkgname +
- // " pid = "+ info.pid); // 程序的ID号
- // 过滤掉这些系统本身的服务。仅仅显示用户安装的服务
- if (pkgname.equals("com.android.appmanager") ) { // 过滤自己
- continue;
- }
- try {
- appByPkgName = pm.getApplicationInfo(pkgname,
- PackageManager.GET_UNINSTALLED_PACKAGES); // 最后一个參数一般为0
- // 就好。
- } catch (NameNotFoundException e) {
- // Log.e("MainActivity 841 line","appByPkgName =
- pm.getApplicationInfo(pkgname, PackageManager.GET_UNINSTALLED_PACKAGES)
- Exception !");
- e.printStackTrace();
- }
- Services_List.add(getRunningInfo(appByPkgName)); //
- 里面含有同样的包的服务。这里哦我们仅仅要求显示一个就可以。
- }
- // 放入set中过滤同样包名的, 这里我复写了RunningInfo 的compareTo方法你 规则是
- pkgName相等两个对象就算相等!
- Set set = new HashSet();
- for (RunningInfo x : Services_List) {
- set.add(x);
- }
- for (RunningInfo y : set) {
- Services_List.add(y);
- }
- return Services_List;
- }
复制代码
好,获取到了正在执行的服务之后,就能够任意停止服务了,停止服务的代码是:
java代码
- // 强行停止一个app
- ublic boolean stopApp(String pkgname) {
- boolean flag = false;
- ActivityManager am = (ActivityManager)
- mContext.getSystemService(Context.ACTIVITY_SERVICE);
- try {
- Method forceStopPackage;
- forceStopPackage = am.getClass().getDeclaredMethod("forceStopPackage",
- String.class); // 反射得到隐藏方法(hide)
- forceStopPackage.setAccessible(true);//获取私有成员变量的值
- forceStopPackage.invoke(am, pkgname);
- flag = true;
- } catch (IllegalArgumentException e) {
- e.printStackTrace();
- flag = false;
- } catch (IllegalAccessException e) {
- e.printStackTrace();
- flag = false;
- } catch (InvocationTargetException e) {
- e.printStackTrace();
- flag = false;
- } catch (SecurityException e) {
- e.printStackTrace();
- flag = false;
- } catch (NoSuchMethodException e) {
- e.printStackTrace();
- flag = false;
- }
- return flag;
复制代码
相同也是用反射的机制来得到隐藏类。
到这里,应用程序管理的功能就差点儿相同了,
剩下就仅仅是界面上的事情和程序的处理流程上的事情,应该还好!
android 卸载程序、清除数据、停止服务用法的更多相关文章
- Android卸载程序之后跳转到指定的反馈页面
一个应用被用户卸载肯定是有理由的,而开发者却未必能得知这一重要的理由,毕竟用户很少会主动反馈建议,多半就是用得不爽就卸,如果能在被卸载后获取到用户的一些反馈,那对开发者进一步改进应用是非常有利的.目前 ...
- android的程序运行数据存放在哪里?
Android应用开发中,给我们提供了5种数据的存储方式1 使用SharedPreferences存储数据2 文件存储数据3 SQLite数据库存储数据4 使用ContentProvider存储数据5 ...
- 【转】Android应用程序的数据存放目录解说
Android的每个应用程序,都有自己的可控的目录. 在Setting/Application info里面,可以看到每个应用程序,都有Clear data和Clear cache选项. 具体这些目录 ...
- Android应用程序请求SurfaceFlinger服务渲染Surface的过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7932268 在前面一篇文章中,我们分析了And ...
- [转] Android应用程序与SurfaceFlinger服务的关系概述和学习计划
转自:Android应用程序与SurfaceFlinger服务的关系概述和学习计划 SurfaceFlinger服务负责绘制Android应用程序的UI,它的实现相当复杂,要从正面分析它的实现不是一件 ...
- Android应用程序与SurfaceFlinger服务的关系概述和学习计划
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7846923 SurfaceFlinger服务负 ...
- Android应用程序请求SurfaceFlinger服务创建Surface的过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7884628 前面我们已经学习过Android应 ...
- Android应用程序与SurfaceFlinger服务之间的共享UI元数据(SharedClient)的创建过程分析
文章转载至CSDN社区罗升阳的安卓之旅,原文地址:http://blog.csdn.net/luoshengyang/article/details/7867340 在前面一篇文章中,我们分析了And ...
- Android应用程序窗口(Activity)与WindowManagerService服务的连接过程分析
在前两文中,我们分析了Activity组件的窗口对象和视图对象的创建过程.Activity组件在其窗口对象和视图对象创建完成之后,就会请求与WindowManagerService建立一个连接,即请求 ...
随机推荐
- 解决新版Emacs的警告:Warning (initialization): Your load-path...
升级到新版Emacs后出现警告 作为做好用的代码编辑器之一,Emacs绝对在极客世界实用率很高.当然VIM也有很多支持者.但小编是从VIM转到Emacs的,个人觉得Emacs更好用. 小编最近升级了F ...
- jQuery
代码的层定位滑动动画效果
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- DataTable填补了实体类返回泛型集合
坤哥见我昨天找了一段代码,如下面: 略微解释下,这段代码时D层查询结束后,将datatable查询到的结果赋值给实体对象的属性,然后返回实体的过程.坤哥看了之后问我,假设实体有500多个属性,难道也要 ...
- android--jenkins+gradle+android自动化构建apk步骤(转)
第一步,安装jenkins,这个网上教程挺多的. 第二步,下载并配置gradle.下载地址http://www.gradle.org/ 解压gradle至某路径下,如/usr/local/lib/gr ...
- Netty In Action中文版 - 第一章:Netty介绍
本章介绍 Netty介绍 为什么要使用non-blocking IO(NIO) 堵塞IO(blocking IO)和非堵塞IO(non-blocking IO)对照 Java NIO的问题和在Nett ...
- 【我们都爱Paul Hegarty】斯坦福大学IOS8公开组个人笔记28 ScrollView 幻灯片视图
随着移动设备,iphone屏幕尺寸的限制.超过内容的屏幕大小为scrollview于,通过滑动来获得.scrollview滑动方向可以是也可以是横向垂直,scrollview可以嵌套,例如,纵向滑动s ...
- 《学习opencv》笔记——矩阵和图像处理——cvMax,cvMaxS,cvMerge,cvMin and cvMinS
矩阵和图像操作 (1)cvMax函数 其结构 void cvMax(//比較两个图像取最大值 const CvArr* src1,//图像1 const CvArr* src2,//图像2 CvArr ...
- 《Swift程序设计语言》中国翻译和学习笔记page23
·<The Swift Programming Language>中文翻译及读书笔记,附件中为英文原版教程 因21页之前内容和技术关系不大,不做翻译整理,从第21页開始 · 页 1 本页主 ...
- 2年SQL Server DBA调优方面总结
原文:2年SQL Server DBA调优方面总结 2年SQL Server DBA调优方面总结 当2年dba 我觉得,有些东西需要和大家分享探讨,先书单. 书单 1.<深入解析SQL Serv ...
- [git] fatal: This operation must be run in a work tree
正在使用git init --bare 它的成立裸仓库后,,正在使用git 其他命令将出现fatal:This operation must be run in a work tree 问题,途径: ...