首页
Web开发
Windows程序
编程语言
数据库
移动开发
系统相关
微信
其他好文
会员
首页
>
移动开发
> 详细
android 卸载程序、清除数据、停止服务用法
时间:
2015-02-03 11:02:27
阅读:
281
评论:
0
收藏:
0
[点我收藏+]
标签:
要实现卸载程序、清除数据、停止正在执行的服务这几大模块,如今将代码粗略总结例如以下:
主要运用到的类有
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 卸载程序、清除数据、停止服务用法
标签:
原文地址:http://www.cnblogs.com/mengfanrong/p/4269283.html
踩
(
0
)
赞
(
0
)
举报
评论
一句话评论(
0
)
登录后才能评论!
分享档案
更多>
2021年07月29日 (22)
2021年07月28日 (40)
2021年07月27日 (32)
2021年07月26日 (79)
2021年07月23日 (29)
2021年07月22日 (30)
2021年07月21日 (42)
2021年07月20日 (16)
2021年07月19日 (90)
2021年07月16日 (35)
周排行
更多
关闭苹果IOS app自动更新
2021-07-29
开发一个即时通讯App
2021-07-28
iOS 跳转App Store进行评分
2021-07-26
诺基亚短信生成!太好玩了
2021-07-26
【Azure 应用服务】App Service 配置 Application Settings 访问Storage Account得到 could not be resolved: '*.file.core.windows.net'的报错。没有解析成对应中国区 Storage Account地址 *.file.core.chinacloudapi.cn
2021-07-26
Android系统编程入门系列之界面Activity响应丝滑的传统动画
2021-07-26
uniapp h5,app两端复制文本
2021-07-22
uni-app滚动视图容器(scroll-view)之监听上拉事件
2021-07-21
新型横向移动工具原理分析、代码分析、优缺点以及检测方案
2021-07-19
Android系统编程入门系列之界面Activity交互响应
2021-07-19
友情链接
兰亭集智
国之画
百度统计
站长统计
阿里云
chrome插件
新版天听网
关于我们
-
联系我们
-
留言反馈
© 2014
mamicode.com
版权所有 联系我们:gaon5@hotmail.com
迷上了代码!