静默卸载(强制卸载、没有界面的卸载)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,表示成功卸载了,这就是静默(强制)卸载。
那我们怎么通过代码实现?
上代码!!
注意了,这个Runtime是通过签名应用获取的,所以有系统权限执行这个命令。
这个方式在6.0以下的系统签名应用都能实现,就在昨晚,在华为mate8 Android6.0上没有办法实现,到现在我也弄不明白问题所在,可能是6.0 的命令格式改变了,在通过adb shell可以实现,费解费解!迫不得已想找其他解决方案。
同事提供了一个新的方案:
PackageManager下的deletePackage();
看源码解释,
试图删除应用包!!!而且是异步处理的,需要传入一个监视者observer。而且我们也看到了@SystemApi,说明这个方法应该就是静默卸载的方式之一了,二话不说尝试一下。
因为传入了一个监视者,所以这个new 一个监视者对象传入试试,IPackageDeleteObserver 可以通过aidl 获取到。然后就是打包尝试了!
结果是感人的,完美实现!!!
那么问题来了,是不是6.0以上我不能使用adb shell命令来实现?还是华为rom的不一样,限制该命令的执行?如果大家有测试,请分享下测试结果。
应用的卸载我们都再熟悉不过了,但是要不提醒用户就卸载了你知道么?当然这个不容易做到,下面讲到的方法都是采用系统签名的方法才能实现,或者大家可以用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的不一样,限制该命令的执行?如果大家有测试,请分享下测试结果。
相关文章推荐
- ABAP更改现有程序
- Remove Duplicate Letters
- 对于CocoaPods的简单理解,实践安装使用过程和常见问题
- Linux下C函数snprintf的使用
- MapReduce: Simplified Data Processing on Large Clusters
- 对于CocoaPods的简单理解,实践安装使用过程和常见问题
- shell 条件判断语句整理
- UIWebView获取跳转链接
- 微信公众号线上和线下增粉秘籍:
- 一、安装mysql、mysql基础、mysql常用命令、数据表以及数据类型
- GeoTrust 企业(OV)型 增强版(EV) 多域名(SAN/UC) SSL证书
- 苹果新手机采 OLED,背光改革
- Hibernate 的认识
- oracle 分区详解
- postgresql 主备机的判断
- Nodejs学习笔记(二)--- 事件模块events
- SSRS 2012 创建ReportServer数据库失败: The RPC server is not listening. (Exception from HRESULT: 0x800706B3)
- shape和selector的结合
- 怎样 真正认识一个 人
- discuz 提供管理员权限