Install apps silently, with granted INSTALL_PACKAGES permission

后端 未结 16 2220
梦谈多话
梦谈多话 2020-11-22 10:32

I am trying to silently install apk into the system. My app is located in /system/app and successfully granted permission \"android.permission.INSTALL_PACKAGES\"

Ho

16条回答
  •  既然无缘
    2020-11-22 10:49

    I have been implementing installation without user consent recently - it was a kiosk application for API level 21+ where I had full control over environment.

    The basic requirements are

    • API level 21+
    • root access to install the updater as a system privileged app.

    The following method reads and installs APK from InputStream:

    public static boolean installPackage(Context context, InputStream in, String packageName)
                throws IOException {
            PackageInstaller packageInstaller = context.getPackageManager().getPackageInstaller();
            PackageInstaller.SessionParams params = new PackageInstaller.SessionParams(
                    PackageInstaller.SessionParams.MODE_FULL_INSTALL);
            params.setAppPackageName(packageName);
            // set params
            int sessionId = packageInstaller.createSession(params);
            PackageInstaller.Session session = packageInstaller.openSession(sessionId);
            OutputStream out = session.openWrite("COSU", 0, -1);
            byte[] buffer = new byte[65536];
            int c;
            while ((c = in.read(buffer)) != -1) {
                out.write(buffer, 0, c);
            }
            session.fsync(out);
            in.close();
            out.close();
    
            Intent intent = new Intent(context, MainActivity.class);
            intent.putExtra("info", "somedata");  // for extra data if needed..
    
            Random generator = new Random();
    
            PendingIntent i = PendingIntent.getActivity(context, generator.nextInt(), intent,PendingIntent.FLAG_UPDATE_CURRENT);
                session.commit(i.getIntentSender());
    
    
            return true;
        }
    

    The following code calls the installation

     try {
         InputStream is = getResources().openRawResource(R.raw.someapk_source);
                        installPackage(MainActivity.this, is, "com.example.apk");
         } catch (IOException e) {
                        Toast.makeText(MainActivity.this, e.getMessage(), Toast.LENGTH_SHORT).show();
         }
    

    for the whole thing to work you desperately need INSTALL_PACKAGES permission, or the code above will fail silently

    
    

    to get this permission you must install your APK as System application which REQUIRES root (however AFTER you have installed your updater application it seem to work WITHOUT root)

    To install as system application I created a signed APK and pushed it with

    adb push updater.apk /sdcard/updater.apk
    

    and then moved it to system/priv-app - which requires remounting FS (this is why the root is required)

    adb shell
    su
    mount -o rw,remount /system
    mv /sdcard/updater.apk /system/priv-app
    chmod 644 /system/priv-app/updater.apk
    

    for some reason it didn't work with simple debug version, but logcat shows useful info if your application in priv-app is not picked up for some reason.

提交回复
热议问题