日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > Android >内容正文

Android

Android 打造自己的个性化应用(四):仿墨迹天气实现--自定义扩展名的zip格式的皮肤...

發(fā)布時間:2025/3/20 Android 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Android 打造自己的个性化应用(四):仿墨迹天气实现--自定义扩展名的zip格式的皮肤... 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

在這里談一下墨跡天氣的換膚實現方式,不過首先聲明我只是通過反編譯以及參考了一些網上其他資料的方式推測出的換膚原理, 在這里只供參考. 若大家有更好的方式, 歡迎交流.

?

?

墨跡天氣下載的皮膚就是一個zip格式的壓縮包,在應用的時候把皮膚資源釋放到墨跡天氣應用的目錄下,更換皮膚時新的皮膚資源會替換掉老的皮膚資源每次加載的時候就是從手機硬盤上讀取圖片,這些圖片資源的命名和程序中的資源的命名保持一致,一旦找不到這些資源,可以選擇到系統默認中查找。這種實現是直接讀取了外部資源文件,在程序運行時通過代碼顯示的替換界面的背景資源。這種方式的優(yōu)點是:皮膚資源的格式定義很隨意可以是zip也可以是自定義的格式,只要程序中能夠解析到資源就行,缺點是效率上的問題.

?

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

?

主要技術點:

如何去讀取zip文件中的資源以及皮膚文件存放方式

?

實現方案:如果軟件每次啟動都去讀取SD卡上的皮膚文件,速度會比較慢。較好的做法是提供一個皮膚設置的界面,用戶選擇了哪一個皮膚,就把那個皮膚文件解壓縮到”/data/data/[package name]/skin”路徑下(讀取的快速及安全性),這樣不需要跨存儲器讀取,速度較快,而且不需要每次都去zip壓縮包中讀取,不依賴SD卡中的文件,即使皮膚壓縮包文件被刪除了也沒有關系。

實現方法:

1. 在軟件的幫助或者官網的幫助中提示用戶將皮膚文件拷貝到SD卡指定路徑下。
2. 在軟件中提供皮膚設置界面??梢栽诓藛位蛘咴谠O置中。可參考墨跡、搜狗輸入法、QQ等支持換膚的軟件。
3. 加載指定路徑下的皮膚文件,讀取其中的縮略圖,在皮膚設置界面中顯示,將用戶選中的皮膚文件解壓縮到”/data/data/[package name]/skin”路徑下。
4. 軟件中優(yōu)先讀取”/data/data/[package name]/skin/”路徑下的資源。如果沒有則使用apk中的資源。

?

效果圖:

?

具體代碼:

1. AndroidManifest.xml:

?

[java]?view plaincopy
  • <?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

    ?

    ?

    [java]?view plaincopy
  • <?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="導入皮膚"?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="請先點擊“導入皮膚”,會將/sdcard/skin.zip導入到/sdcard/Skin_kris目錄下,然后點擊‘換膚’會將sdcard里面的素材用作皮膚"??
  • ?????????android:textColor="#000"></TextView>??
  • </LinearLayout>??

  • 3. Re_Skin2Activity:

    ?

    ?

    [java]?view plaincopy
  • 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,?"導入成功",?Toast.LENGTH_SHORT).show();??
  • ????????????break;??
  • ????????default:??
  • ????????????break;??
  • ????????}??
  • ????}??
  • }??

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

    ?

    ?

    [java]?view plaincopy
  • 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)));??
  • ????????????//設置壓縮的注釋??
  • ????????????zipOut.setComment("comment");??
  • ????????????//設置壓縮的編碼,如果要壓縮的路徑中有中文,就用下面的編碼??
  • ????????????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調用,遞歸完成目錄文件讀取?
  • ?????*?@param?dir?
  • ?????*?@param?zipOut?
  • ?????*?@param?dirName??這個主要是用來記錄壓縮文件的一個目錄層次結構的?
  • ?????*?@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()方法中,目錄以"/"結尾.??
  • ????????????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();??
  • ????????}??
  • ????}??
  • ??
  • ????//?設置緩沖區(qū)大小??
  • ????public?void?setBufSize(int?bufSize)?{??
  • ????????this.bufSize?=?bufSize;??
  • ????}??
  • }?
  • 轉載于:https://www.cnblogs.com/dongweiq/p/4249931.html

    總結

    以上是生活随笔為你收集整理的Android 打造自己的个性化应用(四):仿墨迹天气实现--自定义扩展名的zip格式的皮肤...的全部內容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。