Install / Unistall from shell command in Android

后端 未结 6 1776
一生所求
一生所求 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: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!

提交回复
热议问题