android静默卸载,Android实践 -- Android静默安装和卸载

App的静默安装和卸载

Android系统本身提供了安装卸载功能,但是api接口是@hide的,不是公开的接口,所以在应用级别

是无法实现静默安装和卸载的,要实现静默安装和卸载需要是系统应用,要有系统签名和相应的权限

简单思路如下:

通过反射获得安装接口installPackage和 卸载接口 deletePackage

在自己的包中引入两个接口IPackageInstallObserver和IPackageDeleteObserver的空实现

调用安装卸载的方法,回调上面的两个接口

添加权限

进行系统签名

将应用push到系统中,作为系统应用

在PackageManager中的提供的接口如下

安装接口

// @SystemApi

public abstract void installPackage(

Uri packageURI, IPackageInstallObserver observer, int flags,

String installerPackageName);

卸载接口

// @SystemApi

public abstract void deletePackage(

String packageName, IPackageDeleteObserver observer, int flags);

引入两个回掉的空实现

在自己应用的工程中新建一个包android.content.pm,并添加两个文件

IPackageDeleteObserver.java

package android.content.pm;

public interface IPackageDeleteObserver extends android.os.IInterface {

public abstract static class Stub extends android.os.Binder implements android.content.pm.IPackageDeleteObserver {

public Stub() {

throw new RuntimeException("Stub!");

}

public static android.content.pm.IPackageDeleteObserver asInterface(android.os.IBinder obj) {

throw new RuntimeException("Stub!");

}

public android.os.IBinder asBinder() {

throw new RuntimeException("Stub!");

}

public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)

throws android.os.RemoteException {

throw new RuntimeException("Stub!");

}

}

public abstract void packageDeleted(java.lang.String packageName, int returnCode)

throws android.os.RemoteException;

}

IPackageInstallObserver.java

package android.content.pm;

public interface IPackageInstallObserver extends android.os.IInterface {

public abstract static class Stub extends android.os.Binder implements android.content.pm.IPackageInstallObserver {

public Stub() {

throw new RuntimeException("Stub!");

}

public static android.content.pm.IPackageInstallObserver asInterface(android.os.IBinder obj) {

throw new RuntimeException("Stub!");

}

public android.os.IBinder asBinder() {

throw new RuntimeException("Stub!");

}

public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)

throws android.os.RemoteException {

throw new RuntimeException("Stub!");

}

}

public abstract void packageInstalled(java.lang.String packageName, int returnCode)

throws android.os.RemoteException;

}

自己定义个接口回调

OnPackagedObserver.java

package com.example;

public interface OnPackagedObserver {

public void packageInstalled(String packageName, int returnCode);

public void packageDeleted(String packageName,int returnCode);

}

实现方法

反射接口

PackageManager pm = context.getPackageManager();

Class>[] types = new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class};

Class>[] uninstalltypes = new Class[] {String.class, IPackageDeleteObserver.class, int.class};

Method method = pm.getClass().getMethod("installPackage", types);

Method uninstallmethod = pm.getClass().getMethod("deletePackage", uninstalltypes);

实现回调接口

private OnPackagedObserver onInstalledPackaged;

class PackageInstallObserver extends IPackageInstallObserver.Stub {

public void packageInstalled(String packageName, int returnCode) throws RemoteException {

if (onInstalledPackaged != null) {

onInstalledPackaged.packageInstalled(packageName, returnCode);

}

}

}

class PackageDeleteObserver extends IPackageDeleteObserver.Stub {

public void packageDeleted(String packageName, int returnCode) throws RemoteException {

if (onInstalledPackaged != null) {

onInstalledPackaged.packageDeleted(packageName, returnCode);

}

}

}

实现

卸载接口只需要提供要卸载的应用的包名packagename ,安装提供了三个接口

public void uninstallPackage(String packagename) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {

uninstallmethod.invoke(pm, new Object[] {packagename, observerdelete, 0});

}

