1. 程式人生 > >【Android應用開發】-(18)靜默方式實現批量安裝解除安裝應用程式

【Android應用開發】-(18)靜默方式實現批量安裝解除安裝應用程式

     前段時間做了一個批量安裝解除安裝應用程式的小應用,由於安裝解除安裝應用程式的部分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中編譯通過,並正確批量安裝解除安裝應用程式