Some time ago I made a small application for batch installation and uninstallation of applications. Because some APIs for installing and uninstalling applications are hidden, the Android system source code must be downloaded under ubuntu, after compilation, use the MM command to compile and generate the APK file, which is also difficult.
The idea is that there is a PackageInstaller application under the XX/packages/apps directory, and installation and uninstallation on the Android machine is completed by this application. However, it does not support batch installation and uninstallation. If you want to add the batch installation and uninstallation functions to your application, it is actually very simple, you only need to refer to the installation and uninstallation code in PakcageInstaller and add a loop. However, during compilation, you must copy the Android. mk file in PackageInstaller and change the file to the project directory name.
Okay, let's stop talking nonsense. The following is the key code.
1. Android. mk File
Copy codeThe Code is as follows: 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)
Copy codeThe Code is as follows: 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)
Copy codeThe Code is as follows: package cn.ceadic.apk mgr;
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 );
}
}
Copy codeThe Code is as follows: package cn.ceadic.apk mgr;
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. Do not forget to add permissions
Copy codeThe Code is as follows: <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"/>
Copy codeThe Code is as follows: <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 is compiled in the SDK of Android2.1 and correctly installed and uninstalled in batches.