换肤框架的资源

换肤需要对应的资源,那么资源有哪些来源呢?

1.apk打包的时候,有几个默认的资源被打包进APK中。

2.从网络下载,放到指定的路径。


根据上一章的SkinManager的内容:

@Override
protected Resources doInBackground(String... params) {
    try {
        if (params.length == 1) {
            String skinPkgPath = params[0];
            Log.e("loadSkin", skinPkgPath);///storage/emulated/0/Android/data/ren.solid.materialdesigndemo/cache/skin/skin_brown.skin
            File file = new File(skinPkgPath);
            if (file == null || !file.exists()) {
                return null;
            }

            PackageManager mPm = context.getPackageManager();
            PackageInfo mInfo = mPm.getPackageArchiveInfo(skinPkgPath, PackageManager.GET_ACTIVITIES);
            skinPackageName = mInfo.packageName;

            AssetManager assetManager = AssetManager.class.newInstance();
            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
            addAssetPath.invoke(assetManager, skinPkgPath);


            Resources superRes = context.getResources();
            Resources skinResource = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());

            SkinConfig.saveSkinPath(context, skinPkgPath);

            skinPath = skinPkgPath;
            isDefaultSkin = false;
            return skinResource;
        }
        return null;
    } catch (Exception e) {
        e.printStackTrace();
        return null;
    }
}
他做了三件事

第一步:他获取指定路径的包名:

 PackageManager mPm = context.getPackageManager();
            PackageInfo mInfo = mPm.getPackageArchiveInfo(skinPkgPath, PackageManager.GET_ACTIVITIES);
            skinPackageName = mInfo.packageName;
步:使用asset加载器加载对应的asset资源:
 AssetManager assetManager = AssetManager.class.newInstance();
            Method addAssetPath = assetManager.getClass().getMethod("addAssetPath", String.class);
            addAssetPath.invoke(assetManager, skinPkgPath);
第三步:根据加载器生成Resources对象:

            Resources superRes = context.getResources();
            Resources skinResource = new Resources(assetManager, superRes.getDisplayMetrics(), superRes.getConfiguration());
完成这三步之后就可以获取对应资源的Resources对象了,我们就可以使用Resource中的资源了,对应换肤就可以实现了。



这上面的三步,本质都是找到资源的路径然后生成对应的Resources对象。


1.apk打包的时候,有几个默认的资源被打包进APK中。

Myapplication.apk(主应用程序)
skin.apk(只包含资源的apk文件,皮肤apk,apk本质是压缩文件)
它们在Android studio中的结构是这样的:

Skin的结构里面什么都没有,除了需要替换的资源文件:结构如下:



怎么创建assets文件夹网上有就不说了。然后将应用打包,安卓到手机之后,assets文件夹下面的文件就被保存在系统统一管理assets文件的路径下了,这个区域我在百度上找了很久,也试了很多最终不能以路径的形式找出来,而只能调用assetsManager的open方法打开对应文件名的inputstream数据流。


只能这样的话,就只有一个思路了,那就是采用异步的形式将inputstream数据流copy到应用的cache文件夹(这个路径获取网上也有,不说了),具体代码如下:

public class Copyutil {

    public static boolean copyApkFromAssets(Context context, String fileName ) {
        boolean copyIsFinish = false;
        String  path= context.getExternalCacheDir() + File.separator + "skin.apk";
        try {
            InputStream is = context.getAssets().open(fileName); //关键的代码
            File file = new File(path);
            file.createNewFile();
            FileOutputStream fos = new FileOutputStream(file);
            byte[] temp = new byte[1024];
            int i = 0;
            while ((i = is.read(temp)) > 0) {
                fos.write(temp, 0, i);
            }
            fos.close();
            is.close();
            copyIsFinish = true;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return copyIsFinish;
    }

    public static boolean isExistFile(String path){
        File f=new File(path);
        return f.exists();
    }
}
通过上面的代码,我们就可以将skin.apk复制到如下路径
//storage/emulated/0/Android/data/com.example.myapplication/cache/skin.apk

     接着调用SkinManager的load函数异步加载assets资源得到Resources对象。


2.从网络下载,放到指定的路径

原理同1,只不过通过网络把skin.apk下载到下面这个路径

//storage/emulated/0/Android/data/com.example.myapplication/cache/skin.apk

猜你喜欢

转载自blog.csdn.net/u012345683/article/details/73028552
今日推荐