Android silent mode enables in depth analysis of bulk installation and uninstallation applications

  • 2020-05-10 18:49:49
  • OfStack

Some time ago, I made a small application to install and uninstall the application in batch. Because the part of API of the uninstall and uninstall application is hidden, I must download the Android system source code under ubuntu, and compile it to generate APK files using MM command. In fact, it is also difficult.

The idea is that there is an PackageInstaller application in the XX/packages/apps directory, and this application does the installation and uninstallation on the Android machine. However, it does not have the function of batch installation and uninstallation. If you want to add the function of batch installation and uninstallation in your own application, it is actually very simple, just refer to the installation and uninstallation code in PakcageInstaller and add a loop. However, it is important to note that the Android.mk file in PackageInstaller must be copied during compilation and changed to the project directory name.
Well, without further ado, here's the key code
1. Android.mk

LOCAL_PATH:= $(call my-dir) 
include $(CLEAR_VARS) 

LOCAL_MODULE_TAGS := optional 

LOCAL_SRC_FILES := $(call all-subdir-java-files) 

LOCAL_PACKAGE_NAME := PackageInstaller 
LOCAL_CERTIFICATE := platform 

include $(BUILD_PACKAGE)


    LOCAL_PATH:= $(call my-dir)  
    include $(CLEAR_VARS)  

    LOCAL_MODULE_TAGS := optional  

    LOCAL_SRC_FILES := $(call all-subdir-java-files)  

    LOCAL_PACKAGE_NAME := PackageInstaller  
    LOCAL_CERTIFICATE := platform  

    include $(BUILD_PACKAGE)  

