zoukankan      html  css  js  c++  java
  • android应用Theme(二)

    另外一种实现android应用Theme的方式是通过apk来实现的。

    以下是一个demo。

    1.首先必须新建一个apk。类似的插件,然后在该apk的AndroidManifest.xml文件的application加上一个meta-data。这个是下一步查找是否是自己的插件的apk做一个标记。

    <meta-data android:name="skin_demo2_plugin" android:value="com.example.skindemo2.icon"/>
    
    2.在该apk加入一些图片,也能够用其它(包含style等)这里主要是为了演示。在该apk的MainActivity定义一个方法。

    这里主要为了方便主apk高速调用这种方法。

    static int allDrawableId[] = {R.drawable.img_apparel_accessories,R.drawable.img_computers_software
    		,R.drawable.img_electro,R.drawable.img_electronics,R.drawable.img_entertaiment
    		,R.drawable.img_food_beverage,R.drawable.img_kids_baby,R.drawable.img_sport,R.drawable.img_toys_games};
    	
    	public int getDrawableIdForOtherApp(int position){
    		
    		if(position < allDrawableId.length){
    			return allDrawableId[position];
    		}
    		return 0;	
    	}

    3.在主apk中通过读取全部安装的应用,通过分析applicationInfo的meta-data。然后推断是否是自己的插件apk。

    然后通过context.createPackageContext(packageName,int flag)得到对应插件的context。然后通过类载入器得到MainActivity的class类。然后通过反射得到方法返回的值。然后就能够得到drawable对象。

    package com.example.skindemo2;
    import java.lang.reflect.Method;
    import java.util.ArrayList;
    import java.util.List;
    import android.os.AsyncTask;
    import android.os.Bundle;
    import android.app.Activity;
    import android.content.Context;
    import android.content.pm.ApplicationInfo;
    import android.content.pm.PackageInfo;
    import android.content.pm.PackageManager;
    import android.content.pm.PackageManager.NameNotFoundException;
    import android.graphics.drawable.Drawable;
    import android.view.View;
    import android.widget.Button;
    import android.widget.ImageView;
    
    public class MainActivity extends Activity {
    
    	private Button mSwtichImgBgBtn;
    	private ImageView mShowImg;
    	private Context context;
    	private ArrayList<String> mPluginPackageNameList = new ArrayList<String>();
    	private int position = 0;
    
    	@Override
    	protected void onCreate(Bundle savedInstanceState) {
    		super.onCreate(savedInstanceState);
    		setContentView(R.layout.activity_main);
    		context = this;
    		mSwtichImgBgBtn = (Button) this.findViewById(R.id.swtichImgBgBtn);
    		mSwtichImgBgBtn.setOnClickListener(new View.OnClickListener() {
    			
    			@Override
    			public void onClick(View v) {
    				swtichImgUsePlugin();
    			}
    		});
    		mShowImg = (ImageView) this.findViewById(R.id.myShowImg);
    		new AsyncTask<Void, Void, Void>() {
    
    			@Override
    			protected Void doInBackground(Void... params) {
    				findPluginPackageName();
    				return null;
    			}
    			
    			@Override
    			protected void onPostExecute(Void result) {
    				swtichImgUsePlugin();
    				super.onPostExecute(result);
    			}
    		}.execute();
    
    	}
    
    	private void findPluginPackageName() {
    		PackageManager pm = context.getPackageManager();
    		List<PackageInfo> list = pm.getInstalledPackages(0);//得到全部安装的apk的PackageInfo
    		String meta = null;
    		ApplicationInfo aInfo = null;
    		for (PackageInfo pi : list) {
    			String pkgName = pi.packageName;
    			try {
    				aInfo = pm.getApplicationInfo(pkgName,
    						PackageManager.GET_META_DATA);
    			} catch (NameNotFoundException e) {
    				e.printStackTrace();
    			}
    			if (aInfo == null || aInfo.metaData == null)
    				continue;
    			meta = aInfo.metaData.getString("skin_demo2_plugin");
    			if (meta == null || "".equals(meta))
    				continue;
    			if ("com.example.skindemo2.icon".equals(meta)) {
    				//通过meta的值推断是否是自己的插件apk
    				mPluginPackageNameList.add(aInfo.packageName);
    			}
    		}
    	}
    	//必须在主线程中操作
    	private void swtichImgUsePlugin() {
    		//我这里为了方便直接就取了第一个插件apk数据。实际中是通过用户选择的apk来切换
    		if (mPluginPackageNameList.size() != 0) {
    			try {
    				//通过createPackageContext方法得到插件apk的context
    				Context otherplusContext = context.createPackageContext(
    						mPluginPackageNameList.get(0),
    						Context.CONTEXT_INCLUDE_CODE
    								| Context.CONTEXT_IGNORE_SECURITY);
    				//通过得到插件apk的context类载入器,然后得到MainActvity的类对象
    				Class<?> mainClass = otherplusContext
    						.getClassLoader()
    						.loadClass(mPluginPackageNameList.get(0) + ".MainActivity");
    				//通过反射得到对应位置的drawable
    				Method m = mainClass.getMethod("getDrawableIdForOtherApp",
    						int.class);
    				int imgBgId = (Integer) m.invoke(mainClass.newInstance(), position);
    				//为了能够循环切换img
    				 if(imgBgId == 0){
    					 position = 0;
    				 }else{
    					 position += 1;
    				 }
    				 //得到drawable对象
    				Drawable drawable = otherplusContext.getResources()
    						.getDrawable(imgBgId);
    				mShowImg.setImageDrawable(drawable);
    			} catch (Exception e) {
    				e.printStackTrace();
    			}
    		}
    
    	}
    }
    





  • 相关阅读:
    sqlserver 配置管理器中无法启动sqlserver服务
    9.4笔记
    ASP.NET 正则表达式验证
    ASP.NET之OnClientClick 事件
    ASP.NET之js 根据textbox变化刷新相关数据
    SQL
    leetcode:Roman to Integer(罗马数字转化为罗马数字)
    leetcode:Integer to Roman(整数转化为罗马数字)
    leetcode:Palindrome Number
    leetcode:String to Integer (atoi)
  • 原文地址:https://www.cnblogs.com/gcczhongduan/p/5362151.html
Copyright © 2011-2022 走看看