安卓静默安装与自启动

2019-12-24  本文已影响0人  DDstar
写在前面

静默安装如果在正常的用户手机上除非是残疾用户使用,不然都是耍流氓

本次是因为做一个硬件功能,不带操作的硬件在版本更新的时候只能使用静默安装

不想听瞎逼逼可以直接看总结

说一下大概流程

静默安装需要操作的应用包括需要安装的app(最后安装的app)和被静默安装的app(要被替换掉的)

首先是最后要安装的app需要的操作

代码撸起来

1 首先写个app(省略一万行代码)
2 添加监听安装和卸载权限

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

3 做安装与卸载的广播监听,接收到广播就调用打开应用方法

自定义一个receiver继承BroadcastReceiver

public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //接收安装广播 
        if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {
            String packageName = intent.getDataString();
            // TODO:   ActivityHome为启动页
            Intent intent2 = new Intent(context, ActivityHome.class);
            intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent2);
            Log.e("onReceive", "安装了:" + packageName + "包名的程序");
        }
        //接收重新安装广播
        if (intent.getAction().equals("android.intent.action.PACKAGE_REPLACED")) {
            Toast.makeText(context, "升级了一个安装包,重新启动此程序", Toast.LENGTH_SHORT).show();
            // TODO:   ActivityHome为启动页
            Intent intent2 = new Intent(context, ActivityHome.class);
            intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent2);

        }
        //接收卸载广播
        if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {
            String packageName = intent.getDataString();
            System.out.println("卸载了:" + packageName + "包名的程序");

        }
    }
} 

4 打包应用@@%#$&%*&%&%&^%

之后就可以将此app放到服务器上面等待下载安装了
以上,此app就具有被唤醒的功能,也就是我们静默安装的目标app 可以 被唤醒了

然后是最后具备静默安装的App需要的操作

代码接着撸起来

1 添加安装app权限和超级用户权限

//有root的设备声明超级用户权限
 <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

添加了这个权限还是啊会提示错误,能编译通过就不要管他

2 静默安装需要反射系统的方法来实现

 public void installPackage(String apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, NoSuchMethodException {
        Class<?> pmClz = pm.getClass();
        if (Build.VERSION.SDK_INT >= 21) {
            Class<?> aClass = Class.forName("android.app.PackageInstallObserver");
            Constructor<?> constructor = 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(pm, Uri.fromFile(new File(apkFile)),
                    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(pm, Uri.fromFile(new File(apkFile)), null, 2,
                    null);
        }
    }

3 在下载安装包完成后调用安装逻辑

4 做应用系统签名 <---重点
普通签名的应用在调用静默安装的时候会抛没有此方法的异常,需要对它进行系统应用签名才能做到
所以
|
|
首先 将我们的app打包
然后使用签名工具---链接---
下载此工具包 将apk安装包放到工具包目录下,使用命令工具

java -jar signapk.jar platform.x509.pem platform.pk8 unsign.apk signed.apk

签名完成的安装包就是具备静默安装功能的安装包了,将此安装包安装到设备上,就可以测试静默安装了

总结

静默安装的app当然是需要每次升级安装的版本具备静默安装下一个应用的功能,所以一般来说,一个要做静默安装的应用必须具备静默安装其他app和被其他app静默安装的时候可以唤醒,所以以上的两个功能在同一个apk里面都必须具备

所以总结下步骤(其实看这个就可以了)

 <uses-permission android:name="android.permission.DELETE_PACKAGES" />
    <uses-permission android:name="android.permission.INSTALL_PACKAGES" />
//有root的设备声明超级用户权限
 <uses-permission android:name="android.permission.ACCESS_SUPERUSER" />
  <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
public class BootReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {
        //接收安装广播 
        if (intent.getAction().equals("android.intent.action.PACKAGE_ADDED")) {
            String packageName = intent.getDataString();
            // TODO:   ActivityHome为启动页
            Intent intent2 = new Intent(context, ActivityHome.class);
            intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent2);
            Log.e("onReceive", "安装了:" + packageName + "包名的程序");
        }
        //接收重新安装广播
        if (intent.getAction().equals("android.intent.action.PACKAGE_REPLACED")) {
            Toast.makeText(context, "升级了一个安装包,重新启动此程序", Toast.LENGTH_SHORT).show();
            // TODO:   ActivityHome为启动页
            Intent intent2 = new Intent(context, ActivityHome.class);
            intent2.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
            context.startActivity(intent2);

        }
        //接收卸载广播
        if (intent.getAction().equals("android.intent.action.PACKAGE_REMOVED")) {
            String packageName = intent.getDataString();
            System.out.println("卸载了:" + packageName + "包名的程序");

        }
    }
} 
<receiver
            android:name=".silenceInstall.BootReceiver"
            android:label="@string/app_name">
            <intent-filter>
                <action android:name="android.intent.action.PACKAGE_ADDED" />
                <action android:name="android.intent.action.PACKAGE_REPLACED" />
                <action android:name="android.intent.action.PACKAGE_REMOVED" />

                <data android:scheme="package" />
            </intent-filter>
 public void installPackage(String apkFile) throws IllegalArgumentException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, NoSuchMethodException {
        Class<?> pmClz = pm.getClass();
        if (Build.VERSION.SDK_INT >= 21) {
            Class<?> aClass = Class.forName("android.app.PackageInstallObserver");
            Constructor<?> constructor = 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(pm, Uri.fromFile(new File(apkFile)),
                    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(pm, Uri.fromFile(new File(apkFile)), null, 2,
                    null);
        }
    }
$%#$^$&^%*^*^&

使用系统签名工具---》
使用命令

java -jar signapk.jar platform.x509.pem platform.pk8 unsign.apk signed.apk
上一篇下一篇

猜你喜欢

热点阅读