Android更换皮肤解决方案,2021年哔哩哔哩Android高级面试题及答案

  • @param context

  • @param filename

  • @param path

  • @return

*/

public boolean copyApkFromAssets(Context context, String filename,

String path) {

boolean copyIsFinish = false;

try {

// 打开assets的输入流

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 (FileNotFoundException e) {

e.printStackTrace();

} catch (IOException e) {

e.printStackTrace();

}

return copyIsFinish;

}

/**

  • 异步加载皮肤资源

  • @param dexPath

  •        需要加载的皮肤资源
    
  • @param callback

  •        回调接口
    

*/

public void loadSkinAsync(String dexPath, final loadSkinCallBack callback) {

new AsyncTask<String, Void, Resources>() {

@Override

protected void onPreExecute() {

super.onPreExecute();

if (callback != null) {

callback.startloadSkin();

}

}

@Override

protected Resources doInBackground(String… params) {

try {

if (params.length == 1) {

//

String dexPath_tmp = params[0];

// 得到包管理器

PackageManager mpm = mContext.getPackageManager();

// 得到包信息

PackageInfo mInfo = mpm.getPackageArchiveInfo(

dexPath_tmp, PackageManager.GET_ACTIVITIES);

mPackageName = mInfo.packageName;

// AssetManager实例

AssetManager assetManager = AssetManager.class

.newInstance();

// 通过反射调用addAssetPath方法

Method addAssetPath = assetManager.getClass()

.getMethod(“addAssetPath”, String.class);

addAssetPath.invoke(assetManager, dexPath_tmp);

// 得到资源实例

Resources superRes = mContext.getResources();

// 实例化皮肤资源

Resources skinResource = new Resources(assetManager,

superRes.getDisplayMetrics(),

superRes.getConfiguration());

// 保存资源路径

SkinConfig.getInstance(mContext).setSkinResourcePath(

dexPath_tmp);

return skinResource;

}

} catch (Exception e) {

return null;

}

return null;

}

@Override

protected void onPostExecute(Resources result) {

super.onPostExecute(result);

mResources = result;

// 这里执行回调方法

if (callback != null) {

if (mResources != null) {

callback.loadSkinSuccess();

} else {

callback.loadSkinFail();

}

}

}

}.execute(dexPath);

}

public static interface loadSkinCallBack {

public void startloadSkin();

public void loadSkinSuccess();

public void loadSkinFail();

}

}

重点关注这个类,里面提供了一个异步方法对包和asset进行操作,这

《Android学习笔记总结+最新移动架构视频+大厂安卓面试真题+项目实战源码讲义》

【docs.qq.com/doc/DSkNLaERkbnFoS0ZF】 完整内容开源分享

里用到了反射机制,反射调用addAssetPath来添加assets的路径,这个路径就是我们skin.apk的路径。具体细节,各位查看代码。

我们在Activity界面中使用上面提供的方法:

package com.devilwwj.skin;

import android.app.Activity;

import android.content.res.Resources;

import android.os.Bundle;

import android.os.Environment;

import android.util.Log;

import android.view.View;

import android.view.View.OnClickListener;

import android.widget.Button;

import android.widget.TextView;

import com.devilwwj.skin.SkinPackageManager.loadSkinCallBack;

/**

  • 功能:切换皮肤

  • @author devilwwj

*/

public class MainActivity extends Activity implements OnClickListener,

ISkinUpdate {

private static final String APK_NAME = “skin.apk”;

private static final String DEX_PATH = Environment

.getExternalStorageDirectory().getAbsolutePath() + “/skin.apk”;

private Button dayButton;

private Button nightButton;

private TextView textView;

private boolean nightModel = false;

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

dayButton = (Button) findViewById(R.id.btn_day);

nightButton = (Button) findViewById(R.id.btn_night);

textView = (TextView) findViewById(R.id.text);

// 把apk文件复制到sd卡

SkinPackageManager.getInstance(this).copyApkFromAssets(this, APK_NAME,

DEX_PATH);

}

@Override

protected void onResume() {

super.onResume();

if (SkinPackageManager.getInstance(this).mResources != null) {

updateTheme();

}

}

@Override

public void onClick(View v) {

switch (v.getId()) {

case R.id.btn_day:

nightModel = false;

loadSkin();

break;

case R.id.btn_night:

nightModel = true;

loadSkin();

break;

default:

break;

}

}

/**

  • 加载皮肤

*/

private void loadSkin() {

SkinPackageManager.getInstance(this).loadSkinAsync(DEX_PATH,

new loadSkinCallBack() {

@Override

public void startloadSkin() {

Log.d(“xiaowu”, “startloadSkin”);

}

@Override

public void loadSkinSuccess() {

Log.d(“xiaowu”, “loadSkinSuccess”);

// 然后这里更新主题

updateTheme();

}

@Override

public void loadSkinFail() {

Log.d(“xiaowu”, “loadSkinFail”);

}

});

}

@Override

public void updateTheme() {

Resources mResource = SkinPackageManager.getInstance(this).mResources;

if (nightModel) {

// 如果是黑夜的模式,则加载黑夜的主题

int id1 = mResource.getIdentifier(“night_btn_color”, “color”,

“com.devilwwj.res”);

nightButton.setBackgroundColor(mResource.getColor(id1));

int id2 = mResource.getIdentifier(“night_background”, “color”,

“com.devilwwj.res”);

nightButton.setTextColor(mResource.getColor(id2));

textView.setTextColor(mResource.getColor(id2));

} else {

// 如果是白天模式,则加载白天的主题

int id1 = mResource.getIdentifier(“day_btn_color”, “color”,

“com.devilwwj.res”);

dayButton.setBackgroundColor(mResource.getColor(id1));

int id2 = mResource.getIdentifier(“day_background”, “color”,

“com.devilwwj.res”);

dayButton.setTextColor(mResource.getColor(id2));

textView.setTextColor(mResource.getColor(id2));

}

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值