Android包相关工具类,可用于(root)安装应用、(root)卸载应用、判断是否系统应用等,如:install(Context, String) 安装应用,如果是系统应用或已经root,则静默安装,否则一般安装 uninstall(Context, String) 卸载应用,如果是系统应用或已经root,则静默卸载,否则一般卸载 isSystemApplication(Context, String) 判断应用是否为系统应用
import java.io.File;
import java.util.List;
import android.app.ActivityManager;
import android.app.ActivityManager.RunningTaskInfo;
import android.content.Context;
import android.content.Intent;
import android.content.pm.ApplicationInfo;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.net.Uri;
import android.os.Build;
import android.provider.Settings;
import android.util.Log;
import cn.trinea.android.common.util.ShellUtils.CommandResult;
/**
* PackageUtils
* <ul>
* <strong>Install package</strong>
* <li>{@link PackageUtils#installNormal(Context, String)}</li>
* <li>{@link PackageUtils#installSilent(Context, String)}</li>
* <li>{@link PackageUtils#install(Context, String)}</li>
* </ul>
* <ul>
* <strong>Uninstall package</strong>
* <li>{@link PackageUtils#uninstallNormal(Context, String)}</li>
* <li>{@link PackageUtils#uninstallSilent(Context, String)}</li>
* <li>{@link PackageUtils#uninstall(Context, String)}</li>
* </ul>
* <ul>
* <strong>Is system application</strong>
* <li>{@link PackageUtils#isSystemApplication(Context)}</li>
* <li>{@link PackageUtils#isSystemApplication(Context, String)}</li>
* <li>{@link PackageUtils#isSystemApplication(PackageManager, String)}</li>
* </ul>
* <ul>
* <strong>Others</strong>
* <li>{@link PackageUtils#getInstallLocation()} get system install location</li>
* <li>{@link PackageUtils#isTopActivity(Context, String)} whether the app whost package's name is packageName is on the
* top of the stack</li>
* <li>{@link PackageUtils#startInstalledAppDetails(Context, String)} start InstalledAppDetails Activity</li>
*/
public class PackageUtils {
public static final String TAG = "PackageUtils";
private PackageUtils() {
throw new AssertionError();
}
/**
* App installation location settings values, same to {@link #PackageHelper}
*/
public static final int APP_INSTALL_AUTO = 0;
public static final int APP_INSTALL_INTERNAL = 1;
public static final int APP_INSTALL_EXTERNAL = 2;
/**
* install according conditions
* <ul>
* <li>if system application or rooted, see {@link #installSilent(Context, String)}</li>
* <li>else see {@link #installNormal(Context, String)}</li>
* </ul>
*
* @param context
* @param filePath
* @return
*/
public static final int install(Context context, String filePath) {
if (PackageUtils.isSystemApplication(context) || ShellUtils.checkRootPermission()) {
return installSilent(context, filePath);
}
return installNormal(context, filePath) ? INSTALL_SUCCEEDED : INSTALL_FAILED_INVALID_URI;
}
/**
* install package normal by system intent
*
* @param context
* @param filePath file path of package
* @return whether apk exist
*/
public static boolean installNormal(Context context, String filePath) {
Intent i = new Intent(Intent.ACTION_VIEW);
File file = new File(filePath);
if (file == null || !file.exists() || !file.isFile() || file.length() <= 0) {
return false;
}
i.setDataAndType(Uri.parse("file://" + filePath), "application/vnd.android.package-archive");
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
return true;
}
/**
* install package silent by root
* <ul>
* <strong>Attentions:</strong>
* <li>Don't call this on the ui thread, it may costs some times.</li>
* <li>You should add <strong>android.permission.INSTALL_PACKAGES</strong> in manifest, so no need to request root
* permission, if you are system app.</li>
* <li>Default pm install params is "-r".</li>
* </ul>
*
* @param context
* @param filePath file path of package
* @return {@link PackageUtils#INSTALL_SUCCEEDED} means install success, other means failed. details see
* {@link PackageUtils}.INSTALL_FAILED_*. same to {@link PackageManager}.INSTALL_*
* @see #installSilent(Context, String, String)
*/
public static int installSilent(Context context, String filePath) {
return installSilent(context, filePath, " -r " + getInstallLocationParams());
}
/**
* install package silent by root
* <ul>
* <strong>Attentions:</strong>
* <li>Don't call this on the ui thread, it may costs some times.</li>
* <li>You should add <strong>android.permission.INSTALL_PACKAGES</strong> in manifest, so no need to request root
* permission, if you are system app.</li>
* </ul>
*
* @param context
* @param filePath file path of package
* @param pmParams pm install params
* @return {@link PackageUtils#INSTALL_SUCCEEDED} means install success, other means failed. details see
* {@link PackageUtils}.INSTALL_FAILED_*. same to {@link PackageManager}.INSTALL_*
*/
public static int installSilent(Context context, String filePath, String pmParams) {
if (filePath == null || filePath.length() == 0) {
return INSTALL_FAILED_INVALID_URI;
}
File file = new File(filePath);
if (file == null || file.length() <= 0 || !file.exists() || !file.isFile()) {
return INSTALL_FAILED_INVALID_URI;
}
/**
* if context is system app, don't need root permission, but should add <uses-permission
* android:name="android.permission.INSTALL_PACKAGES" /> in mainfest
**/
StringBuilder command = new StringBuilder().append("LD_LIBRARY_PATH=/vendor/lib*:/system/lib* pm install ")
.append(pmParams == null ? "" : pmParams).append(" ").append(filePath.replace(" ", "\\ "));
CommandResult commandResult = ShellUtils.execCommand(command.toString(), !isSystemApplication(context), true);
if (commandResult.successMsg != null
&& (commandResult.successMsg.contains("Success") || commandResult.successMsg.contains("success"))) {
return INSTALL_SUCCEEDED;
}
Log.e(TAG,
new StringBuilder().append("installSilent successMsg:").append(commandResult.successMsg)
.append(", ErrorMsg:").append(commandResult.errorMsg).toString());
if (commandResult.errorMsg == null) {
return INSTALL_FAILED_OTHER;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_ALREADY_EXISTS")) {
return INSTALL_FAILED_ALREADY_EXISTS;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_APK")) {
return INSTALL_FAILED_INVALID_APK;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_INVALID_URI")) {
return INSTALL_FAILED_INVALID_URI;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_INSUFFICIENT_STORAGE")) {
return INSTALL_FAILED_INSUFFICIENT_STORAGE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_DUPLICATE_PACKAGE")) {
return INSTALL_FAILED_DUPLICATE_PACKAGE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_NO_SHARED_USER")) {
return INSTALL_FAILED_NO_SHARED_USER;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_UPDATE_INCOMPATIBLE")) {
return INSTALL_FAILED_UPDATE_INCOMPATIBLE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_SHARED_USER_INCOMPATIBLE")) {
return INSTALL_FAILED_SHARED_USER_INCOMPATIBLE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_MISSING_SHARED_LIBRARY")) {
return INSTALL_FAILED_MISSING_SHARED_LIBRARY;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_REPLACE_COULDNT_DELETE")) {
return INSTALL_FAILED_REPLACE_COULDNT_DELETE;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_DEXOPT")) {
return INSTALL_FAILED_DEXOPT;
}
if (commandResult.errorMsg.contains("INSTALL_FAILED_OLDER_SDK")) {
return INSTALL_FAILED_OLDER_SDK;
}