通常情况下,android是没有提供静默方式的上层接口,我们需要在android源代码下来调用这个隐藏的接口来完成静默安装。
最重要的就是参考android系统目录下的packages/apps/PackageInstaller,
当中有两个文件 PackageInstallerActivity.java,InstallAppProgress.java ,前者就是我们通常看到的带有提示对话框的安装应用程序,后者是点确定安装后调用的intent。
现提供一个静默安装的关键类,该类在android2.2下成功编译, 其中通过循环调用接口instatllBatch则可实现批量安装
当然最后的应用程序别忘记添加权限
<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" />
package com.android.util;
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.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
import android.net.Uri;
import android.util.Log;
import android.util.DisplayMetrics;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageDeleteObserver;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Message;
public class PackageInstaller {
private File mTmpFile;
private final int INSTALL_COMPLETE = 1;
final static int SUCCEEDED = 1;
final static int FAILED = 0;
private final static String TAG = "PackInstaller";
private Context mContext;
private ApplicationInfo mAppInfo;
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) {
Log.i(TAG, "path=" + path);
int installFlags = 0;
Uri mPackageURI = Uri.fromFile(new File(path));
PackageParser.Package mPkgInfo = getPackageInfo(mPackageURI);
mAppInfo = mPkgInfo.applicationInfo;
String packageName = mAppInfo.packageName;
Log.i(TAG, "====install packageName ="+packageName);
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);
}
PackageInstallObserver observer = new PackageInstallObserver();
pm.installPackage(mPackageURI, observer, installFlags,
packageName);
}
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);
}
/*
* Utility method to get package information for a given packageURI
*/
public PackageParser.Package getPackageInfo(Uri packageURI) {
final String archiveFilePath = packageURI.getPath();
PackageParser packageParser = new PackageParser(archiveFilePath);
File sourceFile = new File(archiveFilePath);
DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
PackageParser.Package pkg = packageParser.parsePackage(sourceFile,
archiveFilePath, metrics, 0);
// Nuke the parser reference.
packageParser = null;
return pkg;
}
/*
* Utility method to get application information for a given packageURI
*/
public ApplicationInfo getApplicationInfo(Uri packageURI) {
final String archiveFilePath = packageURI.getPath();
PackageParser packageParser = new PackageParser(archiveFilePath);
File sourceFile = new File(archiveFilePath);
DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
if (pkg == null) {
return null;
}
return pkg.applicationInfo;
}
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case INSTALL_COMPLETE:
if(msg.arg1 == SUCCEEDED) {
} else {}
break;
default:
break;
}
}
};
}
最重要的就是参考android系统目录下的packages/apps/PackageInstaller,
当中有两个文件 PackageInstallerActivity.java,InstallAppProgress.java ,前者就是我们通常看到的带有提示对话框的安装应用程序,后者是点确定安装后调用的intent。
现提供一个静默安装的关键类,该类在android2.2下成功编译, 其中通过循环调用接口instatllBatch则可实现批量安装
当然最后的应用程序别忘记添加权限
<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" />
package com.android.util;
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.content.pm.ApplicationInfo;
import android.content.pm.PackageParser;
import android.net.Uri;
import android.util.Log;
import android.util.DisplayMetrics;
import android.content.pm.IPackageInstallObserver;
import android.content.pm.IPackageDeleteObserver;
import android.os.FileUtils;
import android.os.Handler;
import android.os.Message;
public class PackageInstaller {
private File mTmpFile;
private final int INSTALL_COMPLETE = 1;
final static int SUCCEEDED = 1;
final static int FAILED = 0;
private final static String TAG = "PackInstaller";
private Context mContext;
private ApplicationInfo mAppInfo;
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) {
Log.i(TAG, "path=" + path);
int installFlags = 0;
Uri mPackageURI = Uri.fromFile(new File(path));
PackageParser.Package mPkgInfo = getPackageInfo(mPackageURI);
mAppInfo = mPkgInfo.applicationInfo;
String packageName = mAppInfo.packageName;
Log.i(TAG, "====install packageName ="+packageName);
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);
}
PackageInstallObserver observer = new PackageInstallObserver();
pm.installPackage(mPackageURI, observer, installFlags,
packageName);
}
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);
}
/*
* Utility method to get package information for a given packageURI
*/
public PackageParser.Package getPackageInfo(Uri packageURI) {
final String archiveFilePath = packageURI.getPath();
PackageParser packageParser = new PackageParser(archiveFilePath);
File sourceFile = new File(archiveFilePath);
DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
PackageParser.Package pkg = packageParser.parsePackage(sourceFile,
archiveFilePath, metrics, 0);
// Nuke the parser reference.
packageParser = null;
return pkg;
}
/*
* Utility method to get application information for a given packageURI
*/
public ApplicationInfo getApplicationInfo(Uri packageURI) {
final String archiveFilePath = packageURI.getPath();
PackageParser packageParser = new PackageParser(archiveFilePath);
File sourceFile = new File(archiveFilePath);
DisplayMetrics metrics = new DisplayMetrics();
metrics.setToDefaults();
PackageParser.Package pkg = packageParser.parsePackage(sourceFile, archiveFilePath, metrics, 0);
if (pkg == null) {
return null;
}
return pkg.applicationInfo;
}
private Handler mHandler = new Handler() {
public void handleMessage(Message msg) {
switch (msg.what) {
case INSTALL_COMPLETE:
if(msg.arg1 == SUCCEEDED) {
} else {}
break;
default:
break;
}
}
};
}