adb 静默安装_GitHub - anricheng/jing_install: 静默安装与卸载

本文介绍了如何在Android系统中实现静默安装和卸载应用,包括使用PM命令和调用PackageInstaller接口的详细步骤,涉及反射、权限设置等相关技术。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

jing_install

静默安装与卸载

Android实现静默卸载与安装

静默安装简介:一般情况下,Android系统安装apk会出现一个安装界面,用户可以点击确定或者取消来进行apk的安装。

但在实际的项目需求中,有一种需求,就是希望apk在后台安装(不出现安装界面的提示),这种安装方式称为静默安装。

以下用两张方式实现静默安装与卸载:

一、PM命令实现静默安装与卸载

注:这种方法需要root权限

直接adb shell 命令卸载应用

adb shell pm uninstall -k (应用包名)

adb shell pm install -r (apk路径)

在Android程序代码中实现pm

Runtime.getRuntime().exec("sh");// 申请root权限

Runtime.getRuntime().exec("pm uninstall -k uninstallPackageName")//卸载

Runtime.getRuntime().exec("pm install -r unstallapkPath")//安装

安装可选的参数:

参数说明

-l锁定应用程序

-r重新安装应用,且保留应用数据

-t允许测试apk被安装

-i 指定安装包的包名

-s安装到sd卡

-f安装到系统 内置存储中(默认安装位置)

-d允许降级安装(同一应用低级换高级)

-g授予应用程序清单中列出的所有权限(只有6.0系统可用)

卸载可选的参数:

参数说明

-k卸载应用且保留数据与缓存(如果不加-k则全部删除)

声明权限:

在Manifest文件中加入如下语句:

二、调用PackageInstaller接口实现静默安装与卸载

注:需要系统签名

实现原理

android自带了一个安装程序—/system/app/PackageInstaller.apk.大多数情况下,我们手机上安装应用都是通过这个apk来安装的。.我们在应用程序中控制安装应用APP,其实就是发送一个如下的intent。去调用packageinstaller进行安装,具体的操作代码如下:

/* 安装apk */

Intent intent = new Intent();

intent.setAction(Intent.ACTION_VIEW);

intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);

intent.setDataAndType(Uri.parse("file://"+ fileName),

"application/vnd.android.package-archive");

context.startActivity(intent);

对比应用正常安装的流程,静默安装的本质就是去掉如下图所示的用户授权同意安装的过程,直接进行应用安装。

源码分析

阅读过源码后我们知道,系统的安装过程其实是调用了系统中的PackageInstaller来完成的。希望做到静默安装,就是找到一个方法,绕过PackageInstaller中的权限授予提示,继续完成安装的步骤。

所以,思路很简单,我们可以从两方面去操作:

•找到PackageInstaller源码,跳过权限授予提醒,直接调用后面的安装API即可完成安装。(这样能够良好的兼容正常安装,不易出错)

•使用pm install 命令进行安装。

调用PackageInstaller中隐藏的API

查看PackageInstaller源码我们能够发现,其实PackageInstaller也是通过使用PackageManager进行安装的。调用的是其installPackage方法,但是此方法是一个abstract,且是对外不可见的(hide),

定义如下所示:

public abstract class PackageManager {

………

/**

安装应用APK文件

@param packageURI 待安装的APK文件位置,可以是'file:'或'content:' URI.

@param observer 一个APK文件安装状态的观察器

@param flags 安装形式 INSTALL_FORWARD_LOCK, INSTALL_REPLACE_EXISTING, INSTALL_ALLOW_TEST.

@paraminstallerPackageName APK安装包的PackageName

*/

// @SystemApi

public abstract void installPackage(UripackageURI, PackageInstallObserverobserver,int flags, StringinstallerPackageName);

}

因为,installPackage是系统的API,为了使用PackageManager.installPackage(),考虑通过反射机制可以调用installPackage()。

静默安装和卸载具体实现如下

1、通过反射实现

注:需要系统签名,并且需要push到/system/app/

安装:

接下来在程序中通过反射拿到PackageManager的installPackage方法,代码如下:

最后在调用安装方法之前,先来看看这个方法的几个参数:

注:需要拷贝IPackageInstallObserver.aidl和IPackageDeleteObserver.aidl到我们的app/src/main/aidl/目录中并且包名一定要为android.content.pm。拷贝的源码路径:\frameworks\base\core\java\android\content\pm

•packageURI: 安装包的地址。

•observer:安装完成后的回调函数。observer可以直接给null,如果想要设置回调的话,需要新建一个类实现IPackageInstallOberver类(从源码中复制过来)。

flags:安装方式,主要有普通安装和覆盖安装。1表示普通,2表示覆盖。

有如下值:

INSTALL_FORWARD_LOCK,

INSTALL_REPLACE_EXISTING,

