• Andriod 切换主题(APK主题包)


    Android apk主题切换方式有很多种,比较传统的方法是:

    1.为APK定制多个style/theme内容,供用户动态切换【优点:实现简单方便;缺点:主题固定,新增麻烦】

    2.作为资源放置到SD卡下,再进行读取(暂无)

    当前目前有一种方式可以通过新建一个资源apk,主应用去获取资源apk的主题,这种方法可以有效的减小主应用的大小。新增主题类型方便。缺点就是实现过程较麻烦

    实现原理:

    1.新建资源apk,该资源APK只要提供必要的资源文件[style、theme、pic等]供主应用调用即可

    2.主应用调用通过PackageManager类来实现

    详细说明下主应用的实现方法

    通过浏览Android系统PackageManager的源码,PackageManager提供了如下的方法

      /**
         * Retrieve overall information about an application package that is
         * installed on the system.
         * <p>
         * Throws {@link NameNotFoundException} if a package with the given name can
         * not be found on the system.
         *
         * @param packageName The full name (i.e. com.google.apps.contacts) of the
         *            desired package.
         * @param flags Additional option flags. Use any combination of
         *            {@link #GET_ACTIVITIES}, {@link #GET_GIDS},
         *            {@link #GET_CONFIGURATIONS}, {@link #GET_INSTRUMENTATION},
         *            {@link #GET_PERMISSIONS}, {@link #GET_PROVIDERS},
         *            {@link #GET_RECEIVERS}, {@link #GET_SERVICES},
         *            {@link #GET_SIGNATURES}, {@link #GET_UNINSTALLED_PACKAGES} to
         *            modify the data returned.
         * @return Returns a PackageInfo object containing information about the
         *         package. If flag GET_UNINSTALLED_PACKAGES is set and if the
         *         package is not found in the list of installed applications, the
         *         package information is retrieved from the list of uninstalled
         *         applications (which includes installed applications as well as
         *         applications with data directory i.e. applications which had been
         *         deleted with {@code DONT_DELETE_DATA} flag set).
         * @see #GET_ACTIVITIES
         * @see #GET_GIDS
         * @see #GET_CONFIGURATIONS
         * @see #GET_INSTRUMENTATION
         * @see #GET_PERMISSIONS
         * @see #GET_PROVIDERS
         * @see #GET_RECEIVERS
         * @see #GET_SERVICES
         * @see #GET_SIGNATURES
         * @see #GET_UNINSTALLED_PACKAGES
         */
        public abstract PackageInfo getPackageInfo(String packageName, int flags)
                throws NameNotFoundException;

     根据注释,该方法需要提供资源apk完整的包名(packageName)及附加选项(flags,该选项会影响方法的参数返回)

     要获取资源APK的resource资源,该类为我们提供了getResourcesForApplication方法

        /**
         * Retrieve the resources for an application.  Throws NameNotFoundException
         * if the package is no longer installed.
         *
         * @param app Information about the desired application.
         *
         * @return Returns the application's Resources.
         * @throws NameNotFoundException Thrown if the resources for the given
         * application could not be loaded (most likely because it was uninstalled).
         */
        public abstract Resources getResourcesForApplication(ApplicationInfo app)
                throws NameNotFoundException;

    该方法的参数我们可以从上一个方法中返回的PackageInfo对象中获取(packageInfo.applicationInfo)

    到这里我们已经成功拿到了资源APK的所有Resources 文件。剩下的就是怎么获取到特定的资源并且使用它。

    使用资源文件,一般我们是通过该资源的ID使用该资源(asset资源除外),所以只要我们能够拿到资源的ID,我们就有办法使用该资源。很幸运,Resources类给我们提供了如下的方法:

       /**
         * Return a resource identifier for the given resource name.  A fully
         * qualified resource name is of the form "package:type/entry".  The first
         * two components (package and type) are optional if defType and
         * defPackage, respectively, are specified here.
         * 
         * <p>Note: use of this function is discouraged.  It is much more
         * efficient to retrieve resources by identifier than by name.
         * 
         * @param name The name of the desired resource.
         * @param defType Optional default resource type to find, if "type/" is
         *                not included in the name.  Can be null to require an
         *                explicit type.
         * @param defPackage Optional default package to find, if "package:" is
         *                   not included in the name.  Can be null to require an
         *                   explicit package.
         * 
         * @return int The associated resource identifier.  Returns 0 if no such
         *         resource was found.  (0 is not a valid resource ID.)
         */
        public int getIdentifier(String name, String defType, String defPackage) {
            if (name == null) {
                throw new NullPointerException("name is null");
            }
            try {
                return Integer.parseInt(name);
            } catch (Exception e) {
                // Ignore
            }
            return mAssets.getResourceIdentifier(name, defType, defPackage);
        }

    该方法需要传递如下的参数

    (name:需要查找的资源名称,比如你的资源APK中有一张test.jpg的图片,想知道它的id,name="test")

     (defType:待查找的资源类型,可以是"layout","dimen"等)

    (defpackage:在哪个包下查找)

    如果未找到 资源文件,该方法将返回0.

    //--------------------------------------------------------------------

    代码实现:(待补充)

  • 相关阅读:
    XML指南——XML 瀏覽器(Netscape、Explorer)
    XML指南——察看 XML 文件
    ASP中Dictionary的使用
    SQL Mobile的RDA数据同步开发
    XML指南——XML 確認
    简单的js分页脚本
    浏览器语种检测,适合于多语言版本的站点
    Com/Dcom/Com+的思考
    XML指南——XML數據島
    MOSS 2007 功能概述
  • 原文地址:https://www.cnblogs.com/IntelligentBrain/p/4938850.html
Copyright © 2020-2023  润新知