您的位置:首页 > 其它

静默卸载(强制卸载、没有界面的卸载)6.0以下和6.0以上的实现

2016-04-28 09:51 423 查看
版权声明:本文择自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的不一样,限制该命令的执行?如果大家有测试,请分享下测试结果。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: