Android 动态加载 之 如何获取插件res资源

直接上干货:

            PackageManager pm = mContext.getPackageManager();
            PackageInfo pi = pm.getPackageArchiveInfo(mFilename, 0);
	     mNewResources = pm.getResourcesForApplication(pi.applicationInfo);

要获取插件的资源信息我们采用的是通过实例packageInfo,并动态的更改里边的sourceDir和publicSourceDir为插件Apk路径地址。

而这里关键的是什么时候去加载的资源信息呢:

1,pm.getPackageArchiveInfo

    public PackageInfo getPackageArchiveInfo(String archiveFilePath, int flags) {
        PackageParser packageParser = new PackageParser(archiveFilePath);
        DisplayMetrics metrics = new DisplayMetrics();
        metrics.setToDefaults();
        final File sourceFile = new File(archiveFilePath);
        PackageParser.Package pkg = packageParser.parsePackage(
                sourceFile, archiveFilePath, metrics, 0);
        if (pkg == null) {
            return null;
        }
        if ((flags & GET_SIGNATURES) != 0) {
            packageParser.collectCertificates(pkg, 0);
        }
        PackageUserState state = new PackageUserState();
        return PackageParser.generatePackageInfo(pkg, null, flags, 0, 0, null, state);
    }


如图,在执行取packageArchiveInfo的时候,回去解析包文件,具体看源码:

493    public Package parsePackage(File sourceFile, String destCodePath,
494            DisplayMetrics metrics, int flags) {
495        mParseError = PackageManager.INSTALL_SUCCEEDED;
496
497        mArchiveSourcePath = sourceFile.getPath();
498        if (!sourceFile.isFile()) {
499            Slog.w(TAG, "Skipping dir: " + mArchiveSourcePath);
500            mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
501            return null;
502        }
503        if (!isPackageFilename(sourceFile.getName())
504                && (flags&PARSE_MUST_BE_APK) != 0) {
505            if ((flags&PARSE_IS_SYSTEM) == 0) {
506                // We expect to have non-.apk files in the system dir,
507                // so don't warn about them.
508                Slog.w(TAG, "Skipping non-package file: " + mArchiveSourcePath);
509            }
510            mParseError = PackageManager.INSTALL_PARSE_FAILED_NOT_APK;
511            return null;
512        }
513
514        if (DEBUG_JAR)
515            Slog.d(TAG, "Scanning package: " + mArchiveSourcePath);
516
517        XmlResourceParser parser = null;
518        AssetManager assmgr = null;
519        Resources res = null;
520        boolean assetError = true;
521        try {
522            assmgr = new AssetManager();
523            int cookie = assmgr.addAssetPath(mArchiveSourcePath);
524            if (cookie != 0) {
525                res = new Resources(assmgr, metrics, null);
526                assmgr.setConfiguration(0, 0, null, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
527                        Build.VERSION.RESOURCES_SDK_INT);
528                parser = assmgr.openXmlResourceParser(cookie, ANDROID_MANIFEST_FILENAME);
529                assetError = false;
530            } else {
531                Slog.w(TAG, "Failed adding asset path:"+mArchiveSourcePath);
532            }
533        } catch (Exception e) {
534            Slog.w(TAG, "Unable to read AndroidManifest.xml of "
535                    + mArchiveSourcePath, e);
536        }
537        if (assetError) {
538            if (assmgr != null) assmgr.close();
539            mParseError = PackageManager.INSTALL_PARSE_FAILED_BAD_MANIFEST;
540            return null;
541        }
542        String[] errorText = new String[1];
543        Package pkg = null;
544        Exception errorException = null;
545        try {
546            // XXXX todo: need to figure out correct configuration.
547            pkg = parsePackage(res, parser, flags, errorText);
548        } catch (Exception e) {
549            errorException = e;
550            mParseError = PackageManager.INSTALL_PARSE_FAILED_UNEXPECTED_EXCEPTION;
551        }
552
553
554        if (pkg == null) {
555            // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED
556            // just means to skip this app so don't make a fuss about it.
557            if (!mOnlyCoreApps || mParseError != PackageManager.INSTALL_SUCCEEDED) {
558                if (errorException != null) {
559                    Slog.w(TAG, mArchiveSourcePath, errorException);
560                } else {
561                    Slog.w(TAG, mArchiveSourcePath + " (at "
562                            + parser.getPositionDescription()
563                            + "): " + errorText[0]);
564                }
565                if (mParseError == PackageManager.INSTALL_SUCCEEDED) {
566                    mParseError = PackageManager.INSTALL_PARSE_FAILED_MANIFEST_MALFORMED;
567                }
568            }
569            parser.close();
570            assmgr.close();
571            return null;
572        }
573
574        parser.close();
575        assmgr.close();
576
577        // Set code and resource paths
578        pkg.mPath = destCodePath;
579        pkg.mScanPath = mArchiveSourcePath;
580        //pkg.applicationInfo.sourceDir = destCodePath;
581        //pkg.applicationInfo.publicSourceDir = destRes;
582        pkg.mSignatures = null;
583
584        return pkg;
585    }
过程中实例了AssetManager 和Resources 

这样在后边调用的时候无论是实例新的ContextThemeWrapper,还是取用资源对象都可以通过getResources()拿到,供动态加载插件资源所用。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值