Android Replacement Skin Solution
Reprint please indicate source: It_xiao Witch
This blog to share with you about the Android application skin-changing demo, you can go to my github to download the demo, the post-related code will be uploaded to GitHub unified management.
GitHub Address: Https://github.com/devilWwj/Android-skin-update
Ideas
What does the skin changing function usually have?
Elements usually have background color, font color, picture, layout, etc.
We know that there are themes in Android theme and Style,theme are for the entire activity, and the style can be used for the specified control, if a relatively small number of substitutions can be done within the app, but if you need to do it dynamically, you can choose the following idea:
Separate the app from the skin, make the skin an apk, and use it as a plugin for the app, so you can download the skins online and change the skin dynamically.
Below this demo, the wizard is built a res project, simply provides a colors.xml, which specifies the background color and button color:
<?xml version="1.0" encoding="utf-8"?><resources> <color name="day_btn_color">#E61ABD</color> <color name="day_background">#38F709</color> <color name="night_btn_color">#000000</color> <color name="night_background">#FFFFFF</color></resources>
There is no logic code, just provide the resource file, then we export to skin.apk file, copied to the target project's assets.
Because this does not involve the download of the skin this operation, so directly into the assets directory, and then in the program to copy the assets apk file into the SD card.
Provide a skin Pack manager in the program
PackageCom.devilwwj.skin;ImportJava.io.File;ImportJava.io.FileNotFoundException;ImportJava.io.FileOutputStream;ImportJava.io.IOException;ImportJava.io.InputStream;ImportJava.lang.reflect.Method;ImportAndroid.content.Context;ImportAndroid.content.pm.PackageInfo;ImportAndroid.content.pm.PackageManager;ImportAndroid.content.res.AssetManager;ImportAndroid.content.res.Resources;ImportAndroid.os.AsyncTask;/** * Skin Pack Manager * * @author DEVILWWJ * * */ Public class skinpackagemanager { Private StaticSkinpackagemanager minstance;PrivateContext Mcontext;/** * Current Resource Bundle name */ PublicString Mpackagename;/** * Skin resources * * PublicResources mresources; Public Skinpackagemanager(Context Mcontext) {Super(); This. Mcontext = Mcontext; }/** * Get a single example * * @param mcontext * @return * * Public StaticSkinpackagemanagergetinstance(Context Mcontext) {if(Minstance = =NULL) {minstance =NewSkinpackagemanager (Mcontext); }returnMinstance; }/** * Copy apk into SD from assets * * @param context * @param filename * @param Path * @return * / Public Boolean copyapkfromassets(context context, string filename, string path) {BooleanCopyisfinish =false;Try{//Open the assets input streamInputStream is = Context.getassets (). open (filename); File File =NewFile (path);//Create a new fileFile.createnewfile (); FileOutputStream fos =NewFileOutputStream (file);byte[] temp =New byte[1024x768];inti =0; while((i = is.read (temp)) >0) {Fos.write (temp,0+ N);//write to file} fos.close (); Is.close (); Copyisfinish =true; }Catch(FileNotFoundException e) {E.printstacktrace (); }Catch(IOException e) {E.printstacktrace (); }returnCopyisfinish; }/** * Load Skin Resources Asynchronously * * @param Dexpath * Required skin resources to load * @param Callback * Callback interface * / Public void Loadskinasync(String Dexpath,FinalLoadskincallback callback) {NewAsynctask<string, Void, resources> () {@Override protected void OnPreExecute() {Super. OnPreExecute ();if(Callback! =NULL) {Callback.startloadskin (); } }@Override protectedResourcesDoinbackground(String ... params) {Try{if(Params.length = =1) {//String dexpath_tmp = params[0];//Get Package ManagerPackagemanager MPM = Mcontext.getpackagemanager ();//Get package InfoPackageInfo mInfo = Mpm.getpackagearchiveinfo (dexpath_tmp, packagemanager.get_activities); Mpackagename = Minfo.packagename;//Assetmanager instancesAssetmanager Assetmanager = Assetmanager.class. newinstance ();//Call the Addassetpath method by reflectionMethod Addassetpath = Assetmanager.getclass (). GetMethod ("Addassetpath", String.class); Addassetpath.invoke (Assetmanager, dexpath_tmp);//Get resource instancesResources superres = Mcontext.getresources ();//Instantiate skin resourcesResources Skinresource =NewResources (Assetmanager, Superres.getdisplaymetrics (), Superr Es.getconfiguration ());//Save resource PathSkinconfig.getinstance (Mcontext). Setskinresourcepath (DEXPATH_TMP);returnSkinresource; } }Catch(Exception e) {return NULL; }return NULL; }@Override protected void OnPostExecute(Resources result) {Super. OnPostExecute (Result); Mresources = result;//Execute callback method here 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(); }}
The focus is on this class, which provides an asynchronous way to manipulate packages and asset, where the reflection mechanism is used, and reflection calls Addassetpath to add assets path, which is the path of our skin.apk. See the code for specifics.
We use the methods provided above in the activity interface:
PackageCom.devilwwj.skin;Importandroid.app.Activity;ImportAndroid.content.res.Resources;ImportAndroid.os.Bundle;ImportAndroid.os.Environment;ImportAndroid.util.Log;ImportAndroid.view.View;ImportAndroid.view.View.OnClickListener;ImportAndroid.widget.Button;ImportAndroid.widget.TextView;ImportCom.devilwwj.skin.SkinPackageManager.loadSkinCallBack;/** * Function: Toggle skin * @author DEVILWWJ * */ Public class mainactivity extends Activity implements Onclicklistener, iskinupdate { Private Static FinalString Apk_name ="skin.apk";Private Static FinalString Dex_path = environment. getExternalStorageDirectory (). GetAbsolutePath () +"/skin.apk";PrivateButton Daybutton;PrivateButton Nightbutton;PrivateTextView TextView;Private BooleanNightmodel =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);//Copy the APK file to the SD cardSkinpackagemanager.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 ()) { CaseR.id.btn_day:nightmodel =false; Loadskin (); Break; CaseR.id.btn_night:nightmodel =true; Loadskin (); Break;default: Break; } }/** * Loading skin * * Private void Loadskin() {skinpackagemanager.getinstance ( This). Loadskinasync (Dex_path,NewLoadskincallback () {@Override Public void Startloadskin() {LOG.D ("Xiaowu","Startloadskin"); }@Override Public void loadskinsuccess() {LOG.D ("Xiaowu","Loadskinsuccess");//Then update the theme hereUpdatetheme (); }@Override Public void Loadskinfail() {LOG.D ("Xiaowu","Loadskinfail"); } }); }@Override Public void Updatetheme() {Resources mresource = skinpackagemanager.getinstance ( This). Mresources;if(Nightmodel) {//If it is night mode, load the theme of the night intID1 = Mresource.getidentifier ("Night_btn_color","Color","Com.devilwwj.res"); Nightbutton.setbackgroundcolor (Mresource.getcolor (ID1));intId2 = Mresource.getidentifier ("Night_background","Color","Com.devilwwj.res"); Nightbutton.settextcolor (Mresource.getcolor (ID2)); Textview.settextcolor (Mresource.getcolor (ID2)); }Else{//If it is daylight mode, load the daytime theme intID1 = Mresource.getidentifier ("Day_btn_color","Color","Com.devilwwj.res"); Daybutton.setbackgroundcolor (Mresource.getcolor (ID1));intId2 = Mresource.getidentifier ("Day_background","Color","Com.devilwwj.res"); Daybutton.settextcolor (Mresource.getcolor (ID2)); Textview.settextcolor (Mresource.getcolor (ID2)); } }}
We can save a pattern, such as the night daytime mode, each time it starts to display the skin in the previously saved mode. We can see that the above is the name that we specify in the resource file by calling the Getidentifier method to get the specified resource id,name.
Finally, you run through the process yourself:
1. Export the res apk file
2. Copy to the assets directory of the target project
3. View the effect of switching skins
Reference post: http://blog.csdn.net/yuanzeyao/article/details/42390431
Android Replacement Skin Solution