Android12適配 Targeting R+(version 30 and above) requires the resources.arsc of installed APKs t...

在使用命令行打包apk時,由于命令行打包直接將resources.arsc進行壓縮,會導(dǎo)致這個問題出現(xiàn),從而在android11及Android12版本的機型上無法安裝,提示信息為:解析安裝包出錯,或者是Targeting R+(version 30 and above) requires the resources.arsc of installed APKs to be stored uncompressed and aligned on a 4-byte boundary]錯誤

在Android 11以及Android12 版本,對resources.arsc文件需要進行對齊,并且不壓縮,

源碼路徑為 framework/base/core/java - android.content.pm.parsing.ParsingPackageUtils

    private ParseResult<ParsingPackage> parseBaseApk(ParseInput input, File apkFile,
            String codePath, SplitAssetLoader assetLoader, int flags)
            throws PackageParserException {
        final String apkPath = apkFile.getAbsolutePath();

        String volumeUuid = null;
        if (apkPath.startsWith(MNT_EXPAND)) {
            final int end = apkPath.indexOf('/', MNT_EXPAND.length());
            volumeUuid = apkPath.substring(MNT_EXPAND.length(), end);
        }

        if (DEBUG_JAR) Slog.d(TAG, "Scanning base APK: " + apkPath);

        final AssetManager assets = assetLoader.getBaseAssetManager();
        final int cookie = assets.findCookieForPath(apkPath);
        if (cookie == 0) {
            return input.error(INSTALL_PARSE_FAILED_BAD_MANIFEST,
                    "Failed adding asset path: " + apkPath);
        }

        try (XmlResourceParser parser = assets.openXmlResourceParser(cookie,
                ANDROID_MANIFEST_FILENAME)) {
            final Resources res = new Resources(assets, mDisplayMetrics, null);

            ParseResult<ParsingPackage> result = parseBaseApk(input, apkPath, codePath, res,
                    parser, flags);
            if (result.isError()) {
                return input.error(result.getErrorCode(),
                        apkPath + " (at " + parser.getPositionDescription() + "): "
                                + result.getErrorMessage());
            }

            final ParsingPackage pkg = result.getResult();
            //判斷resources.arsc文件是否被壓縮且是否用zipalign對齊過,如果資源resources.arsc被壓縮了,或者沒有用zipalign對齊,那么就會拋出這 
            //個異常
            if (assets.containsAllocatedTable()) {
                final ParseResult<?> deferResult = input.deferError(
                        "Targeting R+ (version " + Build.VERSION_CODES.R + " and above) requires"
                                + " the resources.arsc of installed APKs to be stored uncompressed"
                                + " and aligned on a 4-byte boundary",
                        DeferredError.RESOURCES_ARSC_COMPRESSED);
                if (deferResult.isError()) {
                    return input.error(INSTALL_PARSE_FAILED_RESOURCES_ARSC_COMPRESSED,
                            deferResult.getErrorMessage());
                }
            }

            ApkAssets apkAssets = assetLoader.getBaseApkAssets();
            boolean definesOverlayable = false;
            try {
                definesOverlayable = apkAssets.definesOverlayable();
            } catch (IOException ignored) {
                // Will fail if there's no packages in the ApkAssets, which can be treated as false
            }

            if (definesOverlayable) {
                SparseArray<String> packageNames = assets.getAssignedPackageIdentifiers();
                int size = packageNames.size();
                for (int index = 0; index < size; index++) {
                    String packageName = packageNames.valueAt(index);
                    Map<String, String> overlayableToActor = assets.getOverlayableMap(packageName);
                    if (overlayableToActor != null && !overlayableToActor.isEmpty()) {
                        for (String overlayable : overlayableToActor.keySet()) {
                            pkg.addOverlayable(overlayable, overlayableToActor.get(overlayable));
                        }
                    }
                }
            }

            pkg.setVolumeUuid(volumeUuid);

            if ((flags & PARSE_COLLECT_CERTIFICATES) != 0) {
                pkg.setSigningDetails(getSigningDetails(pkg, false));
            } else {
                pkg.setSigningDetails(SigningDetails.UNKNOWN);
            }

            return input.success(pkg);
        } catch (Exception e) {
            return input.error(INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION,
                    "Failed to read manifest from " + apkPath, e);
        }
    }
    /**
     * Returns whether the {@code resources.arsc} of any loaded apk assets is allocated in RAM
     * (not mmapped).
     *
     * @hide
     */
    public boolean containsAllocatedTable() {
        synchronized (this) {
            ensureValidLocked();
            return nativeContainsAllocatedTable(mObject);
        }
    }

所以,如果是使用命令行去打包,且target是Android11以后的版本,那么在安裝到Android11以及Android12機型,就會出現(xiàn)以上的問題。

解決方法是,在壓縮的使用,判斷是否是resources.arsc ,則不進行壓縮,使用ZipEntry.STORED方式保存

        if ("resources.arsc".equals(file.getName())){
            entry.setMethod(ZipEntry.STORED);
            entry.setSize(file.length());
            entry.setCompressedSize(-1);
            BufferedInputStream unknownFile = new BufferedInputStream(new FileInputStream(file));
            CRC32 crc = calculateCrc(unknownFile);
            entry.setCrc(crc.getValue());
        }
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容