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

来源:互联网 发布:八岐大蛇 蓝牙 mac 编辑:程序博客网 时间:2024/06/05 17:08

直接上干货:

            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;496497        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        }513514        if (DEBUG_JAR)515            Slog.d(TAG, "Scanning package: " + mArchiveSourcePath);516517        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        }552553554        if (pkg == null) {555            // If we are only parsing core apps, then a null with INSTALL_SUCCEEDED556            // 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        }573574        parser.close();575        assmgr.close();576577        // Set code and resource paths578        pkg.mPath = destCodePath;579        pkg.mScanPath = mArchiveSourcePath;580        //pkg.applicationInfo.sourceDir = destCodePath;581        //pkg.applicationInfo.publicSourceDir = destRes;582        pkg.mSignatures = null;583584        return pkg;585    }
过程中实例了AssetManager 和Resources 

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

2 0
原创粉丝点击