android 应用如何管理,Android学习-应用程序管理

主要运用到的类有

PackageManager

ActivityManager

ApplicationInfo

RunningServiceInfo

Method

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

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

// 添加过滤 ,得到全部程序,系统程序,用户自己安装的程序

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")// 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这个类生成的桩。

// 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型数据转换成文件大小格式的数据。

// 系统函数,字符串转换 long -String (kb)

private String formateFileSize(long size) {

return Formatter.formatFileSize(MainActivity.this, size);

}

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

// 清除用户数据的操作

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());

}

好,现在到卸载程序的时候了,看代码

// 卸载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等等那些

// 得到正在运行的服务

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;

}

好,获取到了正在运行的服务之后,就可以随意停止服务了,停止服务的代码是:

// 强行停止一个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;

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

到这里,应用程序管理的功能就差不多了,剩下就只是界面上的事情和程序的处理流程上的事情,应该还好!

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值