麻豆小视频在线观看_中文黄色一级片_久久久成人精品_成片免费观看视频大全_午夜精品久久久久久久99热浪潮_成人一区二区三区四区

首頁 > 系統(tǒng) > Android > 正文

仿墨跡天氣在Android App中實現(xiàn)自定義zip皮膚更換

2020-01-02 07:03:37
字體:
供稿:網(wǎng)友

在這里談一下墨跡天氣的換膚實現(xiàn)方式,不過首先聲明我只是通過反編譯以及參考了一些網(wǎng)上其他資料的方式推測出的換膚原理, 在這里只供參考. 若大家有更好的方式, 歡迎交流.
墨跡天氣下載的皮膚就是一個zip格式的壓縮包,在應(yīng)用的時候把皮膚資源釋放到墨跡天氣應(yīng)用的目錄下,更換皮膚時新的皮膚資源會替換掉老的皮膚資源每次加載的時候就是從手機硬盤上讀取圖片,這些圖片資源的命名和程序中的資源的命名保持一致,一旦找不到這些資源,可以選擇到系統(tǒng)默認中查找。這種實現(xiàn)是直接讀取了外部資源文件,在程序運行時通過代碼顯示的替換界面的背景資源。這種方式的優(yōu)點是:皮膚資源的格式定義很隨意可以是zip也可以是自定義的格式,只要程序中能夠解析到資源就行,缺點是效率上的問題.

這里需要注意的一點是,再這里對壓縮包的解壓,借助了第三方工具: ant. jar進行解壓和壓縮文件. 關(guān)于ant工具的使用,我在稍后的文章中會具體介紹.

主要技術(shù)點:
如何去讀取zip文件中的資源以及皮膚文件存放方式

實現(xiàn)方案:如果軟件每次啟動都去讀取SD卡上的皮膚文件,速度會比較慢。較好的做法是提供一個皮膚設(shè)置的界面,用戶選擇了哪一個皮膚,就把那個皮膚文件解壓縮到”/data/data/[package name]/skin”路徑下(讀取的快速及安全性),這樣不需要跨存儲器讀取,速度較快,而且不需要每次都去zip壓縮包中讀取,不依賴SD卡中的文件,即使皮膚壓縮包文件被刪除了也沒有關(guān)系。
實現(xiàn)方法:
1. 在軟件的幫助或者官網(wǎng)的幫助中提示用戶將皮膚文件拷貝到SD卡指定路徑下。
2. 在軟件中提供皮膚設(shè)置界面。可以在菜單或者在設(shè)置中。可參考墨跡、搜狗輸入法、QQ等支持換膚的軟件。
3. 加載指定路徑下的皮膚文件,讀取其中的縮略圖,在皮膚設(shè)置界面中顯示,將用戶選中的皮膚文件解壓縮到”/data/data/[package name]/skin”路徑下。
4. 軟件中優(yōu)先讀取”/data/data/[package name]/skin/”路徑下的資源。如果沒有則使用apk中的資源。

效果圖:

2016226153459744.jpg (375×517)

具體代碼:
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.布局文件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="導(dǎo)入皮膚" 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="請先點擊“導(dǎo)入皮膚”,會將/sdcard/skin.zip導(dǎo)入到/sdcard/Skin_kris目錄下,然后點擊‘換膚'會將sdcard里面的素材用作皮膚"      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 Button btnSet;   private Button btnImport;   private LinearLayout layout;   /** Called when the activity is first created. */   @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= BitmapFactory.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, "導(dǎo)入成功", Toast.LENGTH_SHORT).show();       break;     default:       break;     }   } } 

