插件包括使用zip、jar、dex、apk(未安装、安装)
public class MainActivity extends Activity {
private ImageView imageSource;
private ImageView imageCloud;
private final static String SRC_TAG = "srcTag";
private final static String CLOUD_TAG = "cloud";
@Override
protected void onCreate(Bundle savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
initView();
}
private void initView() {
imageSource = (ImageView)findViewById(R.id.imageSource);
imageCloud = (ImageView)findViewById(R.id.imageCloud);
imageSource.setTag(SRC_TAG);
imageCloud.setTag(CLOUD_TAG);
imageSource.setOnClickListener(this);
imageCloud.setOnClickListener(this);
}
@Override
public void onClick(View v) {
if(v.getTag().equals(SRC_TAG)){
//点到了本地动画
handleAnim(v);
}else if(v.getTag().equals(CLOUD_TAG)){
//插件动画
String fileName = CLOUD_TAG+".apk";
//this.getCacheDir()获取/data/data//cache目录
String filePath = this.getCacheDir()+File.separator+fileName;
String packageName = "com.dn."+CLOUD_TAG;
File apkFile = new File(filePath);
if(apkFile.exists()){
//直接加载插件
Drawable backGround = v.getBackground();
if(backGround instanceof AnimationDrawable){
handleAnim(v);
}else{
//第一次加载插件
try{
AssetManager assetManager = PluginResources.getPluginAssetManager(apkFile);
//插件的resource对象
Resources resources = PluginResources.getPluginResources(getResource(),assetManager);
DexClassLoader classLoader = new DexClassLoader(apkFile.getAbsolutePath(),this.getDir(fileName,Context.MODE_PRIVATE).getAbsolutePath(),null,getClassLoader());
Class<?> loadClass = classLoader.loadClass(packageName+".R$anim");
Field[] declaredFields = loadClass.getDeclaredFields();
for(Field field : declaredFields){
if(field.getName().equals(CLOUD_TAG)){
//云的animId
int animId = field.getInt(R.anim.class);
//插件的动画
Drawable drawable = resources.getDrawable(animId);
((ImageView)v).setBackgroundDrawable(drawable);
handleAnim(v);
}
}
}catch(Exception e){
e.printStackTrace();
}
}
}else{
//下载插件
InputStream is = null;
FileOutputStream os = null;
try{
is = this.getAssets().open(fileName);
os = new FileOutputStream(filePath);
int len=0;
byte[] buffer = new byte[1024];
while((len=is.read(buffer))!=-1){
os.write(buffer,0,len);
}
Toast.makeText(this,"下载完成",Toast.LENGTH_LONG).show();
}catch(Exception e){
e.printStackTrace();
}finally {
try{
if(is!=null){
is.close();
}
if(os!=null){
os.close();
}
}catch(Exception e){
e.printStackTrace();
}
}
}
}
}
private void handleAnim(View v) {
AnimationDrawable drawable = (AnimationDrawable)v.getBackground();
if(drawable!=null){
if(drawable.isRunning()){
drawable.stop();
}else{
drawable.stop();
drawable.start();
}
}
}
}
插件化
自己定义加载资源的Resource类
public class PlguinResources extends Resources {
public PlguinResources(AssetManager assets, DisplayMetrics metrics, Configuration config){
super(assets, metrics,config);
}
//自己加载插件的apk来返回插件的Resources
public static PluginResources getPluginResources(Resources res,AssetManager assets){
PluginResources pluginResources = new PluginResources(assets,res.getDisplayMetrics(),res.getConfiguration());
return pluginResources ;
}
//自己定义assetsManager
public static AssetManager getPluginAssetManager(File apkFile) throws ClassNotFoundException{
Class<?> forName = Class.forName("android.content.res.AssetManager");
Method[] declaredMethods = forName.getDeclaredMethods();
for(Method method:declaredMethods){
if(method.getName().equals("addAssetPath")){
try{
AssetManager assetManager = AssetManager.class.newInstance();
method.invoke(assetManager,apkFile.getAbsolutePath());
return assetManager;
}catch(Exception e){
e.printStackTrace();
}
}
}
return null;
}
}