答案是肯定的,但是在调用pm安装是必须要设定一个-d的参数.
} else if (opt.equals("-d")) { 1188 params.installFlags |= PackageManager.INSTALL_ALLOW_DOWNGRADE;
xref: /frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
在安装apk是会调用installLocationPolicy,而这个函数会调用checkDowngrade 来检测apk的版本
private int installLocationPolicy(PackageInfoLite pkgLite) {
10508 String packageName = pkgLite.packageName;
10509 int installLocation = pkgLite.installLocation;
10510 boolean onSd = (installFlags & PackageManager.INSTALL_EXTERNAL) != 0;
10511 // reader
10512 synchronized (mPackages) {
10513 PackageParser.Package pkg = mPackages.get(packageName);
10514 if (pkg != null) {
10515 if ((installFlags & PackageManager.INSTALL_REPLACE_EXISTING) != 0) {
10516 // Check for downgrading.
10517 if ((installFlags & PackageManager.INSTALL_ALLOW_DOWNGRADE) == 0) {
10518 try {
10519 checkDowngrade(pkg, pkgLite);
10520 } catch (PackageManagerException e) {
10521 Slog.w(TAG, "Downgrade detected: " + e.getMessage());
10522 return PackageHelper.RECOMMEND_FAILED_VERSION_DOWNGRADE;
10523 }
10524 }
而checkDowngrade 的实现如下:
可以看到16556 行和16560行会检查当前apk的版本和之前apk的版本,如果小于等于之前的版本则抛出异常,安装停止
16554 private static void checkDowngrade(PackageParser.Package before, PackageInfoLite after)
16555 throws PackageManagerException {
16556 if (after.versionCode < before.mVersionCode) {
16557 throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE,
16558 "Update version code " + after.versionCode + " is older than current "
16559 + before.mVersionCode);
16560 } else if (after.versionCode == before.mVersionCode) {
16561 if (after.baseRevisionCode < before.baseRevisionCode) {
16562 throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE,
16563 "Update base revision code " + after.baseRevisionCode
16564 + " is older than current " + before.baseRevisionCode);
16565 }
16566
16567 if (!ArrayUtils.isEmpty(after.splitNames)) {
16568 for (int i = 0; i < after.splitNames.length; i++) {
16569 final String splitName = after.splitNames[i];
16570 final int j = ArrayUtils.indexOf(before.splitNames, splitName);
16571 if (j != -1) {
16572 if (after.splitRevisionCodes[i] < before.splitRevisionCodes[j]) {
16573 throw new PackageManagerException(INSTALL_FAILED_VERSION_DOWNGRADE,
16574 "Update split " + splitName + " revision code "
16575 + after.splitRevisionCodes[i] + " is older than current "
16576 + before.splitRevisionCodes[j]);
16577 }
16578 }
16579 }
16580 }
16581 }
16582 }
16583
所以只要不调用checkDowngrade就可以检测低版本的apk。我们注意到checkDowngrade 被调用的条件是设定PackageManager.INSTALL_ALLOW_DOWNGRADE,所以只要设定这个flag,就可以安装低版本的apk.