4. ZipUtil 解壓縮處理ZIP包的工具類

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包壓縮,解壓處理工具類  * @author a  *  */ public class ZipUtil {   private ZipFile     zipFile;    private ZipOutputStream zipOut;   //壓縮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 需要 壓縮的目錄或者文件    * @param destFile 壓縮文件的路徑    */   public void doZip(String srcFile, String destFile) {// zipDirectoryPath:需要壓縮的文件夾名     File zipDir;     String dirName;      zipDir = new File(srcFile);     dirName = zipDir.getName();     try {       this.zipOut = new ZipOutputStream(new BufferedOutputStream(           new FileOutputStream(destFile)));       //設(shè)置壓縮的注釋       zipOut.setComment("comment");       //設(shè)置壓縮的編碼,如果要壓縮的路徑中有中文,就用下面的編碼       zipOut.setEncoding("GBK");       //啟用壓縮        zipOut.setMethod(ZipOutputStream.DEFLATED);         //壓縮級別為最強壓縮,但時間要花得多一點        zipOut.setLevel(Deflater.BEST_COMPRESSION);               handleDir(zipDir, this.zipOut,dirName);       this.zipOut.close();     } catch (IOException ioe) {       ioe.printStackTrace();     }   }    /**    * 由doZip調(diào)用,遞歸完成目錄文件讀取    * @param dir    * @param zipOut    * @param dirName 這個主要是用來記錄壓縮文件的一個目錄層次結(jié)構(gòu)的    * @throws IOException    */   private void handleDir(File dir, ZipOutputStream zipOut,String dirName) throws IOException {     System.out.println("遍歷目錄:"+dir.getName());     FileInputStream fileIn;     File[] files;      files = dir.listFiles();      if (files.length == 0) {// 如果目錄為空,則單獨創(chuàng)建之.       // ZipEntry的isDirectory()方法中,目錄以"/"結(jié)尾.       System.out.println("壓縮的 Name:"+dirName);       this.zipOut.putNextEntry(new ZipEntry(dirName));       this.zipOut.closeEntry();     } else {// 如果目錄不為空,則分別處理目錄和文件.       for (File fileName : files) {         // System.out.println(fileName);          if (fileName.isDirectory()) {           handleDir(fileName, this.zipOut,dirName+File.separator+fileName.getName()+File.separator);         } else {           System.out.println("壓縮的 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();         }       }     }   }    /**    * 解壓指定zip文件    * @param unZipfile 壓縮文件的路徑    * @param destFile   解壓到的目錄     */   public void unZip(String unZipfile, String destFile) {// unZipfileName需要解壓的zip文件名     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 {           // 如果指定文件的目錄不存在,則創(chuàng)建之.           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();     }   }    // 設(shè)置緩沖區(qū)大小   public void setBufSize(int bufSize) {     this.bufSize = bufSize;   } } 

發(fā)表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發(fā)表
主站蜘蛛池模板: 91 成人| 欧美精品一区自拍a毛片在线视频 | 羞羞网站在线观看入口免费 | 26uuu成人人网图片 | 中文字幕一区久久 | 超碰97人人艹 | 激情网站视频 | 福利在线免费 | 黄色片视频观看 | 成人宗合网 | 久草在线资源观看 | 一级免费观看 | 综合国产在线 | 成人观看网站 | 亚洲精品久久久久久 | 91综合在线观看 | 成人在线视频免费观看 | 精品久久久久久久久久久久包黑料 | 91精品国产一区二区在线观看 | 日本欧美一区二区三区视频麻豆 | 久久成人精品视频 | 操操影视| 成人福利免费在线观看 | 亚州视频在线 | 国产噜噜噜噜噜久久久久久久久 | 美女久久 | 午夜激情视频免费 | 成年免费视频黄网站在线观看 | 91重口视频 | 成人免费乱码大片a毛片视频网站 | 日韩精品久久久久久 | 国产精品热 | 黄色毛片免费视频 | 国产1区2区在线 | 日本高清黄色片 | 国产精品久久77777 | 欧美中文字幕一区二区三区亚洲 | 牛牛a级毛片在线播放 | 成人午夜毛片 | 亚洲骚综合 | 国产亚洲精彩视频 |