美文网首页
Android12适配 Targeting R+(versio

Android12适配 Targeting R+(versio

作者: 顽固的石头 | 来源:发表于2021-12-25 14:45 被阅读0次

    在使用命令行打包apk时,由于命令行打包直接将resources.arsc进行压缩,会导致这个问题出现,从而在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机型,就会出现以上的问题。

    解决方法是,在压缩的使用,判断是否是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());
            }
    

    相关文章

      网友评论

          本文标题:Android12适配 Targeting R+(versio

          本文链接:https://www.haomeiwen.com/subject/shpdqrtx.html