INSTALL_ALLOW_TEST,

INSTALL_EXTERNAL,

INSTALL_INTERNAL,

INSTALL_FROM_ADB,

INSTALL_ALL_USERS,

INSTALL_ALLOW_DOWNGRADE,

INSTALL_GRANT_RUNTIME_PERMISSIONS,

INSTALL_FORCE_VOLUME_UUID,

INSTALL_FORCE_PERMISSION_PROMPT,

INSTALL_EPHEMERAL,

INSTALL_DONT_KILL_APP

•installerPackageName:执行安装的应用程序名,apk的名字。

// 静默安装 apkFile是apk的名字

public static void JF_install(Context context, String apkFile, String packageName) {

apkFile = "client-debug.apk";//for test 可删

File installFile = new File(Environment.getExternalStorageDirectory(), File.separator + apkFile);

Uri uri = Uri.fromFile(installFile);

int installFlags = 2;//覆盖安装

PackageManager pm = context.getPackageManager();

MyPakcageInstallObserver observer = new MyPakcageInstallObserver();

// 通过 getMethod 只能获取公有方法,如果获取私有方法则会抛出异常

try {

Method method = pm.getClass().getMethod("installPackage", Uri.class,IPackageInstallObserver.class,int.class,String.class);//得到installPackage()方法

method.invoke(pm, uri, observer, installFlags,apkFile);//调用installPackage()方法

} catch (Exception e) {

Log.i("install fail",e.toString());

e.printStackTrace();

}

}

/静默安装回调/

class MyPakcageInstallObserver extends IPackageInstallObserver.Stub{

@Override

public void packageInstalled(String packageName, int returnCode) {

//通过returnCode 0表示失败 1表示成功

if (returnCode == 1) {

Log.e("DEMO","安装成功");

}else{

Log.e("DEMO","安装失败,返回码是:"+returnCode);

}

}

}

静默卸载:

//静默卸载 反射方式

public static void JF_uninstall(Context context, String packageName) {

try {

PackageManager pm = context.getPackageManager();

MyPackageDeleteObserver observer = new MyPackageDeleteObserver();

//得到deletePackage()方法

Method method = pm.getClass().getMethod("deletePackage", String.class, IPackageDeleteObserver.class, int.class);

//调用deletePackage()

method.invoke(pm, packageName, observer, 2);//第三个参数为2时表示删除所有数据,第三个参数有以下值可选:DELETE_KEEP_DATA,

DELETE_ALL_USERS,

DELETE_SYSTEM_APP(值为4,可删除系统应用或用系统签名的应用),

DELETE_DONT_KILL_APP

} catch (Exception e) {

Log.i("uninstall fail",e.toString());

}

}

//静默卸载回调

class MyPackageDeleteObserver extends IPackageDeleteObserver.Stub {

@Override

public void packageDeleted(String packageName, int returnCode) {

if (returnCode == 1) {

Log.e("DEMO","卸载成功...");

}else{

Log.e("DEMO","卸载失败...返回码:"+returnCode);

}

}

}

声明权限:

在Manifest文件中加入如下语句:

2、在源码中编译实现

注:也需要系统签名

若不通过反射的方式,则另外一种方法是可以通过在源码中编译实现静默安装卸载

安装:

代码如下

// 静默安装 apkFile是apk的名字

public static void J_install(Context context, String apkFile, String packageName) {

apkFile = "client-debug.apk";//for test 可删

File installFile = new File(Environment.getExternalStorageDirectory(), File.separator + apkFile);

Uri uri = Uri.fromFile(installFile);

int installFlags = 2;//覆盖安装

PackageManager pm = context.getPackageManager();

//安装函数的回调,此类在反射实现中有定义

MyPakcageInstallObserver observer = new MyPakcageInstallObserver();

pm.installPackage(uri, observer, installFlags, apkFile);//参数同反射实现中的参数意义一样

}

卸载:

代码如下

//静默卸载

public static void J_uninstall(Context context, String packageName) {

PackageManager pm = context.getPackageManager();

MyPackageDeleteObserver observer = new MyPackageDeleteObserver();

pm.deletePackage(packageName, observer, 0);

}

声明权限:

在Manifest文件中加入如下语句:

由于然后在manifest文件中,在节点中加入sharedUserId属性:

package="com.example.slienceinstall"

android:sharedUserId="android.uid.system" //声明为系统应用

android:versionCode="1"

android:versionName="1.0" >

... ...

3、自动更新

自动更新功能的实现原理,就是我们事先和后台协商好一个接口,我们在应用的主Activity里,去访问这个接口,如果需要更新,后台会返回一些数据(比如,提示语;最新版本的url等)。然后开始下载,下载完成后开始调用静默安装方法覆盖原来的安装程序,这样用户的应用就保持最新的拉。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值