標籤:
另外一種實現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;@Overrideprotected 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() {@Overridepublic void onClick(View v) {swtichImgUsePlugin();}});mShowImg = (ImageView) this.findViewById(R.id.myShowImg);new AsyncTask<Void, Void, Void>() {@Overrideprotected Void doInBackground(Void... params) {findPluginPackageName();return null;}@Overrideprotected void onPostExecute(Void result) {swtichImgUsePlugin();super.onPostExecute(result);}}.execute();}private void findPluginPackageName() {PackageManager pm = context.getPackageManager();List<PackageInfo> list = pm.getInstalledPackages(0);//得到全部安裝的apk的PackageInfoString 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的值推斷是否是自己的外掛程式apkmPluginPackageNameList.add(aInfo.packageName);}}}//必須在主線程中操作private void swtichImgUsePlugin() {//我這裡為了方便直接就取了第一個外掛程式apk資料。實際中是通過使用者選擇的apk來切換if (mPluginPackageNameList.size() != 0) {try {//通過createPackageContext方法得到外掛程式apk的contextContext 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");//通過反射得到對應位置的drawableMethod 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();}}}}
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvaHVhbmd5YW5iaW4xMjM=/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" >
android應用Theme(二)