編輯:關於Android編程
用戶通常會避免下載過大的app,尤其是在新興市場,那裡的設備網絡連接2G和3G往往參差不齊,或者以按流量收費的形式。這篇文檔描述了如何減少你的app的APK大小,它會使得更多的用戶下載你的app;
理解APK的結構
--------------------------------------------------------------------------------
在討論如何減少你的app的大小之前,理解一個app的apk結構是非常有用的。一個APK文件是一個zip壓縮文件,它包含你的app的所有文件。這些文件包含Java類文件,資源文件,和一個編譯資源的文件。
一個APK包含下面的目錄:
META-INF/:包含CERT.SF和CERT.RSA簽名文件,和MANIFEST.MF清單文件;
assets/:包含app的assets,app可以使用一個AssetManager對象獲取它;
res/:包含沒有編譯到resources.arsc中的資源;
一個APK也包含下面的文件。在它們裡面,只有AndroidManifest.xml是必須的。
resources.arsc:包含被編譯的資源。這個文件包含來自res/values目錄下所有配置的XML內容。打包工具提取XML內容,將它們編譯為二進制的形式,並且打包。這些內容包含語言字符串和樣式,和在resources.arsc文件不包含的內容的路徑,如布局文件和圖片;
Classes.dex:包含被編譯的類,以Dalvik/ART虛擬機能理解的dex文件格式;
減少資源數目和大小
--------------------------------------------------------------------------------
你的apk的大小對你的app的加載速度,使用內存大小和消耗功率多少有一定影響。使你的apk變小的一種簡單方式就是減少它包含資源的數目和大小。尤其是,你要移除你的app不再使用的資源,並且你可以使用Drawable對象代替圖片文件。這個章節討論了這些,和其它一些能減少你的app資源的方法,來減少你的APK的整體大小。
移除不使用的資源
在Android Studio中的一個靜態代碼工具lint,檢測在你的/res目錄下代碼沒有引用的資源。當lint工具在你的項目中發現一個潛在的未使用的資源,它會打印一條如下示例的消息。
res/layout/preferences.xml: Warning: The resource R.layout.preferences appears
to be unused [UnusedResources]
注意:lint工具沒有掃描assets/目錄,assets通過反射引用,或者你的app鏈接的庫文件。另外,它不會移除資源;它僅僅是提醒你它們的存在;
你添加到你的代碼中的庫可能包含未使用的資源。如果你在你的app的build.gradle文件中啟動shrinkResourcesGradle,它能自動替你刪除這些資源。
android{ // Other settings buildTypes{ release{ minifyEnabledtrue shrinkResourcestrue proguardFiles getDefaultProguardFile('proguard-android.txt'),'proguard-rules.pro' } } }
為了使用shrinkResources,你必須啟動代碼壓縮。在構建的過程中,首先ProGuard移除了沒有使用的代碼,但是還存在沒有使用的資源。然後Gradle會移除沒有使用的資源。
更多關於ProGuard的信息,和其它Android Studios幫助你減少APK大小的方式,查閱Shrink Your Code and Resources。
在Android Gradle插件0.7或者更高版本,你可以聲明你的app支持該配置。Gradle通過使用resConfig和resConfigs flavor和defaultConfig向構建系統傳遞信息。構建系統然後禁止在APK中出現其它來源的資源,不支持的配置,減小APK的大小。更多的關於這個功能的信息,請查閱Remove unused alternative resources。
減少庫中使用的資源
在開發Android app的時候,你通常會使用擴展庫來提升你的app的可用性和多功能性。例如,你可能引用Android Support Library來提升在老設備上的用戶體驗,或者你可能使用Google Play Services來檢索自動翻譯你的app中的文本。
如果一個庫針對server和desktop設計,它會包含許多你的app不需要的對象和方法。為了僅僅包含你的app需要的庫的這部分,如果允許你修改這個庫,你可以編輯這個庫的文件。你也可以使用一個可選的,針對移動端設計的庫來為你的app添加具體的功能。
注意:ProGuard能清除導入的庫不必要的代碼,但是它不能移除庫龐大的內部依賴。
只支持特定的密度
Android支持一個非常大的設備集合,包括各種屏幕密度。在Android4.4(API Level 19)和更高版本,framework支持各種各樣的密度:ldpi,mdpi,tvdpi,xhdpi,xxhdpi和xxxdpi。盡管Android支持所有這些密度,你不需要為每個密度制作資源。
如果你知道你的用戶只有一小部分使用特定密度,考慮下你是否需要將這些密度捆綁你的app中。如果你不包含某一指定屏幕密度的資源,Android自動縮放存在的,原來為其它屏幕密度設計的資源。
如果你的app僅僅需要被縮放的圖片,你可以通過在drawable-nodpi/目錄中保存圖片的一個變體,來節省更多的空間。我們要求任何app至少包含一個xxxhdpi圖片變體;
更多關於屏幕密度的信息,請查閱Screen Sizes and Densities。
減少動畫幀
幀動畫可以徹底減少你的APK的大小。下圖展示了一個幀動畫被分離成多張圖片保存在目錄中的例子。每個圖片在動畫中是為一幀。
對於你添加到動畫中的每一幀,你增加了在APK中圖片的數量。如下圖,在app中這個圖片動畫30幀。如果圖片動畫用僅僅15幀代替,這個動畫僅僅需要一半數量的幀。
aapt工具不會壓縮在asset/目錄下的PNG文件;
aapt工具只優化使用256或者更少的顏色的圖片文件;
aaptOptions{ cruncherEnabled=false }
壓縮PNG和JPEG文件
你可以使用如pngcrush,pngquant或者aopflipng來減小PNG文件的大小,並且不降低圖片的質量。所有的這些工具都可以減少圖片的大小並且保持圖片的質量。
pngcrush工具尤其有效:這個工具迭代PNG過濾器和zlib參數,使用每個過濾器組合和參數來壓縮圖片。然後選擇最小壓縮配置輸出。
對於JPEG文件,你可以使用如packJPG工具來將JPEG文件壓縮為更緊湊格式。
使用webp文件格式
你可以使用WebP文件格式,代替使用PNG或者JPEG文件。Webp格式支持有損壓縮(像JPEG)和透明度(如PNG),但比JPEG或PNG的壓縮更好。
使用WebP文件格式有幾個顯著的缺點。首先,在低於Android3.2系統版本(API level 13)不支持Webp格式。其次,系統解碼WebP相比PNG圖片會消耗了更多的時間。
注意:Google Play僅僅接受使用PNG格式圖標的APK。如果你想通過Google Play發布你的app的話,你不能使用其它文件格式如JPEG或者WebP用戶app的圖標。
使用矢量圖
你可以使用矢量圖來創建獨立於分辨率的圖標和其它可擴展的媒體。使用這些圖標可以大大減少你的apk。矢量圖在Android中以VectorDrawable對象代表。使用VectorDrawable對象,一個100-byte文件可以生成一個屏幕大小清晰圖像。
然而,每個VectorDrawable對象的渲染明顯的消耗了系統時間,並且更大的圖片需要更長的時間來展示在屏幕上。因此僅僅在顯示小的圖片的時候考慮使用矢量圖。
更新關於使用VectorDrawable對象的信息,請查閱Working With Drawables。
減少Native和Java代碼
--------------------------------------------------------------------------------
這裡有幾種你可以用來減少app的Java和native代碼大小的方式。
刪除不必要生成的代碼
一定要明白任何自動生成代碼的足跡。例如,許多協議緩沖工具生成過多的方法和類,它會兩三倍的增加你的app的大小。
移除枚舉
一個枚舉會增加你的app的class.dex文件大約1.0到1.4K的大小。對於復雜的系統或者共享庫這種情況會更加明顯。如果可能的話,考慮使用@IntDef和ProGuard來剝離枚舉,並轉換成Integer。這種類型轉換保留了所有枚舉的安全效益。
減少Native庫的大小
如果你的app使用了native代碼和Android NDK,你也可以通過優化你的代碼減少你的app的大小。兩個有用的技術是移除Debug符號和避免取native庫。
移除Debug符號
使用debug符號意味著著你的應用程序正在開發並且持續需要debug。使用在Android NDK中提供的arm-dabi-strip工具,來移除不必要的native庫的debug符號。在這之後,你可以編譯你的release構建。
避免提取Native庫
保存APK中解壓的.so文件,並且設置在你的應用清單文件中元素中的android:extractNativeLibs標識為false。這將會阻止PackageManager在安裝的過程中從APK中復制出.so文件到文件系統中,並且將增加使得你的app的增量更新更小的好處。
維護多個精簡的APK
--------------------------------------------------------------------------------
你的apk包含了用戶下載但是從來不使用的內容,例如區域的或者語言信息。為了給你的用戶提供一個最小的下載,你可以以屏幕尺寸或者GPU類型劃分,將你的app分給為多個APK。
當一個用戶下載你的應用的時候,他們的設備根據設備的功能和配置獲取對應的APK。這種方式下,設備不會獲取它沒有功能的資源。例如,如果一個用戶有一個hdpi的設備,他們不需要xxxhdpi資源,你可能為了更高的密度設備顯示而包含。
為View添加自定義XML屬性Android中的各種Widget都提供了很多XML屬性,我們可以利用這些XML屬性在layout文件中為Widget的屬性賦值。如下所示:
一、簡介現在的Android應用程序中,不可避免的都會使用到圖片,如果每次加載圖片的時候都要從網絡重新拉取,這樣不但很耗費用戶的流量,而且圖片加載的也會很慢,用戶體驗很不
APP中可能會遇到一種需求,就是將當前所在位置的坐標傳到服務器上,今天我提供三種途徑去獲取經緯度坐標信息,第一種是通過Android API來實現,第二種通過百度地圖AP
2.7導航欄及菜單2.7.1 ActionBarActionBar是Android3.0(API 11)開始增加的新特性,ActionBar出現在活動窗口的頂部,可以顯示