——歡迎轉載,請註明出處 http://blog.csdn.net/asce1885 ,未經本人贊成請勿用於商業用途,謝謝——html
原文連接:https://github.com/futurice/android-best-practicesjava
本文是Futurice公司的Android開發人員總結的最佳實踐,遵循這些準則能夠避免重複製造輪子。若是你對iOS或者Windows Phone開發感興趣,那麼也請看看iOS最佳實踐和Windows客戶端開發最佳實踐。android
概要ios
使用Gradle和推薦的工程結構
git
把密碼和敏感數據存放在gradle.properties文件中
程序員
不要本身實現HTTP客戶端,要使用Volley或者OkHttp庫
github
使用Jackson庫來解析JSON數據
web
避免使用Guava,使用少許的函數庫從而避免超出65k方法數限制
shell
使用Fragments來表示UI界面
編程
Activities只用來管理Fragments
佈局XML文件是代碼,要組織好它們
使用樣式文件來避免佈局XML文件中屬性的重複定義
使用多個樣式文件避免單一大樣式文件的使用
保持colors.xml文件簡短和不重複,只定義顏色值
保持dimens.xml文件不重複,並只定義通用的常量
避免ViewGroups層次結構太深
避免在客戶端側處理WebViews,謹防內存泄漏
使用Robolectric做爲單元測試的工具,Robotium做爲UI測試的工具
使用Genymotion做爲你的模擬器
老是使用ProGuard或者DexGuard
Android SDK
把你的Android SDK目錄放在電腦的主目錄或者其餘跟IDE安裝目錄獨立的磁盤位置,某些IDE在安裝時就包含了Android SDK,並且可能把它放在跟IDE相同的目錄下。當你須要升級(或從新安裝)IDE,或者更換IDE時,這種作法是很差的。一樣要避免把Android SDK放在另一個系統層級的目錄中,這樣當你的IDE在user模式下運行而不是root模式時,將須要sudo權限。
構建系統
你的默認選擇應該是Gradle。相比之下,Ant限制更大並且使用起來更繁瑣。使用Gradle能夠很簡單的實現:
1)將你的app編譯成不一樣的版本;
2)實現簡單的相似腳本的任務;
3)管理和下載第三方依賴項;
4)自定義密鑰庫;
5)其餘
Google也在積極的開發Android的Gradle插件,以此做爲新的標準編譯系統。
工程結構
目前有兩個流行的選擇:之前的Ant和Eclipse ADT工程結構,以及新的Gradle和Android Studio工程結構。你應該選擇新的工程結構,若是你的工程還在使用舊的結構,那麼應該當即開始將它遷移到新的結構上面來。
舊的工程結構以下所示:
- old-structure
- ├─ assets
- ├─ libs
- ├─ res
- ├─ src
- │ └─ com/futurice/project
- ├─ AndroidManifest.xml
- ├─ build.gradle
- ├─ project.properties
- └─ proguard-rules.pro
新的工程結構以下所示:
- new-structure
- ├─ library-foobar
- ├─ app
- │ ├─ libs
- │ ├─ src
- │ │ ├─ androidTest
- │ │ │ └─ java
- │ │ │ └─ com/futurice/project
- │ │ └─ main
- │ │ ├─ java
- │ │ │ └─ com/futurice/project
- │ │ ├─ res
- │ │ └─ AndroidManifest.xml
- │ ├─ build.gradle
- │ └─ proguard-rules.pro
- ├─ build.gradle
- └─ settings.gradle
主要的區別在於新的結構明確的區分源碼集合(main和androidTest),這是從Gradle引入的概念。例如,你能夠在源碼目錄src中添加paid和free兩個子目錄,分別用來存放付費版和免費版app的源碼。
頂層的app目錄有助於把你的app和工程中會引用到的其餘庫工程(例如library-foobar)區分開。settings.gradle文件中記錄了這些庫工程的引用,這樣app/build.gradle就可以引用到了。
Gradle配置
小任務:在Gradle中,咱們使用tasks而不是腳本(shell,Python,Perl等使用腳本),詳細的內容可參見
Gradle文檔。
密碼:發佈release版本時,你須要在app目錄下面的build.gradle文件中定義signingConfigs字段,下面這個配置會出如今版本控制系統中,這是你應該避免的:
- signingConfigs {
- release {
- storeFile file("myapp.keystore")
- storePassword "password123"
- keyAlias "thekey"
- keyPassword "password789"
- }
- }
你應用建立一個gradle.properties文件,該文件不要添加到版本控制系統中,並設置以下:
- KEYSTORE_PASSWORD=password123
- KEY_PASSWORD=password789
gradle會自動導入這個文件,如今你能夠在build.gradle中這樣使用:
- signingConfigs {
- release {
- try {
- storeFile file("myapp.keystore")
- storePassword KEYSTORE_PASSWORD
- keyAlias "thekey"
- keyPassword KEY_PASSWORD
- }
- catch (ex) {
- throw new InvalidUserDataException("You should define KEYSTORE_PASSWORD and KEY_PASSWORD in gradle.properties.")
- }
- }
- }
優先選擇Maven依賴而不是導入jar文件。若是你在工程中顯式地包含jar文件,它們會是特定的不可變的版本,例如2.1.1。下載jar包並手動更新是很麻煩的,而這個問題Maven正好幫咱們解決了,在Android Gradle構建中也建議這麼作。你能夠指定某個版本範圍的jar包,例如2.1.+,這樣Maven會幫咱們自動更新和這個版本模式匹配的後續升級。例子以下:
- dependencies {
- compile 'com.netflix.rxjava:rxjava-core:0.19.+'
- compile 'com.netflix.rxjava:rxjava-android:0.19.+'
- compile 'com.fasterxml.jackson.core:jackson-databind:2.4.+'
- compile 'com.fasterxml.jackson.core:jackson-core:2.4.+'
- compile 'com.fasterxml.jackson.core:jackson-annotations:2.4.+'
- compile 'com.squareup.okhttp:okhttp:2.0.+'
- compile 'com.squareup.okhttp:okhttp-urlconnection:2.0.+'
- }
IDE和文本編輯器
使用任何保持良好工程結構的代碼編輯器。代碼編輯器是我的喜愛的選擇,你須要作的是保證你所用的編輯器可以和工程結構以及構建系統良好集成。
當下最受推崇的IDE是Android Studio,由於它是Google開發的,和Gradle耦合最好,默認使用最新的工程結構,已經處於穩定階段,是爲Android開發量身定作的IDE。
固然你也可使用Eclipse ADT,但你須要配置它才能使用Gradle,由於它默認使用的是舊的工程結構和使用Ant進行構建。你甚至可使用相似Vim,Sublime Text,Emacs等文本編輯器,這種狀況下你須要在命令行中使用Gradle和adb。若是你的Eclipse集成Gradle不可用,你的選擇是要麼使用命令行編譯或者把項目遷移到Android Studio中。Android Studio是最好的選擇,由於ADT插件已經被標記爲過期了,也就是不會再做後續維護和更新了。
不管你使用哪一種方式,需保證的是按照官方的推薦使用新的工程結構和Gradle來構建你的應用,並避免把你特定於編輯器的配置文件加入到版本控制系統中。例如要避免把Ant的build.xml文件添加到版本控制系統中。特別是若是你在Ant中更改了編譯配置,不要忘了同步更新build.gradle文件。最後一點,要對其餘開發人員友好,不要迫使他們修改他們所用編輯器的偏好設置。
函數庫
Jackson是一個把Java對象轉換爲JSON字符串或者把JSON字符串轉換成Java對象的Java函數庫。Gson也是解決這類問題很流行的選擇之一,但咱們發現Jackson更加高性能,由於它支持多種可選的處理JSON的方式:流,內存樹模型和傳統的JSON-POJO數據綁定。儘管如此,Jackson是比Gson更大的函數庫,因此須要根據你項目的具體狀況,你可能會選擇GSON來避免65k方法數限制。其餘的選擇還有:Json-smart和Boon JSON。
網絡,緩存和圖像。向後端服務器發起網絡請求有不少通過實戰檢驗的解決方案,你應該使用這些解決方案而不是本身實現一個。使用Volley或者Retrofit吧!除了網絡請求,Volley還提供了幫助類用於加載和緩存圖像。若是你選擇Retrofit,那麼能夠考慮使用Picasso做爲加載和緩存圖像的函數庫,並結合OkHttp實現高效的HTTP請求。Retrofit,Picasso和OkHttp這三款函數庫都是同一家公司開發的,因此它們可以很好的互補。Volley也能使用OkHttp來實現網絡鏈接。
RxJava是一個響應式編程的函數庫,也就是能夠處理異步事件。這是一個強大和有前途的編程範式,但因爲它是如此的不一樣,所以會顯得很差理解。在使用這個函數庫搭建你的應用的框架時,咱們建議你要保持謹慎的態度。咱們有幾個項目已經使用RxJava來實現,若是你須要幫助能夠聯繫如下這些人:Timo Tuominen, Olli Salonen, Andre Medeiros, Mark Voit, Antti Lammi, Vera Izrailit, Juha Ristolainen。咱們已經寫了一些博客文章來進行介紹
1)http://blog.futurice.com/tech-pick-of-the-week-rx-for-net-and-rxjava-for-android;
2)http://blog.futurice.com/top-7-tips-for-rxjava-on-android;
3)https://gist.github.com/staltz/868e7e9bc2a7b8c1f754;
4)http://blog.futurice.com/android-development-has-its-own-swift)。
若是你以前沒有使用RxJava的經驗,那麼開始時能夠僅在網絡請求API的響應處使用。若是有經驗了,能夠將RxJava應用在簡單UI事件的處理,例如點擊事件或者搜索框中的輸入事件。若是你對本身的RxJava技能很自信並且想把RxJava應用到整個項目架構中,那麼在代碼難以理解的部分要編寫Javadocs。要記住對RxJava不熟悉的程序員可能在維護工程的初期會很痛苦。盡你所能幫助他們理解你的代碼和RxJava。
Retrolambda是兼容在Android中和JDK8以前的Java版本中使用Lambda表達式語法的一個Java函數庫。它幫助你的代碼保持緊湊和可讀,特別是當你使用函數式編程風格時,例如使用RxJava。要使用這個庫,須要安裝JDK8,在Android Studio工程結構對話框中設置SDK的位置,並設置JAVA8_HOME和JAVA7_HOME環境變量,而後在工程的build.gradle中設置以下:
- dependencies {
- classpath 'me.tatarka:gradle-retrolambda:2.4.+'
- }
接着在各個模塊的build.gradle中增長配置以下:
- apply plugin: 'retrolambda'
-
- android {
- compileOptions {
- sourceCompatibility JavaVersion.VERSION_1_8
- targetCompatibility JavaVersion.VERSION_1_8
- }
-
- retrolambda {
- jdk System.getenv("JAVA8_HOME")
- oldJdk System.getenv("JAVA7_HOME")
- javaVersion JavaVersion.VERSION_1_7
- }
Android Studio提供了支持Java8 lambdas的代碼輔助功能。若是你剛接觸lambdas,能夠參見下面的建議來開始:
1)任何只有一個函數的接口(Interface)是「lambda友好」的,能夠被摺疊爲更緊湊的語法格式;
2)若是對參數或諸如此類的用法還存有懷疑的話,能夠編寫一個普通的匿名內部類而後讓Android Studio幫你把它摺疊成lambda表達式的形式。
要注意dex文件方法數限制的問題,避免使用太多的第三方函數庫。當Android應用打包成一個dex文件時,存在最多65536個引用方法數的限制問題。當超出這個限制時,你將在編譯階段看到fatal error。所以,應該使用盡量少的第三方函數庫,並使用dex-method-counts工具來決定使用哪些函數庫的組合以免不超過該限制。特別要避免使用Guava函數庫,由於它包含的方法數超過13k。
Activities and Fragments
在Android中實現UI界面默認應該選擇Fragments。Fragments是可複用用戶界面,可以在你的應用中很好的組合。咱們建議使用Fragments代替Activities來表示用戶界面,下面是幾點緣由:
1)多窗口布局的解決方案。最初引入Fragment的緣由是爲了把手機應用適配到平板電腦屏幕上,這樣你能夠在平板電腦屏幕上具備A和B兩個窗口,而到了手機屏幕上A或者B窗口獨佔整個手機屏幕。若是你的應用在最開始的時候是基於Fragments實現的,那麼之後要適配到其餘不一樣類型的屏幕上面會容易得多。
2)不一樣界面之間的通訊。Android API沒有提供在Activity之間傳遞複雜數據(例如某些Java對象)的正確方法。對於Fragments而已,你可使用Activity的實例做爲它的子Fragments之間通訊的通道。雖然這種方法比Activities之間的通訊更好,但你可能願意考慮Event Bus框架,例如使用
Otto或者
green robot EventBus做爲更簡潔的方法。若是你想避免添加多一個函數庫的話,RxJava也能夠用於實現Event Bus。
咱們建議不要大量的使用嵌套Fragments,這會致使
matryoshka bugs。只有在必要的時候(例如在Fragment屏幕中內嵌水平滑動的ViewPager)或者確實是明智的決定時才使用嵌套Fragments。
從軟件架構的層面看,你的app應該具備一個包含大部分業務相關fragments的頂級activity。固然你也能夠有其餘輔助activities,這些activities與主activity的具備簡單的數據通訊,例如經過Intent.setData()或者Intent.setAction()等等。
Java包結構
Android應用的Java包結構大體相似MVC模式。在Android中Fragment和Activity其實是controller類,另外一方面,它們顯然也是用戶界面的一部分,所以也是View類。
所以,很難嚴格界定Fragments(或者Activities)是controllers類仍是views類。最好把Fragments類單獨放在fragments包裏面。若是你遵循前面段落的建議的話(只有一個主Activity),Activities能夠放在頂層的包裏面。若是你計劃會存在多個activities,那麼就將Activity放在單獨的activities包裏面。
另外一方面,整個包結構看起來很像經典的MVC框架,models包目錄存放網絡請求API響應通過JSON解析器填充後獲得的POJOs對象。views包目錄存放自定義的views,notifications,action bar views,widgets等等。Adapters處於灰色地帶,介於data和views之間,然而,它們通常須要經過getView()函數導出視圖,因此你能夠在views包中增長adapters子包。
有的controller類是應用範圍的並和Android系統緊密關聯,它們能夠放在managers包裏面。其餘的數據處理類,例如「DateUtils」,能夠放在utils包裏面。與服務器端響應交互的類放在network包裏面。
總之,整個包結構從服務器端到用戶界面劃分以下所示:
- com.futurice.project
- ├─ network
- ├─ models
- ├─ managers
- ├─ utils
- ├─ fragments
- └─ views
- ├─ adapters
- ├─ actionbar
- ├─ widgets
- └─ notifications
資源
命名。遵循以類型做爲前綴命名的慣例,即type_foo_bar.xml。例子以下:fragment_contact_details.xml,view_primary_button.xml,activity_main.xml。
組織布局XMLs。若是你對如何格式化佈局XML文件不大清楚的話,那麼下面的慣例或許能夠幫你:
1)每行一個屬性,縮進四個空格
2)android:id始終做爲第一個屬性
3)android:layout_****屬性放在頭部
4)style屬性放在尾部
5)結束標籤/>放在單獨一行,便於新增屬性或者從新排列屬性
- <?xml version="1.0" encoding="utf-8"?>
- <LinearLayout
- xmlns:android="http://schemas.android.com/apk/res/android"
- xmlns:tools="http://schemas.android.com/tools"
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- >
-
- <TextView
- android:id="@+id/name"
- android:layout_width="match_parent"
- android:layout_height="wrap_content"
- android:layout_alignParentRight="true"
- android:text="@string/name"
- style="@style/FancyText"
- />
-
- <include layout="@layout/reusable_part" />
-
- </LinearLayout>
通常來講android:layout_****屬性應該定義在XML佈局文件中,而其餘的android:****屬性應該放在樣式xml文件中。這條法則也有例外,但通常狀況是這樣的
。這種作法是爲了在佈局文件中只保留佈局屬性(位置,留白,大小)和內容屬性,而其餘外觀細節(顏色,填充,字體)放到樣式文件中。
例外的有:
1)android:id必須放在layout文件中
2)在LinearLayout中的android:orientation通常放在layout文件中更有意思
3)android:text必須放在layout文件中,由於它定義了內容
4)有時建立通用的style文件並定義android:layout_width和android:layout_height屬性更有意思,但默認狀況下這兩個屬性應該放在layout文件中。
使用styles。幾乎全部工程都須要正確的使用styles,由於它是讓view具備相同外觀的常見的方法。你的應用的文本內容應該至少具備一個公用的樣式,例如:
- <style name="ContentText">
- <item name="android:textSize">@dimen/font_normal</item>
- <item name="android:textColor">@color/basic_black</item>
- </style>
用在TextView上面以下:
- <TextView
- android:layout_width="wrap_content"
- android:layout_height="wrap_content"
- android:text="@string/price"
- style="@style/ContentText"
- />
你可能須要對buttons作相似的工做,但別就此停住。繼續把相關的和重複的android:****屬性分組到公用的style文件中。
把一個大的style文件細分紅多個文件。你沒有必要維護單獨一個styles.xml文件,Android SDK能很好的支持其餘文件。styles文件的名字並不必定要是styles.xml,起做用的是xml文件裏面的<style>標籤。所以,你的樣式文件命名能夠是styles.xml,styles_home.xml,styles_item_details.xml,styles_forms.xml等。和資源目錄名不一樣(編譯系統須要根據資源目錄名找到資源),res/values裏面的文件名能夠隨意命名。
colors.xml是調色板。在你的colors.xml文件中除了定義顏色名字到RGBA顏色值的映射外,不該該定義其餘的東西。不用使用它來定義不一樣類型按鈕的RGBA顏色值。
不要這樣作:
- <resources>
- <color name="button_foreground">#FFFFFF</color>
- <color name="button_background">#2A91BD</color>
- <color name="comment_background_inactive">#5F5F5F</color>
- <color name="comment_background_active">#939393</color>
- <color name="comment_foreground">#FFFFFF</color>
- <color name="comment_foreground_important">#FF9D2F</color>
- ...
- <color name="comment_shadow">#323232</color>
這樣的使用很容易重複定義相同的RGBA值,這致使若是須要更改一個基本色值時會很麻煩。並且上面的這些定義是和上下文相關的,例如「button」,「comment」,這些應該放到button樣式文件中,而不是colors.xml文件中。
應該這樣作:
- <resources>
-
-
- <color name="white" >#FFFFFF</color>
- <color name="gray_light">#DBDBDB</color>
- <color name="gray" >#939393</color>
- <color name="gray_dark" >#5F5F5F</color>
- <color name="black" >#323232</color>
-
-
- <color name="green">#27D34D</color>
- <color name="blue">#2A91BD</color>
- <color name="orange">#FF9D2F</color>
- <color name="red">#FF432F</color>
-
- </resources>
嚮應用的設計師要以上這些色值定義。命名不須要爲顏色名字,如「green」,「blue」等,例如「brand_primary」,「brand_secondary」,「brand_negative」這樣的命名也是徹底能夠接受的。這樣來格式化顏色值使得之後若是要修改或者重構顏色時很容易,同時應用中使用了多少種顏色也是一目瞭然的。對於一個美觀的UI,減小使用的顏色種類是很重要的。
dimens.xml文件跟colors.xml文件具備相同的用法。你應該定義一個典型的間距和字體大小的模版,目的基本上和colors.xml文件同樣,好的dimens.xml文件例子以下:
- <resources>
-
-
- <dimen name="font_larger">22sp</dimen>
- <dimen name="font_large">18sp</dimen>
- <dimen name="font_normal">15sp</dimen>
- <dimen name="font_small">12sp</dimen>
-
-
- <dimen name="spacing_huge">40dp</dimen>
- <dimen name="spacing_large">24dp</dimen>
- <dimen name="spacing_normal">14dp</dimen>
- <dimen name="spacing_small">10dp</dimen>
- <dimen name="spacing_tiny">4dp</dimen>
-
-
- <dimen name="button_height_tall">60dp</dimen>
- <dimen name="button_height_normal">40dp</dimen>
- <dimen name="button_height_short">32dp</dimen>
-
- </resources>
佈局文件的邊距和填充應該使用spacing_****尺寸定義,而不是使用硬編碼(相似字符串硬編碼)。這樣會帶來統一的外觀,同時使得組織和修改樣式和佈局更簡單。
避免過深的views層級。有時你可能會被誘導在LinearLayout中再增長一層LinearLayout,例如爲了完成一組views的排列。這種狀況相似以下:
- <LinearLayout
- android:layout_width="match_parent"
- android:layout_height="match_parent"
- android:orientation="vertical"
- >
-
- <RelativeLayout
- ...
- >
-
- <LinearLayout
- ...
- >
-
- <LinearLayout
- ...
- >
-
- <LinearLayout
- ...
- >
- </LinearLayout>
-
- </LinearLayout>
-
- </LinearLayout>
-
- </RelativeLayout>
-
- </LinearLayout>
即便你沒有很明顯的在Layout文件中看到這種狀況,但可能最終發生在Java代碼中將某個view inflate到另外的view中。
這可能會引發一些問題,你可能會遇到性能問題,由於處理器須要處理很複雜的UI樹層級。另外一個更嚴重的問題是可能會引發StackOverflowError。
所以,儘可能使你的view具備扁平的層級:學習怎樣使用RelativeLayout,怎樣優化佈局和使用<merge>標籤。
當心WebView相關的問題。當你須要展現一個web頁面時,例如新聞文章,要避免在客戶端側對HTML進行簡化處理,相反,應該向服務器端請求通過簡化後的HTML。當WebView持有所在Activity Context引用而不是Application Context引用時,也可能致使內存泄漏。要避免在簡單文本或者按鈕使用WebView,應該使用TextView和Button。
測試框架
Android SDK的測試框架還很簡單,尤爲是UI測試相關的。Android Gradle目前實現了一個叫作connectedAndroidTest的測試任務,它可以使用JUnit的Android擴展來運行你建立的JUnit測試用例。這意味着你須要鏈接設備或者模擬器來運行測試用例,遵循官方幫助指南來進行測試1)http://developer.android.com/tools/testing/testing_android.html;
2)http://developer.android.com/tools/testing/activity_test.html)。
使用Robolectric來進行單元測試,而不是UI測試。這是一個爲了提升開發速度,專一於提供「獨立於設備」的測試框架,尤爲適用於models和view models的單元測試。可是Robolectric對於UI測試的支持是不許確和不完善的。使用Robolectric進行動畫,對話框等相關的UI元素測試時會遇到問題,你將看不到屏幕相應的UI元素被測試實時操縱,你將相似於在黑暗中行走。
Robotium簡化了UI測試。你不須要Robotium來執行UI測試用例,但它提供了不少幫助工具用來獲取和分析views,控制屏幕等,這一點對你可能頗有幫助。測試用例很簡單,以下所示:
- solo.sendKey(Solo.MENU);
- solo.clickOnText("More");
- solo.clickOnText("Preferences");
- solo.clickOnText("Edit File Extensions");
- Assert.assertTrue(solo.searchText("rtf"));
模擬器
若是你的工做是開發android app,那麼買一個Genymotion模擬器的licence吧。Genymotion模擬器比AVD模擬器具備更快的幀率,並且具備演示app,模擬網絡鏈接質量,GPS位置等工具。它也是用於鏈接測試的理想工具。使用Genymotion模擬器,你能夠模擬不少不一樣類型的設備,因此購買一個Genymotion模擬器licence比買多個真實設備更划算。
要注意的是:Genymotion模擬器沒有移植全部的Google服務,例如Google Play Stoe和Google Maps。你可能須要測試三星特有的API,這時須要購買一臺真實的三星設備。
Proguard配置
在Android工程中ProGuard被用於壓縮和混淆打包後的代碼。ProGuard的使用能夠在工程配置文件中設置。通常狀況下當構建一個release版本的apk時,你須要配置Gradle使用ProGuard。
- buildTypes {
- debug {
- minifyEnabled false
- }
- release {
- signingConfig signingConfigs.release
- minifyEnabled true
- proguardFiles 'proguard-rules.pro'
- }
- }
爲了決定哪些代碼須要保留,哪些代碼須要丟棄或者混淆,你須要在你的代碼中指定一個或者多個入口點。這些入口點典型的就是具備main函數,applets,midlets,activities等的類。Android框架使用的默認配置文件是SDK_HOME/tools/proguard/proguard-android.txt。自定義的工程特有的proguard規則文件定義爲my-project/app/proguard-rules.pro,將會拼接到默認配置中。
Proguard相關的一個常見問題是在應用啓動時出現crash,錯誤類型是ClassNotFoundException或者NoSuchFieldException等,即便編譯是成功的,緣由不過以下兩種:
1)ProGuard把須要用到的類,枚舉,方法,變量或者註解等給移除了;
2)ProGuard把相應的類,枚舉或者變量名給混淆(重命名)了,但調用者仍是使用它原來的名字,例如Java反射的狀況。
檢查app/build/outputs/proguard/release/usage.txt文件看出問題的對象是否被移除了;檢查app/build/outputs/proguard/release/mapping.txt文件看出問題的對象是否被混淆了。爲了防止ProGuard把須要的類或者類成員移除了,須要在ProGuard配置文件中增長keep選項:
- -keep class com.futurice.project.MyClass { *; }
爲了防止ProGuard把須要的類或者類變量混淆了,要增長keepnames選項:
- -keepnames class com.futurice.project.MyClass { *; }
一些例子能夠從ProGuard配置模版上面找到,更多例子參見ProGuard官方例子。
在你的項目早期,執行一個release構建來檢查ProGuard規則是否正確的保持了不須要移除或者混淆的東西。當你增長新的函數庫,也要執行新的Release構建並在設備上測試生成的apk來確保沒有問題。不要等到你的app要發佈1.0版本了纔想到要執行一個release構建,這時你可能會獲得及其不愉快的驚喜,並花一段時間來修復這些問題。
貼士:保存每一個你發佈給最終用戶的apk包對應的mapping.txt文件。保存mapping.txt的緣由在於當你的用戶上傳混淆過的crash日誌時,你能夠很容易的進行調試。
DexGuard:若是你須要能對你發佈的代碼進行優化,尤爲是混淆的核心工具的話,能夠考慮DexGuard,這是由ProGuard同一團隊發佈的商業軟件。它還能夠很容易的對分割Dex文件以解決65k函數個數限制問題。
——歡迎轉載,請註明出處 http://blog.csdn.net/asce1885 ,未經本人贊成請勿用於商業用途,謝謝——