Here to talk about the ink on the way the implementation of the weather, but first of all, I simply decompile and refer to some other online data to speculate on the principle of skin, here for reference only. If you have a better way, welcome to the exchange.
Ink weather download of the skin is a zip format of the package, in the application of the skin resources released to the application of the ink in the directory, the replacement of skin resources will replace the old skin resources for the change of the elderly every time the load is from the mobile hard disk read pictures, The naming of these picture resources is consistent with the naming of resources in the program, and once these resources are not found, you can choose to find them in the system default. This implementation is a direct read of the external resource file, the background resource of the replacement interface that is displayed through code when the program runs. The advantage of this approach is that the skin resource format is very arbitrary can be a zip or a custom format, as long as the program can be resolved to the resources on the line, the disadvantage is the problem of efficiency.
One thing to note here is that the decompression of the package here is aided by a third-party tool: Ant. Jar to extract and compress the file. I'll explain the use of the Ant tool in a later article.
Main technical points:
How to read the resources in the zip file and how to store the skin files
Implementation scenario: If the software every boot to read the SD card skin files, the speed will be slow. A better approach is to provide a skin-setting interface in which the user chooses which skin to extract the skin file to the "/data/data/[package Name]/skin" path (fast and secure reading) so that it does not need to be read across the memory, faster, And do not need to go to the ZIP compression packet every time read, do not rely on the file in the SD card, even if the skin compression package file was deleted does not matter.
Implementation method:
1. In the software Help or the official website help prompts the user to copy the skin file to the SD card specified path.
2. Provide the skin setting interface in the software. Can be in the menu or in the settings. can refer to ink, Sogou input method, QQ and other support for skin-changing software.
3. Load the skin file under the specified path, read the thumbnail, display in the Skin setting interface, extract the user's selected skin file to the "/data/data/[package Name]/skin" path.
4. The resources under the "/data/data/[package name]/skin/" path are first read in the software. If not, use the resources in APK.
Effect Chart:
Specific code:
1. Androidmanifest.xml:
<?xml version= "1.0" encoding= "Utf-8"?> <manifest xmlns:android=
"http://schemas.android.com/apk/res/" Android "
package=" Com.tony.skin "android:versioncode=" 1 "android:versionname=" 1.0 ">
<uses-sdk android:minsdkversion= "7"/>
<uses-permission android:name= "Android.permission.WRITE_EXTERNAL_STORAGE" />
<application android:icon= "@drawable/icon" android:label= "@string/app_name" >
<activity Android:name= ". Re_skin2activity "
android:label=" @string/app_name ">
<intent-filter>
<action android: Name= "Android.intent.action.MAIN"/>
<category android:name= "Android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
</application>
</manifest>
2. layout file Main.xml
<?xml version= "1.0" encoding= "Utf-8"?> <linearlayout xmlns:android=
"http://schemas.android.com/apk/" Res/android "
android:orientation=" vertical "
android:layout_width=" fill_parent "
android:layout_" height= "Fill_parent"
android:background= "#d2d2d2"
android:id= "@+id/layout" >
<button android: text= "Import Skin" android:id= "@+id/button2" android:layout_width= "wrap_content" android:layout_height= "Wrap_content" ></Button>
<button android:text= "android:id=" @+id/button1 "android:layout_width=" wrap_content "Android:layout_height=" wrap_content ></Button>
<textview android:id= "@+id/textview1" Android: Layout_width= "Wrap_content" "android:layout_height=" wrap_content "
android:text=", please click "Import Skin", will/sdcard/ Skin.zip into the/sdcard/skin_kris directory, then click on ' Skin ' will use the sdcard inside the material as skin "
android:textcolor= #000" ></TextView>
</LinearLayout>
3. Re_skin2activity:
Package Com.tony.skin;
Import android.app.Activity;
Import Android.graphics.Bitmap;
Import Android.graphics.BitmapFactory;
Import android.graphics.drawable.BitmapDrawable;
Import Android.os.Bundle;
Import Android.view.View;
Import Android.view.View.OnClickListener;
Import Android.widget.Button;
Import Android.widget.LinearLayout;
Import Android.widget.Toast;
Import Com.tony.skin.utils.ZipUtil; /** * * @author Tony * */public class Re_skin2activity extends activity implements onclicklistener{private B
Utton Btnset;
Private Button Btnimport;
Private LinearLayout layout; /** called the activity is a.
* * @Override public void onCreate (Bundle savedinstancestate) {super.oncreate (savedinstancestate);
Setcontentview (R.layout.main);
Btnset = (Button) Findviewbyid (R.id.button1);
Btnset.setonclicklistener (this);
Btnimport = (Button) Findviewbyid (R.id.button2);
Btnimport.setonclicklistener (this); Layout = (linearlayout) Findviewbyid (r.id.layout); @Override public void OnClick (View v) {switch (V.getid ()) {case R.id.button1:bitmap bitmap= Bi
Tmapfactory.decodefile ("/sdcard/tony/skin/skin.png");
Bitmapdrawable bd=new bitmapdrawable (bitmap);
Btnset.setbackgrounddrawable (BD);
Layout.setbackgrounddrawable (New Bitmapdrawable (Bitmapfactory.decodefile ("/sdcard/skin_kris/skin/bg/bg.png"));
Break
Case R.id.button2:ziputil Zipp = new Ziputil (2049);
SYSTEM.OUT.PRINTLN ("Begin do zip");
Zipp.unzip ("/sdcard/skin.zip", "/sdcard/skin_kris");
Toast.maketext (this, import succeeded, Toast.length_short). Show ();
Break
Default:break;
}
}
}
4. Ziputil Unzip the tool class for handling zip packages
Package com.tony.skin.utils;
Import Java.io.BufferedOutputStream;
Import Java.io.File;
Import Java.io.FileInputStream;
Import Java.io.FileOutputStream;
Import java.io.IOException;
Import Java.io.InputStream;
Import java.util.Enumeration;
Import Java.util.zip.Deflater;
Import Org.apache.tools.zip.ZipEntry;
Import Org.apache.tools.zip.ZipFile;
Import Org.apache.tools.zip.ZipOutputStream;
/** * Zip package compression, decompression processing tool class * @author A * * */public class Ziputil {private ZipFile zipfile; Private Zipoutputstream zipout; Compressed zip private int bufsize;
Size of bytes private byte[] buf;
private int readedbytes;
Public Ziputil () {this (512);
Public ziputil (int bufsize) {this.bufsize = bufsize;
This.buf = new Byte[this.bufsize]; /** * * @param srcfile directories or files that need to be compressed @param the path to destfile compressed files */public void Dozip (String sr
CFile, String destfile) {//Zipdirectorypath: folder name to compress File Zipdir;
String dirname;
Zipdir = new File (srcfile);
DirName = Zipdir.getname ();
try {this.zipout = new Zipoutputstream (new Bufferedoutputstream (New FileOutputStream (DestFile));
Set the compressed annotation zipout.setcomment ("comment");
Set the compression encoding, if you want to compress the path in Chinese, use the following encoding zipout.setencoding ("GBK");
Enable compression Zipout.setmethod (zipoutputstream.deflated);
Compression level is the strongest compression, but time to spend a little bit more zipout.setlevel (deflater.best_compression);
Handledir (Zipdir, this.zipout,dirname);
This.zipOut.close ();
catch (IOException IoE) {ioe.printstacktrace (); }/** * Called by dozip, recursive complete directory file read * @param dir * @param zipout * @param dirname This is a directory hierarchy that is used primarily to record compressed files * @throws IOException */private void Handledir (File dir, Zipoutputstream zipout,string dirname) throws Ioexc
eption {System.out.println ("Traverse directory:" +dir.getname ());
FileInputStream Filein; File[] FiLes
Files = Dir.listfiles ();
if (Files.length = = 0) {//If the directory is empty, it is created separately.
In the Isdirectory () method of ZipEntry, the directory ends with "/".
SYSTEM.OUT.PRINTLN ("Compressed Name:" +dirname);
This.zipOut.putNextEntry (New ZipEntry (dirname));
This.zipOut.closeEntry ();
else {//If the directory is not empty, the directories and files are processed separately.
for (File filename:files) {//System.out.println (FileName); if (Filename.isdirectory ()) {Handledir (FileName, This.zipout,dirname+file.separator+filename.getname () +File.se
Parator);
else {System.out.println ("Compressed Name:" +dirname + file.separator+filename.getname ());
Filein = new FileInputStream (fileName);
This.zipOut.putNextEntry (New ZipEntry (dirname + file.separator+filename.getname ()));
while ((This.readedbytes = Filein.read (this.buf)) > 0) {this.zipOut.write (this.buf, 0, this.readedbytes);
} this.zipOut.closeEntry (); }
}
}
}
/** * Extract the specified zip file * @param unzipfile The path of the compressed file * @param destfile the directory to extract to (* * public void UnZip (String
Unzipfile, String destfile) {//Unzipfilename need to extract zip file name FileOutputStream fileout;
File file;
InputStream InputStream;
try {this.zipfile = new ZipFile (unzipfile); For (Enumeration entries = This.zipFile.getEntries (); entries. hasMoreElements ();)
{ZipEntry entry = (zipentry) entries.nextelement ();
File = new file (Destfile+file.separator+entry.getname ());
if (Entry.isdirectory ()) {file.mkdirs ();
else {//If the directory for the specified file does not exist, create it.
File parent = File.getparentfile ();
if (!parent.exists ()) {parent.mkdirs ();
} InputStream = Zipfile.getinputstream (entry);
Fileout = new FileOutputStream (file); while ((This.readedbytes = Inputstream.read (this.buf)) > 0) {fileout.write (This.buf, 0, this.readedbytes);
} fileout.close ();
Inputstream.close ();
} this.zipFile.close ();
catch (IOException IoE) {ioe.printstacktrace ();
}//Set buffer size public void setbufsize (int bufsize) {this.bufsize = bufsize;
}
}