public void installPackage(String apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {

installPackage(new File(apkFile));

}

public void installPackage(File apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {

if (!apkFile.exists()) throw new IllegalArgumentException();

Uri packageURI = Uri.fromFile(apkFile);

installPackage(packageURI);

}

public void installPackage(Uri apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException {

method.invoke(pm, new Object[] {apkFile, observer, INSTALL_REPLACE_EXISTING, null});

}

签名

生成一个apk文件,需要对这个apk文件进行系统签名,由于

是系统应用需要的权限,在开发应用时,如果加载AndroidManifest.xml

中会编译不过,需要先用工具 apktool 工具先把apk文件解压出来,用编辑器在AndroidManifest.xml中加入上面的两个权限,然后在用工具apktool重新打包

具体的使用方法参考 [Android实践 -- Apktool 的使用](http://www.jianshu.com/p/1896307da564)

解压

apktool d test.apk

修改之后,重新打包

apktool b test

签名之后的文件,需要在进行系统签名

具体的使用方法请参考 Android实践 -- 对apk进行系统签名

java -jar signapk.jar platform.x509.pem platform.pk8 test.apk test_signed.apk

将签名之后的文件 push到手机中,需要root权限

具体的代码实现

附录,安装卸载错误码速查

回调中的returnCode在PackageManager中的相关的定义如下:

安装错误码

public static final int INSTALL_SUCCEEDED = 1;

public static final int INSTALL_FAILED_ALREADY_EXISTS = -1;

public static final int INSTALL_FAILED_INVALID_APK = -2;

public static final int INSTALL_FAILED_INVALID_URI = -3;

public static final int INSTALL_FAILED_INSUFFICIENT_STORAGE = -4;

public static final int INSTALL_FAILED_DUPLICATE_PACKAGE = -5;

public static final int INSTALL_FAILED_NO_SHARED_USER = -6;

public static final int INSTALL_FAILED_UPDATE_INCOMPATIBLE = -7;

public static final int INSTALL_FAILED_SHARED_USER_INCOMPATIBLE = -8;

public static final int INSTALL_FAILED_MISSING_SHARED_LIBRARY = -9;

public static final int INSTALL_FAILED_REPLACE_COULDNT_DELETE = -10;

public static final int INSTALL_FAILED_DEXOPT = -11;

public static final int INSTALL_FAILED_OLDER_SDK = -12;

public static final int INSTALL_FAILED_CONFLICTING_PROVIDER = -13;

public static final int INSTALL_FAILED_NEWER_SDK = -14;

public static final int INSTALL_FAILED_TEST_ONLY = -15;

public static final int INSTALL_FAILED_CPU_ABI_INCOMPATIBLE = -16;

public static final int INSTALL_FAILED_MISSING_FEATURE = -17;

public static final int INSTALL_FAILED_CONTAINER_ERROR = -18;

public static final int INSTALL_FAILED_INVALID_INSTALL_LOCATION = -19;

public static final int INSTALL_FAILED_MEDIA_UNAVAILABLE = -20;

public static final int INSTALL_FAILED_VERIFICATION_TIMEOUT = -21;

public static final int INSTALL_FAILED_VERIFICATION_FAILURE = -22;

public static final int INSTALL_FAILED_PACKAGE_CHANGED = -23;

public static final int INSTALL_FAILED_UID_CHANGED = -24;

public static final int INSTALL_FAILED_VERSION_DOWNGRADE = -25;

public static final int INSTALL_FAILED_PERMISSION_MODEL_DOWNGRADE = -26;

public static final int INSTALL_PARSE_FAILED_NOT_APK = -100;

public static final int INSTALL_PARSE_FAILED_BAD_MANIFEST = -101;

public static final int INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION = -102;

public static final int INSTALL_PARSE_FAILED_NO_CERTIFICATES = -103;

public static final int INSTALL_PARSE_FAILED_INCONSISTENT_CERTIFICATES = -104;

public static final int INSTALL_PARSE_FAILED_CERTIFICATE_ENCODING = -105;

public static final int INSTALL_PARSE_FAILED_BAD_PACKAGE_NAME = -106;

public static final int INSTALL_PARSE_FAILED_BAD_SHARED_USER_ID = -107;

public static final int INSTALL_PARSE_FAILED_MANIFEST_MALFORMED = -108;

public static final int INSTALL_PARSE_FAILED_MANIFEST_EMPTY = -109;

public static final int INSTALL_FAILED_INTERNAL_ERROR = -110;

public static final int INSTALL_FAILED_USER_RESTRICTED = -111;

public static final int INSTALL_FAILED_DUPLICATE_PERMISSION = -112;

public static final int INSTALL_FAILED_NO_MATCHING_ABIS = -113;

public static final int NO_NATIVE_LIBRARIES = -114;

public static final int INSTALL_FAILED_ABORTED = -115;

卸载错误码

public static final int DELETE_SUCCEEDED = 1;

public static final int DELETE_FAILED_INTERNAL_ERROR = -1;

public static final int DELETE_FAILED_DEVICE_POLICY_MANAGER = -2;

public static final int DELETE_FAILED_USER_RESTRICTED = -3;

public static final int DELETE_FAILED_OWNER_BLOCKED = -4;

public static final int DELETE_FAILED_ABORTED = -5;

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/244288.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

outlook邮箱邮件大小限制_Office Outlook 2010、2013附件大小超过了允许的范围限制三种解决方法图解...

在outlook2010、2013中添加附件超过20M,就会提示:“附件大小超出了允许的范围”!outlook2007的附件默认大小是150M,而outlook2010、2013的是20M(有种说法是10M,也许是版本问题,未验证),也许微软…

dota迷你盒子Android5,DOTA:第一批TI7的迷你Aegis复制品已经到货

原标题:DOTA:第一批TI7的迷你Aegis复制品已经到货各地华丽的工艺。节日期间,一些Dota 2粉丝的完美礼物被封顶,他们本周开始收到令人垂涎的“宙斯盾”(Aegis of Champions)的缩影复制品。今年5月4日至10月1日举行的国际7战斗通行证…

oracle unpivot 索引_oracle 11g 行列转换之unpivot、pivot

一、 列 转 行create table STU_ROW2COL(id VARCHAR2(10),intname VARCHAR2(10),subject VARCHAR2(20),grade NUMBER)insert into stu_row2col (ID, INTNAME, SUBJECT, GRADE) values (1, ZORRO, 语文, 70);insert into stu_row2col (ID, INTNAME, SUBJECT, GR…

鸿蒙系统下拉菜单,鸿蒙的js开发部模式17:鸿蒙的系统能力的应用模块

1. 鸿蒙的系统能力主要涉及通知消息模块,在模拟器中也可以实践和获取初始界面:点击发送通知,顶部出现通知消息的图标下拉通知菜单栏,出现通知信息:js的业务逻辑代码:import notification from system.notification;no…

win7开启uasp协议_UASP与USB模式切换工具(SwitchUA官方版下载_UASP与USB模式切换工具(SwitchUASP) v1.0免费版 - Win7旗舰版...

UASP与USB模式切换工具(SwitchUASP)是一款能够帮助用户将系统的USB3.0传输模式切换到UASP模式的软件,利用软件能够有效的提升用户的电脑传输速度,有需要的可以下载使用。功能介绍UASP模式可以让USB的速度增加不少,特别是小文件的处理速度在us…

华为 原生android 6.0,安卓6.0原生桌面轻体验,我的手机从未如此流畅过

本帖最后由 啷个里格弄 于 2016-12-30 13:05 编辑1.png (188.33 KB, 下载次数: 65)2016-4-29 18:21 上传▏写在开头P8的EMUI系统或者称之为桌面在功能性和流畅度上都给我留下不错的印象。但是成天盯着一款桌面难免“七年之痒”,楼主这边就来给大家的P8换换口味&…

大数据职业理解_到底什么是大数据,大数据职业的具体工作内容是什么?

综合网络解释加上自己的理解给出了大数据的定义。大数据就是数据规模达到海量级、极快的速度流转、数据类型和来源多种多样、价值密度低而且能够反映事物真实性的数据就是大数据。大数据的工作内容包括以下几个方面:数据采集调查显示,未被使 用的信息比例…

兼容ios和android的ar,安卓又落后 这几款AR游戏只能iOS玩

近日苹果正式推送iOS 11,很多AR应用也随之上线。iOS 11一个很重要的亮点就是AR增强现实,利用它用户可以实现很多前所未有的体验,比如将室内的环境与游戏融为一体;还能测量距离。想知道你喜欢的明星身高吗?打开Measure这…

群晖如何建php网站_群晖折腾 篇一:群晖Web Station 功能搭建属于自己的照片分享网站...

群晖折腾 篇一:群晖Web Station 功能搭建属于自己的照片分享网站2020-03-03 16:42:1514点赞83收藏11评论小编注:此篇文章来自即可瓜分10万金币,周边好礼达标就有,邀新任务奖励无上限,点击查看活动详情创作立场声明&…

dilink智能网联系统鸿蒙系统,【图】秦Pro DM DiLink智能网联系统实测解读_汽车江湖...

一辆天天接触的车对于车主而言,早已不是一辆车这么简单了,更多时候它还充当我们的“好伙伴”甚至是“知己”,多少人下班停好车以后不愿意下车?因为他们知道这是一个分界点:推开车门你就是柴米油盐、是父亲、是儿子、是…

卓越性能代码_装好win10后,应该这样设置,才能压榨出系统十足的性能

用了这么久win10系统,你知道在win10中有不同的性能模式吗?而使用不同的性能模式会消耗不同的电量,就会为系统提供不同的性能。为了拥有好的性能,我们一般会在电源选项中给系统设置为高性能模式,但你以为这就够了吗&…

html语言中的转行标记是6,网页设计与制作模拟试题

全国2004年7月高等教育自学考试网页设计与制作试题网页设计与制作模拟试题一、 单项选择题(每空1分,共10分)1.目前在Internet上应用最为广泛的服务是( )。A.FTP服务 B.WWW服务 C.Telnet服务 D.Gopher服务2.在域名系统中,域名采用( )。A.树型命名机制 B.星…

swoolephp加密_PHP中给源代码加密的几种方法

商业使用推荐 Swoole Compiler 代码加密以下是如何通过PHP的自定义函数来加密我们的PHP源代码方法一function encode_file_contents($filename) {$typestrtolower(substr(strrchr($filename,.),1));if (php $type && is_file($filename) && is_writable($file…

将html保存为图片,html2canvas 将html代码转为图片并保存下来

html2canvas 将html代码转为图片并保存下来发布时间:2018-05-22 10:15,浏览次数:421, 标签:htmlcanvas只是测试了下,在 谷歌和360上都可以,但是在火狐和ie下面暂时没有效果,所以先做个小记录,等…

产品配件类目税目分类_我国消费税税目种类有哪些?

在日常生活中我们接触到的商品,比如:烟、酒、汽车、贵重首饰及珠宝玉石、鞭炮焰火等等,其实在法律上都是需要交纳消费税的,这也就导致了这些商品在不同区域存在不同的价格这一现象。那么,我国消费税税目种类有哪些呢?…

raid 物理盘缓存状态_服务器raid卡、磁盘缓存的配置策略

最近遇到不少因服务器异常断电,导致文件系统元数据等被破坏的问题,究其原因是磁盘缓存没有关闭。不再重复码字了,直接贴图:所以带raid卡、磁盘服务器环境的推荐配置为:1 商用环境,RAID一定要有超级电容&…

主管护士需要考计算机和英语吗,2020主管护师改为机考,一定要注意这些问题!...

原标题:2020主管护师改为机考,一定要注意这些问题!中国卫生人才网官方通知已确定,2020年护理学中级既主管护师考试形式-推行机考。那么,人机对话考试怎么考,有什么注意事项,为考生整理如下&…

pythonflask configlist.py_Python+Flask.0004.FLASK配置管理之三种方式加载外部配置

简单介绍:说明: 复杂的项目需要配置各种环境,若设置少可直接硬编码,设置多的话可通过加载配置/加载文件/加载变量的方式来设置123app.config.update(DEBUGTrue,)扩展: app.config是flask.config.Config类的实例,继承子PY内置数据结构dict,所以可以使用如上update方法,支持传入多…

html引用c 变量,在jsp页面中定义全局变量,供其他页面引用

一、在一个jsp中引用另一个jsp的方法有:1.使用 jsp include指令(常用):file属性是必填的(绝对或相对路径),但它不支持任何的表达式,也不允许通过?挂参方式来传递参数。注意:一般页面的top和bottom固定的时候…