Install / Unistall from shell command in Android

后端 未结 6 1753
一生所求
一生所求 2020-12-28 20:55

I want to implement a silent installer-from-apk-file and unistaller-package in Android. The topic has largely been discussed on SO and elsewhere but I can\'t apply any for s

相关标签:
6条回答
  • 2020-12-28 21:20

    For all who are still having problem: you will need a rooted device and use

    Process result = Runtime.getRuntime().exec("pm install -r -d MyApp.apk /system/app")
    

    If you are getting result code 9 (error code 9) you will need to delete your apk from the device and push it back (PUSH not INSTAL!).

    Go to the device shell and Push the apk

    launcher=MyApp.apk
    $adb shell su -c "mount -o remount,rw -t rfs /dev/stl5 /system"
    $adb push $launcher /sdcard/$launcher
    $adb shell su -c "chmod 644 /system/app/$launcher"
    

    Now you are able to use pm install without getting an error. Hope it will help somebody.

    0 讨论(0)
  • 2020-12-28 21:30

    Well you can do this also with the PackageManager directly (requires root access):

    • Create an app with a platform-sdk which has the interfaces publicly (create or download it, and configure eclipse)
    • In the app directly call the hidden API functions which allow silent install/remove.
    • Install the APK on your device as a system app by copying it to /system/app (root needed)

    See this: http://forum.xda-developers.com/showthread.php?t=1711653

    0 讨论(0)
  • 2020-12-28 21:31

    Don't know, but just a idea:

    I think that you are writing in the standarout, not executing a command nor giving extra data to the process via its input. I think it should be:

    Runtime.getRuntime().exec("pm install /mnt/sdcard/HelloAndroid.apk\n"); 
    

    Hope this helps.

    0 讨论(0)
  • 2020-12-28 21:33

    As I promised here is the solution to this problem, without doing any forcing to the system other than having to install the whole application in the /system/app directory. I have followed, then did some fixing to the excellent article here: http://paulononaka.wordpress.com/2011/07/02/how-to-install-a-application-in-background-on-android/. I have downloaded the zip file referenced in the article then, (I tried to keep the same class names where possible):

    1. created a new project and a main activity as entry point
    
    package com.example.silentinstuninst;
    
    import java.io.File;
    import java.lang.reflect.InvocationTargetException;
    
    import com.example.instuninsthelper.ApplicationManager;
    import com.example.instuninsthelper.OnDeletedPackage;
    import com.example.instuninsthelper.OnInstalledPackage;
    
    import android.os.Bundle;
    import android.os.Environment;
    import android.app.Activity;
    import android.util.Log;
    import android.view.View;
    import android.view.View.OnClickListener;
    import android.widget.Button;
    import android.widget.EditText;
    import android.widget.Toast;
    
    public class MainActivity extends Activity implements OnClickListener {
    
        Process install;
        Button btnInstall, btnUninstall;
        EditText txtApkFileName, txtPackageName; 
    
        public static final String TAG = "SilentInstall/Uninstall";
    
        private static ApplicationManager am;
    
        @Override
        public void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            initializeValues();
    
        }
    
        private void initializeValues() {
    
            btnInstall = (Button) findViewById(R.id.btnInstall);
            btnUninstall = (Button) findViewById(R.id.btnUninstall);
            txtApkFileName = (EditText) findViewById(R.id.txtApkFilePath);
            txtPackageName = (EditText) findViewById(R.id.txtPackageName);
    
            btnInstall.setOnClickListener(this);
            btnUninstall.setOnClickListener(this);
    
            try {
                am = new ApplicationManager(this);
                am.setOnInstalledPackage(new OnInstalledPackage() {
    
                    public void packageInstalled(String packageName, int returnCode) {
                        if (returnCode == ApplicationManager.INSTALL_SUCCEEDED) {
                            Log.d(TAG, "Install succeeded");
                        } else {
                            Log.d(TAG, "Install failed: " + returnCode);
                        }
                    }
                });
    
                am.setOnDeletedPackage(new OnDeletedPackage() {
                    public void packageDeleted(boolean succeeded) {
                        Log.d(TAG, "Uninstall succeeded");  
                    }
                });
    
            } catch (Exception e) {
                logError(e);
            }
        }
    
        private void logError(Exception e) {
            e.printStackTrace();
            Toast.makeText(this, R.string.error+e.getMessage(), Toast.LENGTH_LONG).show();
        }
    
        @Override
        public void onClick(View v) {
            switch (v.getId())
               {
                  case R.id.btnInstall:
                      // InstallUninstall.Install(txtApkFileName.getText().toString());
                try {
                    am.installPackage(Environment.getExternalStorageDirectory() +
                            File.separator + txtApkFileName.getText().toString());
                } catch (IllegalArgumentException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (IllegalAccessException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } catch (InvocationTargetException e1) {
                    // TODO Auto-generated catch block
                    e1.printStackTrace();
                } // install package
                      break;
    
                  case R.id.btnUninstall:
                      // InstallUninstall.Uninstall(txtPackageName.getText().toString());
                try {
                    am.uninstallPackage(txtPackageName.getText().toString());
                } catch (IllegalArgumentException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    logError(e);
                } catch (IllegalAccessException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    logError(e);
                } catch (InvocationTargetException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                    logError(e);
                }
                      break;
               }    
        }
    }
    
    1. create in /src the package com.example.instuninsthelper. I have added there the ApplicationManager.java and OnInstalledPackage.java files
    2. inserted the following code inside the ApplicationManager class:
    
    private OnDeletedPackage onDeletedPackage;
    class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 
    
            public void packageDeleted(boolean succeeded) throws RemoteException {
                if (onDeletedPackage != null) {
                    onDeletedPackage.packageDeleted(succeeded);
                }
            }
    
        }
    
    1. created, under the same com.example.instuninsthelper package the file OnDeletedPackage.java with the following code:
    
    package com.example.instuninsthelper;
    public interface OnDeletedPackage {
        public void packageDeleted(boolean succeeded);
    }
    
    1. in the android.content.pm package (the namespace SHOULD not be changed) I modified the IPackageDeleteObserver.java, with this result:
    
    package android.content.pm;
    
    public interface IPackageDeleteObserver extends android.os.IInterface {
    
        public abstract static class Stub extends android.os.Binder implements android.content.pm.IPackageDeleteObserver {
            public Stub() {
                throw new RuntimeException("Stub!");
            }
    
            public static android.content.pm.IPackageDeleteObserver asInterface(android.os.IBinder obj) {
                throw new RuntimeException("Stub!");
            }
    
            public android.os.IBinder asBinder() {
                throw new RuntimeException("Stub!");
            }
    
            public boolean onTransact(int code, android.os.Parcel data, android.os.Parcel reply, int flags)
                    throws android.os.RemoteException {
                throw new RuntimeException("Stub!");
            }
        }
    
        public abstract void packageDeleted(boolean succeeded)
                throws android.os.RemoteException;
    }
    
    1. build the application in Eclipse and deploy it to the emulator
    2. in the emulator: home button > Settings > applications > ...uninstall the application (because it is not installed in /system/app, and we just needed the generation of the apk file)
    3. do the following to root the emulator (so that we can write in /system/app; other solution, that I have used, is to generate a custom ROM with this app included into the /system/app):
      • download the su file from here http://forum.xda-developers.com/showthread.php?t=682828http://forum.xda-developers.com/showthread.php?t=682828. Rename it to su.zip
      • then from the console: * adb shell mount -o rw,remount -t yaffs2 /dev/block/mtdblock03 /system * adb push su.zip /system/xbin/su * adb shell chmod 06755 /system * adb shell chmod 06755 /system/xbin/su
    4. from the console, go to the /bin directory of the project, then enter: * adb push .apk /system/app
    5. finally, always from the console, enter: * adb shell am start -n com.example.silentinstuninst/com.example.silentinstuninst.MainActivity
    6. enjoy!
    0 讨论(0)
  • 2020-12-28 21:34

    Installing in the /system/app directory is essentially the same as requiring root.

    Assuming you have root, check out RootTools. Then you can do:

    if (RootTools.isAccessGiven()) {
        CommandCapture command = new CommandCapture(0, "pm install " + PATH_TO_APK);
        RootTools.getShell(true).add(command).waitForFinish();
    }
    

    Note that waitForFinish() is a blocking call!

    0 讨论(0)
  • 2020-12-28 21:39

    Runtime.getRuntime().exec("pm install /mnt/sdcard/HelloAndroid.apk\n");

    This works for me, although two more additional details have to be done:

    1. Add android:sharedUserId="android.uid.system" in AndroidManifest.xml.

    2. Signed the apk with the system key.

      But in this way it seems there is no way to tell whether the installation is succeeded, so I will try @Ginger's method later.

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