Android8.1 以上静默安装实现

简介: Android8.1 以上静默安装实现

前提是你已经拥有了当前 android 设备的系统签名,比如定制设备开发


一、获取系统签名 jks 文件


在 android 源码目录下路径 build/target/product/security/ 下,存在 platform.pk8、platform.x509.pem


这两货就是我们平常说的系统签名,有了系统签名再给app增加 android.uid.system 属性,app就变成了系统级app。


当我们在 AndroidManifest.xml 中增加了 uid 属性,AS 就无法直接运行安装调试了,会出现如下错误


The application could not be installed: INSTALL_FAILED_SHARED_USER_INCOMPATIBLE

Installation failed due to: ‘no signatures that match those in shared user android.uid.system;’


我们一般都需要先打包app,然后在用 signapk.jar 给app签名后再安装运行,这样调试起来就很繁琐。那么我们就来生成一个


platform.jks,直接在AS中就能Run起来。


在 build/target/product/security/ 路径下,执行下面三条指令

  openssl pkcs8 -inform DER -nocrypt -in platform.pk8 -out platform.pem
  openssl pkcs12 -export -in platform.x509.pem -out platform.p12 -inkey platform.pem -password pass:123 -name test
  keytool -importkeystore -deststorepass 123 -destkeystore platform.jks -srckeystore platform.p12 -srcstoretype PKCS12 -srcstorepass 123


这样就会生成 platform.jks,这就是我们要的,还多出来 platform.p12、platform.pem 忽略就好


platform.jks 对应的 keyAlias 为上面的name,test,password 为 123,所以在 AS 的 build.gradle 配置如下

 signingConfigs {
        releaseConfig {
            storeFile file("platform.jks")
            storePassword '123'
            keyPassword '123'
            keyAlias = 'test'
        }
        debug {
            storeFile file("platform.jks")
            storePassword '123'
            keyPassword '123'
            keyAlias = 'test'
        }
    }


二、增加 android.uid.system 属性,反射调用 installPackage()


导入 android_dependency.jar

private void SilentInstallApkByReflect(String apkPath) {
         apkPath = Environment.getExternalStorageDirectory()+"/Android/11.apk";
        try {
            PackageManager packageManager = getPackageManager();
            Method method = packageManager.getClass().getDeclaredMethod("installPackage",
                    new Class[] {Uri.class, IPackageInstallObserver.class, int.class, String.class} );
            method.setAccessible(true);
            File apkFile = new File(apkPath);
            Uri apkUri = Uri.fromFile(apkFile);
            method.invoke(packageManager, new Object[]{apkUri, new IPackageInstallObserver.Stub() {
                @Override
                public void packageInstalled(String pkgName, int resultCode) throws RemoteException {
                    Log.d("install", "packageInstalled = " + pkgName + "; resultCode = " + resultCode);
                }
            }, Integer.valueOf(2), ""});
        }catch (Exception e) {
            e.printStackTrace();
        }
}

不加 android.uid.system 属性会报如下错误

W/System.err: Caused by: java.lang.SecurityException: Neither user 10078 nor current process has android.permission.INSTALL_PACKAGES.
W/System.err:     at android.os.Parcel.readException(Parcel.java:2005)
W/System.err:     at android.os.Parcel.readException(Parcel.java:1951)
W/System.err:     at android.content.pm.IPackageManager$Stub$Proxy.installPackageAsUser(IPackageManager.java:4092)
W/System.err:     at android.app.ApplicationPackageManager.installCommon(ApplicationPackageManager.java:1705)
W/System.err:     at android.app.ApplicationPackageManager.installPackage(ApplicationPackageManager.java:1686)
W/System.err:   ... 14 more

安装成功将回调 packageInstalled()

D/install: packageInstalled = com.sound.smartphone; resultCode = 1


同时通过监听静态广播 android.intent.action.PACKAGE_REPLACED 判断是否安装成功

<receiver android:name=".ServiceBroadcastReceiver">
  <intent-filter android:priority="1000">
    <action android:name="android.intent.action.PACKAGE_REPLACED" />
    <action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
    <data android:scheme="package" />
  </intent-filter>
</receiver>
if ("android.intent.action.PACKAGE_REPLACED".equals(action)
                || "android.intent.action.MY_PACKAGE_REPLACED".equals(action)){
  try{
    String scheme = intent.getScheme();
    String packageName = intent.getData().getSchemeSpecificPart();
    if(context.getPackageName().equals(packageName)) {
      Toast.makeText(context, "成功升级新版本!", Toast.LENGTH_SHORT).show();
    }
    LogUtils.i("KePackageService", "收到 ACTION_PACKAGE_REPLACED");
    LogUtils.e("KePackageService", " scheme="+scheme);
    LogUtils.e("KePackageService", " schemeSpecificPart="+packageName);
  }catch (Exception e){
    e.printStackTrace();
  }
}


E/LogUtils: action=android.intent.action.MY_PACKAGE_REPLACED

I/KePackageService: 收到 ACTION_PACKAGE_REPLACED

E/KePackageService: scheme=package

E/KePackageService: schemeSpecificPart=com.sound.smartphone

目录
相关文章
|
缓存 Shell Android开发
Android 常见adb命令
Android 常见adb命令
206 0
|
Java Shell Android开发
|
缓存 监控 Shell
Android--adb命令详解
ADB,即 Android Debug Bridge,它是 Android 开发/测试人员不可替代的强大工具,也是 Android 设备玩家的好玩具。
2569 0
|
数据安全/隐私保护 Android开发
|
数据库 Android开发 开发工具
|
Shell Android开发 网络协议
|
Android开发 iOS开发 数据库
|
Android开发 开发工具
Android虚拟机安装
由于虫师那边的源估计到期了,我又找了一波。 打开SDK Manager.exe, 就在安卓目录下。 点击Tools--Options进入配置页面 mirrors.neusoft.edu.cn 配置如下,然后就可以看到刷刷的一些安卓包了。
|
开发工具 Android开发 开发者