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.
//--------------------------------------------------------------------
代码实现:(待补充)