【Android應用開發】-(18)靜默方式實現批量安裝解除安裝應用程式
阿新 • • 發佈:2019-01-01
前段時間做了一個批量安裝解除安裝應用程式的小應用,由於安裝解除安裝應用程式的部分API是隱藏的,所以必須在ubuntu下下載Android系統原始碼,並編譯之後使用MM命令編譯生成APK檔案,其實也難。思路是這樣的,在XX/packages/apps目錄下有一個PackageInstaller的應用程式,Android機器中安裝解除安裝都是由這個應用程式完成的。但是它沒有批量安裝和解除安裝的功能,如果要在自己的應用程式中新增批量安裝和解除安裝的功能,其實很簡單,只需要參考PakcageInstaller裡面的安裝解除安裝程式碼加個迴圈就可以了。但值得注意的是在編譯的過程中必須複製PackageInstaller裡面的Android.mk檔案,修改檔案為工程目錄名。好了,廢話不再多說,下面是關鍵程式碼
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)
2、PakcageInstaller.java檔案(關鍵程式碼)
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、別忘記新增許可權
<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" />
以上程式碼在Android2.1的SDK中編譯通過,並正確批量安裝解除安裝應用程式