Install apps silently, with granted INSTALL_PACKAGES permission

后端 未结 16 2222
梦谈多话
梦谈多话 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:45

    Your first bet is to look into Android's native PackageInstaller. I would recommend modifying that app the way you like, or just extract required functionality.


    Specifically, if you look into PackageInstallerActivity and its method onClickListener:

     public void onClick(View v) {
        if(v == mOk) {
            // Start subactivity to actually install the application
            Intent newIntent = new Intent();
            ...
            newIntent.setClass(this, InstallAppProgress.class);
            ...
            startActivity(newIntent);
            finish();
        } else if(v == mCancel) {
            // Cancel and finish
            finish();
        }
    }
    

    Then you'll notice that actual installer is located in InstallAppProgress class. Inspecting that class you'll find that initView is the core installer function, and the final thing it does is call to PackageManager's installPackage function:

    public void initView() {
    ...
    pm.installPackage(mPackageURI, observer, installFlags, installerPackageName);
    }
    

    Next step is to inspect PackageManager, which is abstract class. You'll find installPackage(...) function there. The bad news is that it's marked with @hide. This means it's not directly available (you won't be able to compile with call to this method).

     /**
      * @hide
      * ....
      */
      public abstract void installPackage(Uri packageURI,
                 IPackageInstallObserver observer, 
                 int flags,String installerPackageName); 
    

    But you will be able to access this methods via reflection.

    If you are interested in how PackageManager's installPackage function is implemented, take a look at PackageManagerService.

    Summary

    You'll need to get package manager object via Context's getPackageManager(). Then you will call installPackage function via reflection.

    0 讨论(0)
  • 2020-11-22 10:45

    I had no idea of how to do this, because nobody answered that time, and I found no documentation about this permission. So I found my own solution. It is worser that yours, but this is a solution anyway.

    I installed busybox, that set 777 permission to /data/app (I dont care about security). Then just executed "busybox install" from app. This works, but has a big security leak. If you set permissions 777, no root required.

    0 讨论(0)
  • 2020-11-22 10:46

    !/bin/bash

    f=/home/cox/myapp.apk   #or $1 if input from terminal.
    
    #backup env var
    backup=$LD_LIBRARY_PATH
    LD_LIBRARY_PATH=/vendor/lib:/system/lib
    myTemp=/sdcard/temp.apk
    adb push $f $myTemp
    adb shell pm install -r $myTemp
    #restore env var
    LD_LIBRARY_PATH=$backup
    

    This works for me. I run this on ubuntu 12.04, on shell terminal.

    0 讨论(0)
  • 2020-11-22 10:48

    I tried on rooted Android 4.2.2 and this method works for me:

    private void installApk(String filename) {
        File file = new File(filename); 
        if(file.exists()){
            try {   
                final String command = "pm install -r " + file.getAbsolutePath();
                Process proc = Runtime.getRuntime().exec(new String[] { "su", "-c", command });
                proc.waitFor();
            } catch (Exception e) {
                e.printStackTrace();
            }
         }
    }
    
    0 讨论(0)
  • 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

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

    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.

    0 讨论(0)
  • 2020-11-22 10:53

    I made a test app for silent installs, using PackageManager.installPackage method.

    I get installPackage method through reflection, and made android.content.pm.IPackageInstallObserver interface in my src folder (because it's hidden in android.content.pm package).

    When i run installPackage, i got SecurityException with string indication, that my app has no android.permission.INSTALL_PACKAGES, but it defined in AndroidManifest.xml.

    So, i think, it's not possible to use this method.

    PS. I tested in on Android SDK 2.3 and 4.0. Maybe it will work with earlier versions.

    0 讨论(0)
提交回复
热议问题