2. PakcageInstaller.java file (key code)

    package cn.ceadic.apkmgr; 

    import java.io.File; 
    import java.io.FileNotFoundException; 
    import java.io.FileOutputStream; 
    import java.io.IOException; 

    import android.content.Context; 
    import android.content.Intent; 
    import android.content.pm.PackageInfo; 
    import android.content.pm.PackageManager; 
    import android.content.pm.PackageManager.NameNotFoundException; 
    import android.net.Uri; 
    import android.util.Log; 

    import android.content.pm.IPackageInstallObserver; 
    import android.content.pm.IPackageDeleteObserver; 
    import android.os.FileUtils; 

     
    public class PackageInstaller { 

        private File mTmpFile; 
        private final String TMP_FILE_NAME = "tmpCopy.apk"; 

        private final static String TAG = "PackInstaller"; 
        private Context mContext; 

        public PackageInstaller(Context context) { 
            mContext = context; 
        } 

         
        public void install(String path,String packageName){ 
             Intent intent = new Intent(Intent.ACTION_VIEW); 
             intent.setDataAndType(Uri.fromFile(new File(path)), 
             "application/vnd.android.package-archive"); 
             mContext.startActivity(intent); 
        } 

        public void instatllBatch(String path, String packageName) { 

            Log.i(TAG, "path=" + path); 
            int installFlags = 0; 
            PackageManager pm = mContext.getPackageManager(); 
            try { 
                PackageInfo pi = pm.getPackageInfo(packageName, 
                        PackageManager.GET_UNINSTALLED_PACKAGES); 
                if (pi != null) { 
                    installFlags |= PackageManager.INSTALL_REPLACE_EXISTING; 
                } 
            } catch (NameNotFoundException e) { 
            } 
            if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) { 
                Log.w(TAG, "Replacing package:" + packageName); 
            } 

            // Create temp file before invoking install api 
            mTmpFile = createTempPackageFile(path); 
            if (mTmpFile == null) { 
                // Message msg = mHandler.obtainMessage(INSTALL_COMPLETE); 
                // msg.arg1 = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE; 
                // mHandler.sendMessage(msg); 
                return; 
            } 
            Uri mPackageURI = Uri.parse("file://" + mTmpFile.getPath()); 
            String installerPackageName = mContext.getIntent().getStringExtra( 
                    Intent.EXTRA_INSTALLER_PACKAGE_NAME); 

            PackageInstallObserver observer = new PackageInstallObserver(); 
            pm.installPackage(mPackageURI, observer, installFlags, 
                    installerPackageName); 
        } 

        private File createTempPackageFile(String filePath) { 
            File tmpPackageFile = mContext.getFileStreamPath(TMP_FILE_NAME); 
            if (tmpPackageFile == null) { 
                Log.w(TAG, "Failed to create temp file"); 
                return null; 
            } 
            if (tmpPackageFile.exists()) { 
                tmpPackageFile.delete(); 
            } 
            // Open file to make it world readable 
            FileOutputStream fos; 
            try { 
                fos = openFileOutput(TMP_FILE_NAME, MODE_WORLD_READABLE); 
            } catch (FileNotFoundException e1) { 
                Log.e(TAG, "Error opening file " + TMP_FILE_NAME); 
                return null; 
            } 
            try { 
                fos.close(); 
            } catch (IOException e) { 
                Log.e(TAG, "Error opening file " + TMP_FILE_NAME); 
                return null; 
            } 

            File srcPackageFile = new File(filePath); 
            if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) { 
                Log.w(TAG, "Failed to make copy of file: " + srcPackageFile); 
                return null; 
            } 
            return tmpPackageFile; 
        } 

        private class PackageInstallObserver extends IPackageInstallObserver.Stub { 
            public void packageInstalled(String packageName, int returnCode) { 
                // Message msg = mHandler.obtainMessage(INSTALL_COMPLETE); 
                // msg.arg1 = returnCode; 
                // mHandler.sendMessage(msg); 
                Log.i(TAG, "====INSTALL_COMPLETE"); 
            } 
        } 

        private class PackageDeleteObserver extends IPackageDeleteObserver.Stub { 
            public void packageDeleted(boolean succeeded) { 
    //            Message msg = mHandler.obtainMessage(UNINSTALL_COMPLETE); 
    //            msg.arg1 = succeeded?SUCCEEDED:FAILED; 
    //            mHandler.sendMessage(msg); 
                Log.i(TAG, "====UNINSTALL_COMPLETE"); 
            } 
        } 

        public void uninstall(String packageName){ 
            Uri packageURI = Uri.parse("package:" + packageName); 
            Intent uninstallIntent = new Intent(Intent.ACTION_DELETE, 
            packageURI); 
            mContext.startActivity(uninstallIntent); 
        } 

        public void uninstallBatch(String packageName) { 
            PackageDeleteObserver observer = new PackageDeleteObserver(); 
            mContext.getPackageManager().deletePackage(packageName, observer, 0); 

        } 
    }  


    package cn.ceadic.apkmgr;  

    import java.io.File;  
    import java.io.FileNotFoundException;  
    import java.io.FileOutputStream;  
    import java.io.IOException;  

    import android.content.Context;  
    import android.content.Intent;  
    import android.content.pm.PackageInfo;  
    import android.content.pm.PackageManager;  
    import android.content.pm.PackageManager.NameNotFoundException;  
    import android.net.Uri;  
    import android.util.Log;  

    import android.content.pm.IPackageInstallObserver;  
    import android.content.pm.IPackageDeleteObserver;  
    import android.os.FileUtils;  

      
    public class PackageInstaller {  

        private File mTmpFile;  
        private final String TMP_FILE_NAME = "tmpCopy.apk";  

        private final static String TAG = "PackInstaller";  
        private Context mContext;  

        public PackageInstaller(Context context) {  
            mContext = context;  
        }  

          
        public void install(String path,String packageName){  
             Intent intent = new Intent(Intent.ACTION_VIEW);  
             intent.setDataAndType(Uri.fromFile(new File(path)),  
             "application/vnd.android.package-archive");  
             mContext.startActivity(intent);  
        }  

        public void instatllBatch(String path, String packageName) {  

            Log.i(TAG, "path=" + path);  
            int installFlags = 0;  
            PackageManager pm = mContext.getPackageManager();  
            try {  
                PackageInfo pi = pm.getPackageInfo(packageName,  
                        PackageManager.GET_UNINSTALLED_PACKAGES);  
                if (pi != null) {  
                    installFlags |= PackageManager.INSTALL_REPLACE_EXISTING;  
                }  
            } catch (NameNotFoundException e) {  
            }  
            if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {  
                Log.w(TAG, "Replacing package:" + packageName);  
            }  

            // Create temp file before invoking install api  
            mTmpFile = createTempPackageFile(path);  
            if (mTmpFile == null) {  
                // Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);  
                // msg.arg1 = PackageManager.INSTALL_FAILED_INSUFFICIENT_STORAGE;  
                // mHandler.sendMessage(msg);  
                return;  
            }  
            Uri mPackageURI = Uri.parse("file://" + mTmpFile.getPath());  
            String installerPackageName = mContext.getIntent().getStringExtra(  
                    Intent.EXTRA_INSTALLER_PACKAGE_NAME);  

            PackageInstallObserver observer = new PackageInstallObserver();  
            pm.installPackage(mPackageURI, observer, installFlags,  
                    installerPackageName);  
        }  

        private File createTempPackageFile(String filePath) {  
            File tmpPackageFile = mContext.getFileStreamPath(TMP_FILE_NAME);  
            if (tmpPackageFile == null) {  
                Log.w(TAG, "Failed to create temp file");  
                return null;  
            }  
            if (tmpPackageFile.exists()) {  
                tmpPackageFile.delete();  
            }  
            // Open file to make it world readable  
            FileOutputStream fos;  
            try {  
                fos = openFileOutput(TMP_FILE_NAME, MODE_WORLD_READABLE);  
            } catch (FileNotFoundException e1) {  
                Log.e(TAG, "Error opening file " + TMP_FILE_NAME);  
                return null;  
            }  
            try {  
                fos.close();  
            } catch (IOException e) {  
                Log.e(TAG, "Error opening file " + TMP_FILE_NAME);  
                return null;  
            }  

            File srcPackageFile = new File(filePath);  
            if (!FileUtils.copyFile(srcPackageFile, tmpPackageFile)) {  
                Log.w(TAG, "Failed to make copy of file: " + srcPackageFile);  
                return null;  
            }  
            return tmpPackageFile;  
        }  

        private class PackageInstallObserver extends IPackageInstallObserver.Stub {  
            public void packageInstalled(String packageName, int returnCode) {  
                // Message msg = mHandler.obtainMessage(INSTALL_COMPLETE);  
                // msg.arg1 = returnCode;  
                // mHandler.sendMessage(msg);  
                Log.i(TAG, "====INSTALL_COMPLETE");  
            }  
        }  

        private class PackageDeleteObserver extends IPackageDeleteObserver.Stub {  
            public void packageDeleted(boolean succeeded) {  
    //            Message msg = mHandler.obtainMessage(UNINSTALL_COMPLETE);  
    //            msg.arg1 = succeeded?SUCCEEDED:FAILED;  
    //            mHandler.sendMessage(msg);  
                Log.i(TAG, "====UNINSTALL_COMPLETE");  
            }  
        }  

        public void uninstall(String packageName){  
            Uri packageURI = Uri.parse("package:" + packageName);  
            Intent uninstallIntent = new Intent(Intent.ACTION_DELETE,  
            packageURI);  
            mContext.startActivity(uninstallIntent);  
        }  

        public void uninstallBatch(String packageName) {  
            PackageDeleteObserver observer = new PackageDeleteObserver();  
            mContext.getPackageManager().deletePackage(packageName, observer, 0);  

        }  
    }  

3. Don't forget to add permissions

    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/> 
        <uses-permission android:name="android.permission.INSTALL_PACKAGES" /> 
        <uses-permission android:name="android.permission.DELETE_PACKAGES" /> 
        <uses-permission android:name="android.permission.CLEAR_APP_CACHE" /> 
        <uses-permission android:name="android.permission.READ_PHONE_STATE" /> 
        <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />  


    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>  
        <uses-permission android:name="android.permission.INSTALL_PACKAGES" />  
        <uses-permission android:name="android.permission.DELETE_PACKAGES" />  
        <uses-permission android:name="android.permission.CLEAR_APP_CACHE" />  
        <uses-permission android:name="android.permission.READ_PHONE_STATE" />  
        <uses-permission android:name="android.permission.CLEAR_APP_USER_DATA" />  

The above code was compiled in SDK of Android2.1 and installed and uninstalled the application in the correct batch

Related articles: