背景介绍
条件:
1.不使用Process process = Runtime.getRuntime().exec(pm install -r ....)执行shell命令。为什么不使用是因为su拿得到前提是系统支持。
2.需要拥有系统权限,即系统签名+android:sharedUserId="android.uid.system"。
实现方式
1.使用eclipse打系统jar只包含如下,打系统jar包的时候,只复制如下几个文件,然后忽略所有error直接export jar包
传送门 ApplicationPackageManager.java,PackageInstallObserver.java
2.jar放在Android Studio显示如下:
你会发现class文件会有各种error,不管。(因为接着我们会使用compileOnly)
App Gradle配置:
根Gradle配置
3.在src/main/aidl 下面也要创建IPackageInstallObserver.aidl和PackageManager.jar里面的文件一样,如果这里不放的话会提示找不到IPackageInstallObserver错误。请注意。
静默安装
public class InstallUtils {
public static final String path = "sdcard/Android/data/com.xxx/cache/xxxx.apk";
public static void installByPackageManager(Context context, String path) {
PackageManager packageManager = context.getPackageManager();
if (packageManager instanceof ApplicationPackageManager) {
((ApplicationPackageManager)packageManager).installPackage(
Uri.fromFile(new File(path)),new MyPackageInstallObserver(),0,"com.android.vending");
}
}
private static class MyPackageInstallObserver extends PackageInstallObserver{
public void onUserActionRequired(Intent intent) {
}
public void onPackageInstalled(String basePackageName, int returnCode, String msg,
Bundle extras) {
LogUtils.d(LogUtils.TAG,"MyPackageInstallObserver--onPackageInstalled basePackageName="+basePackageName);
}
}
}
分析
ApplicationPackageManager 构造器传IPackageManager
protected ApplicationPackageManager(ContextImpl context,
IPackageManager pm) {
mContext = context;
mPM = pm;
}
@Override
public void installPackage(Uri packageURI, IPackageInstallObserver observer, int flags,
String installerPackageName) {
installCommon(packageURI, new LegacyPackageInstallObserver(observer), flags,
installerPackageName, mContext.getUserId());
}
@Override
public void installPackage(Uri packageURI, PackageInstallObserver observer,
int flags, String installerPackageName) {
installCommon(packageURI, observer, flags, installerPackageName, mContext.getUserId());
}
private void installCommon(Uri packageURI,
PackageInstallObserver observer, int flags, String installerPackageName,
int userId) {
if (!"file".equals(packageURI.getScheme())) {
throw new UnsupportedOperationException("Only file:// URIs are supported");
}
final String originPath = packageURI.getPath();
try {
mPM.installPackageAsUser(originPath, observer.getBinder(), flags, installerPackageName,
userId);
} catch (RemoteException e) {
throw e.rethrowFromSystemServer();
}
}
IPackageManager的父类其实是 PackageManagerService.java 最终的PackageManager的方法调用都是Service进行执行,如下:
public void installPackageAsUser(String originPath, IPackageInstallObserver2 observer,
int installFlags, String installerPackageName, int userId) {
mContext.enforceCallingOrSelfPermission(android.Manifest.permission.INSTALL_PACKAGES, null);
final int callingUid = Binder.getCallingUid();
enforceCrossUserPermission(callingUid, userId,
true /* requireFullPermission */, true /* checkShell */, "installPackageAsUser");
if (isUserRestricted(userId, UserManager.DISALLOW_INSTALL_APPS)) {
try {
if (observer != null) {
observer.onPackageInstalled("", INSTALL_FAILED_USER_RESTRICTED, null, null);
}
} catch (RemoteException re) {
}
return;
}
if ((callingUid == Process.SHELL_UID) || (callingUid == Process.ROOT_UID)) {
installFlags |= PackageManager.INSTALL_FROM_ADB;
} else {
// Caller holds INSTALL_PACKAGES permission, so we're less strict
// about installerPackageName.
installFlags &= ~PackageManager.INSTALL_FROM_ADB;
installFlags &= ~PackageManager.INSTALL_ALL_USERS;
}
UserHandle user;
if ((installFlags & PackageManager.INSTALL_ALL_USERS) != 0) {
user = UserHandle.ALL;
} else {
user = new UserHandle(userId);
}
// Only system components can circumvent runtime permissions when installing.
if ((installFlags & PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS) != 0
&& mContext.checkCallingOrSelfPermission(Manifest.permission
.INSTALL_GRANT_RUNTIME_PERMISSIONS) == PackageManager.PERMISSION_DENIED) {
throw new SecurityException("You need the "
+ "android.permission.INSTALL_GRANT_RUNTIME_PERMISSIONS permission "
+ "to use the PackageManager.INSTALL_GRANT_RUNTIME_PERMISSIONS flag");
}
if ((installFlags & PackageManager.INSTALL_FORWARD_LOCK) != 0
|| (installFlags & PackageManager.INSTALL_EXTERNAL) != 0) {
throw new IllegalArgumentException(
"New installs into ASEC containers no longer supported");
}
final File originFile = new File(originPath);
final OriginInfo origin = OriginInfo.fromUntrustedFile(originFile);
final Message msg = mHandler.obtainMessage(INIT_COPY);
final VerificationInfo verificationInfo = new VerificationInfo(
null /*originatingUri*/, null /*referrer*/, -1 /*originatingUid*/, callingUid);
final InstallParams params = new InstallParams(origin, null /*moveInfo*/, observer,
installFlags, installerPackageName, null /*volumeUuid*/, verificationInfo, user,
null /*packageAbiOverride*/, null /*grantedPermissions*/,
null /*certificates*/, PackageManager.INSTALL_REASON_UNKNOWN);
params.setTraceMethod("installAsUser").setTraceCookie(System.identityHashCode(params));
msg.obj = params;
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "installAsUser",
System.identityHashCode(msg.obj));
Trace.asyncTraceBegin(TRACE_TAG_PACKAGE_MANAGER, "queueInstall",
System.identityHashCode(msg.obj));
mHandler.sendMessage(msg);
}