阅读 379

Android APP的静默安装和自启动

最近碰到项目中碰到一个需求,就是定制开发系统的APP需要静默安装和自启动,于是找了网上很多文章,大致都没怎么能解决,我来说说总结下。

1、Android未root的设备怎么实现静默安装?

这个方法调用静默安装需要apk有系统签名的权限,否则不可以。

需要的权限

<uses-permission android:name= "android.permission.RESTART_PACKAGES" />

<uses-permission android:name="android.permission.INSTALL_PACKAGES" tools:ignore="ProtectedPermissions" />

代码:

public boolean slienceInstallWithSysSign(String filePath) {

File file =new File(filePath);

PackageManager packageManager =HclyApplication.getInstance().getPackageManager();

ClasspmClz =packageManager.getClass();

try {

if (Build.VERSION.SDK_INT >=21) {

ClassaClass =Class.forName("android.app.PackageInstallObserver");

Constructorconstructor =aClass.getDeclaredConstructor();

constructor.setAccessible(true);

Object installObserver =constructor.newInstance();

Method method =pmClz.getDeclaredMethod("installPackage",Uri.class,aClass,int.class,String.class);

method.setAccessible(true);

method.invoke(packageManager,Uri.fromFile(file),installObserver,2,null);

}else {

Method method =pmClz.getDeclaredMethod("installPackage",

Uri.class,Class.forName("android.content.pm.IPackageInstallObserver"),int.class,String.class);

method.setAccessible(true);

method.invoke(packageManager,Uri.fromFile(file),null,2,null);

}

return true;

}catch (Exception e) {

e.printStackTrace();

}

return false;

}

2、root过的设备怎么静默安装?

其实就是调用pm install -r来安装的,-r是保留原来APP的数据。

代码:

public static boolean slienceInstall(String apkUrl) {

boolean result =false;

DataOutputStream dataOutputStream =null;

BufferedReader errorStream =null;

try {

Process process =Runtime.getRuntime().exec("su");

dataOutputStream =new DataOutputStream(process.getOutputStream());

String command ="pm install -r " + apkUrl +"\n";

dataOutputStream.write(command.getBytes(Charset.forName("utf-8")));

dataOutputStream.flush();

dataOutputStream.writeBytes("exit\n");

dataOutputStream.flush();

process.waitFor();

errorStream =new BufferedReader(new InputStreamReader(process.getErrorStream()));

String msg ="";

String line;

while ((line = errorStream.readLine()) !=null) {

msg += line;

}

if (!msg.contains("Failure")) {

result =true;

}

}catch (Exception e) {

}finally {

try {

if (dataOutputStream !=null) {

dataOutputStream.close();

}

if (errorStream !=null) {

errorStream.close();

}

}catch (IOException e) {

}

}

return result;

}

3、下面我们来说怎么自启动?

自启动这个是最难的,也是我在网上找了很多资料都没有实现的。网上说的自启动就是几种方法:

第一种:sleep 1; am start -n 包名 / 包名+activity名,睡眠一秒开启

这种我亲测过,之前是在5.1的系统可用,但是在8.1的系统就失效了,具体原因也没有去探究

至于:自启动 https://www.jianshu.com/p/782760197969,这个文章中所说的command1 && command2 && command3说是可以的,但是我测试过后发现也不行。

第二种:就是利用广播。

注册广播接收app安装成功的广播,但是经过我测试发现,完全行不通,因为执行pm install的时候原来的apk都被kill掉了,导致无法执行你的广播代码。

我是怎么做的呢?

首先我也是利用第二种广播的方法做的,但是不能写在你自己的APP里面,相当于我要多做一个APP,把广播的代码放在我这个APP中,去监听,然后去启动静默升级的APP,相当于守护进程。至于这个APP什么时候被启动就要看你们自己的需求了,我是放在了有版本更新的地方了!

亲测可以

val intentFilter = IntentFilter()

intentFilter.addAction(Intent.ACTION_PACKAGE_REPLACED)

intentFilter.addDataScheme("package")

registerReceiver(mInstallAppBroadcastReceiver,intentFilter)


private val mInstallAppBroadcastReceiver =object : BroadcastReceiver() {

override fun onReceive(context:Context?, intent:Intent?) {

val packageName = intent?.data?.schemeSpecificPart

        val action = intent?.action

        if (action ==Intent.ACTION_PACKAGE_REPLACED) {

if (packageName ==pkgName) { // 这里的pkgName是我静默升级的那个APP包名,startEntrance是静默升级的APP入口类,全路径的

val componentName = ComponentName(pkgName,startEntrance)

val intent = Intent()

intent.component =componentName

                intent.flags =Intent.FLAG_ACTIVITY_NEW_TASK

                startActivity(intent)

}

}

}

}

最后记得:unregisterReceiver(mInstallAppBroadcastReceiver)

作者:Smart0928

原文链接:https://www.jianshu.com/p/9f0deecf6e72

文章分类
后端
文章标签
版权声明:本站是系统测试站点,无实际运营。本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容, 请发送邮件至 XXXXXXo@163.com 举报,一经查实,本站将立刻删除。
相关推荐