版权声明:本文择自http://blog.csdn.net/maodunti,未经博主允许不得转载。
应用的卸载我们都再熟悉不过了,但是要不提醒用户就卸载了你知道么?当然这个不容易做到,下面讲到的方法都是采用系统签名的方法才能实现,或者大家可以用root后的设备可以实现。
系统签名就是通过签名获取到系统权限去做系统才能做的事情,root以后你就获取到系统权限,这里不多谈这些权限的问题。
如果使用过adb shell命令的同学知道,我们可以通过输入命令静默(强制)安装、卸载应用,即不提供“是否安装”、“是否卸载”这样的提示,我们这里主要讲静默(强制)卸载。
如下
*****\android-sdk-windows\platform-tools>adb shell
shell@HWNXT:/ $ /system/bin/pm uninstall com.ishugui
/system/bin/pm uninstall com.ishugui
Success
shell@HWNXT:/ $
*****\android-sdk-windows\platform-tools>
我们通过adb shell 卸载的手机上的com.hugui这个包,而且没有界面提示,返回值是success,表示成功卸载了,这就是静默(强制)卸载。
那我们怎么通过代码实现?
上代码!!
public static String execRuntime(Runtime rt, String command) {
String str = "";
Process process = null;
BufferedReader reader = null;
try {
process = rt.exec(command);
reader = new BufferedReader(new InputStreamReader(process.getInputStream()));
int read;
char[] buffer = new char[1024];
StringBuffer output = new StringBuffer();
while ((read = reader.read(buffer)) > 0) {
output.append(buffer, 0, read);
}
process.waitFor();
str = output.toString();
} catch (InterruptedException ie) {
Log.e(LOG_TAG, "exec InterruptedException:", ie);
} catch (IOException ioe) {
Log.e(LOG_TAG, "exec IOException:", ioe);
} catch (Exception e) {
Log.e(LOG_TAG, "exec Exception:", e);
} finally {
try {
if (reader != null) {
reader.close();
}
} catch (IOException ioe) {
Log.e(LOG_TAG, "Close IOException", ioe);
}
destroyProcess(process);
}
return str;
}
注意了,这个Runtime是通过签名应用获取的,所以有系统权限执行这个命令。
这个方式在6.0以下的系统签名应用都能实现,就在昨晚,在华为mate8 Android6.0上没有办法实现,到现在我也弄不明白问题所在,可能是6.0 的命令格式改变了,在通过adb shell可以实现,费解费解!迫不得已想找其他解决方案。
同事提供了一个新的方案:
PackageManager下的deletePackage();
看源码解释,
Attempts to delete a package. Since this may take a little while, the result will be posted back to the given observer. A deletion will fail if the calling context lacks the android.Manifest.permission permission, if the named package cannot be found, or if the named package is a "system package". (TODO: include pointer to documentation on "system packages")
Parameters:
packageName The name of the package to delete
observer An observer callback to get notified when the package deletion is complete. IPackageDeleteObserver.packageDeleted(java.lang.String,int) will be called when that happens. observer may be null to indicate that no callback is desired.
flags - possible values: DELETE_KEEP_DATA, DELETE_ALL_USERS.
Hide:
3428
3429 // @SystemApi
3430 public abstract void More ...deletePackage(
3431 String packageName, IPackageDeleteObserver observer, int flags);
试图删除应用包!!!而且是异步处理的,需要传入一个监视者observer。而且我们也看到了@SystemApi,说明这个方法应该就是静默卸载的方式之一了,二话不说尝试一下。
private void delPkg(Context context, String pkgName) {
try {
PackageManager pm = context.getPackageManager();
Method[] methods = pm != null ? pm.getClass().getDeclaredMethods() : null;
Method mDel = null;
if (methods != null && methods.length > 0) {
for (Method method : methods) {
if (method.getName().toString().equals("deletePackage")) {
mDel = method;
break;
}
}
}
if (mDel != null) {
mDel.setAccessible(true);
mDel.invoke(pm, pkgName, new PackageDeleteObserver(), 0);
}
} catch (Exception e) {
}
}
private class PackageDeleteObserver extends IPackageDeleteObserver.Stub {
@Override
public void packageDeleted(String packageName, int returnCode) throws RemoteException {
Log.i(LOG_TAG, "del apk >>" + packageName + ";code >>" + returnCode);
}
}
因为传入了一个监视者,所以这个new 一个监视者对象传入试试,IPackageDeleteObserver 可以通过aidl 获取到。然后就是打包尝试了!
结果是感人的,完美实现!!!
那么问题来了,是不是6.0以上我不能使用adb shell命令来实现?还是华为rom的不一样,限制该命令的执行?如果大家有测试,请分享下测试结果。