代碼是一個程序猿的門面,有門面的程序猿纔是一個好程序猿。html
本文節選自阿里巴巴開發手冊,下載地址android
本手冊以開發者爲中心視角分爲Java語言規範(遵循《阿里巴巴Java開發手冊》), Android 資源文件命名與使用,Android 基本組件,UI 與佈局,進程、線程與消息通訊, 文件與數據庫,Bitmap、Drawable 與動畫,安全,其餘等九大部分,根據約束力強弱, 規約依次分爲強制、推薦、參考三大類:git
必須遵照,違反本約定或將會引發嚴重的後果;github
儘可能遵照,長期遵照有助於系統穩定性和合做效率的提高;web
充分理解,技術意識的引導,是我的學習、團隊溝通、項目合做的方向。算法
對於規約條目的延伸信息中,「說明」對內容作了適當擴展和解釋;「正例」提倡 什麼樣的編碼和實現方式;「反例」說明須要提防的雷區,以及錯誤案例。數據庫
遵循《阿里巴巴 Java 開發手冊》手冊,下載地址canvas
資源文件需帶模塊前綴。數組
layout 文件的命名方式。 Activity 的 layout 以 module_activity 開頭 Fragment 的 layout 以 module_fragment 開頭 Dialog 的 layout 以 module_dialog 開頭 include 的 layout 以 module_include 開頭 ListView 的行 layout 以 module_list_item 開頭 RecyclerView 的 item layout 以 module_recycle_item 開頭 GridView 的行 layout 以 module_grid_item 開頭瀏覽器
drawable 資源名稱以小寫單詞+下劃線的方式命名,根據分辨率不一樣存放在不一樣的 drawable 目錄下,建議只使用一套,例如 drawable-xhdpi。採用規則以下:模塊名_業務功能描述_控件描述_控件狀態限定詞 如:module_login_btn_pressed,module_tabs_icon_home_normal
anim 資源名稱以小寫單詞+下劃線的方式命名,採用如下規則:模塊名_邏輯名稱_[方向|序號]tween 動畫資源 : 儘量以通用的動畫名稱命名,如 module_fade_in ,module_fade_out , module_push_down_in (動畫+方向);
frame 動畫資源:儘量以模 塊+功能命名+序號。如:module_loading_grey_001
color 資源使用#AARRGGBB 格式,寫入modul_colors.xml
文件中,命名格式採用如下規則:模塊名_邏輯名稱_顏色。 如:<color name="module_btn_bg_color">#33b5e5e5</color>
dimen 資源以小寫單詞+下劃線方式命名,寫入 module_dimens.xml 文件中,採用如下規則:模塊名_描述信息。如:<dimen name="module_horizontal_line_height">1dp</dimen>
style 資源採用小寫單詞+下劃線方式命名,寫入 module_styles.xml 文件中,採用如下規則:父 style 名稱.當前 style 名稱。 如: <style name="ParentTheme.ThisActivityTheme"> …</style>
string資源文件或者文本用到字符須要所有寫入module_strings.xml文件中,字符串以小寫單詞+下劃線的方式命名,採用如下規則:模塊名_邏輯名稱 如:moudule_login_tips,module_homepage_notice_desc
Id 資源原則上以駝峯法命名,View 組件的資源 id 須要以 View 的縮寫做爲前綴。經常使用縮寫表以下
其它控件的縮寫推薦使用小寫字母並用下劃線進行分割,例如: ProgressBar 對應的縮寫爲 progress_bar DatePicker 對應的縮寫爲 date_picker10.大分辨率圖片(單維度超過 1000)大分辨率圖片建議統一放在 xxhdpi 目錄下管理,不然將致使佔用內存成倍數增長。 說明: 爲了支持多種屏幕尺寸和密度,Android 爲多種屏幕提供不一樣的資源目錄進行適配。 爲不一樣屏幕密度提供不一樣的位圖可繪製對象,可用於密度特定資源的配置限定符(在 下面詳述) 包括 ldpi(低)、mdpi(中)、 hdpi(高)、xhdpi(超高)、xxhdpi (超 超高)和 xxxhdpi(超超超高)。例如,高密度屏幕的位圖應使用 drawable-hdpi/。 根據當前的設備屏幕尺寸和密度,將會尋找最匹配的資源,若是將高分辨率圖片放 入低密度目錄,將會形成低端機加載過大圖片資源,又可能形成 OOM,同時也是資 源浪費,沒有必要在低端機使用大圖。 正例: 將 144 * 144 的應用圖標 PNG 文件放在 drawable-xxhdpi 目錄 反例: 將 144 * 144 的應用圖標 PNG 文件放在 drawable-mhdpi 目錄
Android 基本組件指 Activity、Fragment、Service、BroadcastReceiver、 ContentProvider 等等。
Activity 間的數據通訊,對於數據量比較大的,避免使用 Intent + Parcelable 的方式,能夠考慮 EventBus 等替代方案,以避免形成 TransactionTooLargeException。
Activity#onSaveInstanceState()方法不是 Activity 生命週期方法,也不保證 必定會被調用。它是用來在 Activity 被意外銷燬時保存 UI 狀態的,只能用於保存臨 時性數據,例如 UI 控件的屬性等,不能跟數據的持久化存儲混爲一談。持久化存儲 應該在 Activity#onPause()/onStop()中實行。
Activity 間經過隱式 Intent 的跳轉,在發出 Intent 以前必須經過 resolveActivity 檢查,避免找不到合適的調用組件,形成 ActivityNotFoundException 的異常。
避免在 Service#onStartCommand()/onBind()方法中執行耗時操做,若是確 實有需求,應改用 IntentService 或採用其餘異步機制完成。
避免在 BroadcastReceiver#onReceive()中執行耗時操做,若是有耗時工做, 應該建立 IntentService 完成,而不該該在 BroadcastReceiver 內建立子線程去作。 說明: 因爲該方法是在主線程執行,若是執行耗時操做會致使 UI 不流暢。可使用 IntentService 、 創 建 HandlerThread 或者調用 Context#registerReceiver (BroadcastReceiver, IntentFilter, String, Handler)方法等方式,在其餘 Wroker 線程 執行 onReceive 方法。BroadcastReceiver#onReceive()方法耗時超過 10 秒鐘,可 能會被系統殺死。
避免使用隱式 Intent 廣播敏感信息,信息可能被其餘註冊了對應 BroadcastReceiver 的 App 接收。 說明: 經過 Context#sendBroadcast()發送的隱式廣播會被全部感興趣的 receiver 接收,惡 意應用註冊監聽該廣播的 receiver 可能會獲取到 Intent 中傳遞的敏感信息,並進行 其餘危險操做。若是發送的廣播爲使用 Context#sendOrderedBroadcast()方法發送 的有序廣播,優先級較高的惡意 receiver 可能直接丟棄該廣播,形成服務不可用, 或者向廣播結果塞入惡意數據。 若是廣播僅限於應用內,則可使用 LocalBroadcastManager#sendBroadcast()實 現,避免敏感信息外泄和 Intent 攔截的風險。 以上廣播可能被其餘應用的以下 receiver 接收致使敏感信息泄漏
添 加 Fragment 時 , 確 保 FragmentTransaction#commit() 在 Activity#onPostResume()或者 FragmentActivity#onResumeFragments()內調用。 不要隨意使用 FragmentTransaction#commitAllowingStateLoss()來代替,任何 commitAllowingStateLoss()的使用必須通過 code review,確保無負面影響。 說明: Activity 可 能 因 爲 各 種 原 因 被 銷 毀 , Android 支 持 頁 面 被 銷 毀 前 通 過 Activity#onSaveInstanceState() 保 存 自 己 的 狀 態 。 但 如 果 FragmentTransaction.commit()發生在 Activity 狀態保存以後,就會致使 Activity 重 建、恢復狀態時沒法還原頁面狀態,從而可能出錯。爲了不給用戶形成很差的體 驗,系統會拋出 IllegalStateExceptionStateLoss 異常。推薦的作法是在 Activity 的 onPostResume() 或 onResumeFragments() ( 對 FragmentActivity )裏執行 FragmentTransaction.commit(),若有必要也可在 onCreate()裏執行。不要隨意改用 FragmentTransaction.commitAllowingStateLoss() 或 者 直 接 使 用 try-catch 避 免 crash,這不是問題的根本解決之道,當且僅當你確認 Activity 重建、恢復狀態時, 本次 commit 丟失不會形成影響時纔可這麼作。
不要在 Activity#onDestroy()內執行釋放資源的工做,例如一些工做線程的 銷燬和中止,由於 onDestroy()執行的時機可能較晚。可根據實際須要,在 Activity#onPause()/onStop()中結合 isFinishing()的判斷來執行。
如非必須,避免使用嵌套的 Fragment。 說明: 嵌套 Fragment 是在 Android API 17 添加到 SDK 以及 Support 庫中的功能, Fragment 嵌套使用會有一些坑,容易出現 bug,比較常見的問題有以下幾種:
10.老是使用顯式 Intent 啓動或者綁定 Service,且不要爲服務聲明 Intent Filter, 保證應用的安全性。若是確實須要使用隱式調用,則可爲 Service 提供 Intent Filter 並從 Intent 中排除相應的組件名稱,但必須搭配使用 Intent#setPackage()方法設置 Intent 的指定包名,這樣能夠充分消除目標服務的不肯定性。
11.Service 須要以多線程來併發處理多個啓動請求,建議使用 IntentService, 可避免各類複雜的設置。 說明: Service 組件通常運行主線程,應當避免耗時操做,若是有耗時操做應該在 Worker 線程執行。 可使用 IntentService 執行後臺任務。
12.對於只用於應用內的廣播,優先使用 LocalBroadcastManager 來進行註冊 和發送,LocalBroadcastManager 安全性更好,同時擁有更高的運行效率。 說明: 對於使用 Context#sendBroadcast()等方法發送全局廣播的代碼進行提示。若是該廣 播僅用於應用內,則可使用 LocalBroadcastManager 來避免廣播泄漏以及廣播被 攔截等安全問題,同時相對全局廣播本地廣播的更高效。
13.當前Activity的onPause方法執行結束後纔會執行下一個Activity的onCreate方法,因此在 onPause 方法中不適合作耗時較長的工做,這會影響到頁面之間的跳 轉效率。
14.不要在 Android 的 Application 對象中緩存數據。基礎組件之間的數據共享 請使用 Intent 等機制,也可以使用 SharedPreferences 等數據持久化機制。
15.使用 Toast 時,建議定義一個全局的 Toast 對象,這樣能夠避免連續顯示 Toast 時不能取消上一次 Toast 消息的狀況(若是你有連續彈出 Toast 的狀況,避免 使用 Toast.makeText)。
16.使用 Adapter 的時候,若是你使用了 ViewHolder 作緩存,在 getView()的 方法中不管這項 convertView 的每一個子控件是否須要設置屬性(好比某個 TextView 設置的文本可能爲 null,某個按鈕的背景色爲透明,某控件的顏色爲透明等),都需 要爲其顯式設置屬性(Textview 的文本爲空也須要設置 setText(""),背景透明也須要 設置),不然在滑動的過程當中,由於 adapter item 複用的緣由,會出現內容的顯示錯 亂。
17.Activity或者 Fragment 中動態註冊BroadCastReceiver 時,registerReceiver() 和 unregisterReceiver()要成對出現。 說明: 若是 registerReceiver()和 unregisterReceiver()不成對出現,則可能致使已經註冊的 receiver 沒有在合適的時機註銷,致使內存泄漏,佔用內存空間,加劇 SystemService 負擔。 部分華爲的機型會對 receiver 進行資源管控,單個應用註冊過多 receiver 會觸發管 控模塊拋出異常,應用直接崩潰。 Activity 的生命週期不對應,可能出現屢次 onResume 形成 receiver 註冊多個,但 最終只註銷一個,其他 receiver 產生內存泄漏。
佈局中不得不使用 ViewGroup 多重嵌套時,不要使用 LinearLayout 嵌套,改用 RelativeLayout,能夠有效下降嵌套數。 說明: Android 應用頁面上任何一個 View 都須要通過 measure、layout、draw 三個步驟 才能被正確的渲染。從 xml layout 的頂部節點開始進行 measure,每一個子節點都需 要向本身的父節點提供本身的尺寸來決定展現的位置,在此過程當中可能還會從新 measure(由此可能致使 measure 的時間消耗爲原來的 2-3 倍)。節點所處位置越 深,套嵌帶來的 measure 越多,計算就會越費時。這就是爲何扁平的 View 結構 會性能更好。 同時,頁面擁上的 View 越多,measure、layout、draw 所花費的時間就越久。要縮 短這個時間,關鍵是保持 View 的樹形結構儘可能扁平,並且要移除全部不須要渲染的 View。理想狀況下,總共的 measure,layout,draw 時間應該被很好的控制在 16ms 之內,以保證滑動屏幕時 UI 的流暢。 要找到那些多餘的 View(增長渲染延遲的 view),能夠用 Android Studio Monitor 裏的 Hierarachy Viewer 工具,可視化的查看全部的 view。 多重嵌套致使 measure 以及 layout 等步驟耗時過多。
在 Activity 中顯示對話框或彈出浮層時,儘可能使用 DialogFragment,而非 Dialog/AlertDialog,這樣便於隨Activity生命週期管理對話框/彈出浮層的生命週期。
源文件統一採用 UTF-8 的形式進行編碼。
禁止在非 ui 線程進行 view 相關操做。
文本大小使用單位 dp,view 大小使用單位 dp。對於 Textview,若是在文字大小肯定的狀況下推薦使用 wrap_content 佈局避免出現文字顯示不全的適配問 題。
禁止在設計佈局時屢次設置子 view 和父 view 中爲一樣的背景形成頁面過分繪製,推薦將不須要顯示的佈局進行及時隱藏。
靈活使用佈局,推薦 Merge、ViewStub 來優化佈局,儘量多的減小 UI佈局層級,推薦使用 FrameLayout,LinearLayout、RelativeLayout 次之。
在須要時刻刷新某一區域的組件時,建議經過如下方式避免引起全局 layout 刷新:
10.儘可能不要使用 AnimationDrawable,它在初始化的時候就將全部圖片加載到內存中,特別佔內存,而且還不能釋放,釋放以後下次進入再次加載時會報錯。 說明: Android 的幀動畫可使用 AnimationDrawable 實現,可是若是你的幀動畫中若是 包含過多幀圖片,一次性加載全部幀圖片所致使的內存消耗會使低端機發生 OOM 異常。幀動畫所使用的圖片要注意下降內存消耗,當圖片比較大時,容易出現 OOM。
11.不能使用 ScrollView 包裹 ListView/GridView/ExpandableListVIew;由於這樣會把 ListView 的全部 Item 都加載到內存中,要消耗巨大的內存和 cpu 去繪製圖面。 說明: ScrollView 中嵌套 List 或 RecyclerView 的作法官方明確禁止。除了開發過程當中遇到 的各類視覺和交互問題,這種作法對性能也有較大損耗。ListView 等 UI 組件自身有 垂直滾動功能,也沒有必要在嵌套一層 ScrollView。目前爲了較好的 UI 體驗,更貼 近 Material Design 的設計,推薦使用 NestedScrollView。
不要經過 Intent 在 Android 基礎組件之間傳遞大數據(binder transaction緩存爲 1MB),可能致使 OOM。
在 Application 的業務初始化代碼加入進程判斷,確保只在本身須要的進程初始化。特別是後臺進程減小沒必要要的業務初始化。
新建線程時,必須經過線程池提供(AsyncTask 或者 ThreadPoolExecutor 或者其餘形式自定義的線程池),不容許在應用中自行顯式建立線程。 說明: 使用線程池的好處是減小在建立和銷燬線程上所花的時間以及系統資源的開銷,解 決資源不足的問題。若是不使用線程池,有可能形成系統建立大量同類線程而致使 消耗完內存或者「過分切換」的問題。另外建立匿名線程不便於後續的資源使用分析, 對性能分析等會形成困擾。
線程池不容許使用 Executors 去建立,而是經過 ThreadPoolExecutor 的方式,這樣的處理方式讓寫的同窗更加明確線程池的運行規則,規避資源耗盡的風險。 說明: Executors 返回的線程池對象的弊端以下:
子線程中不能更新界面,更新界面必須在主線程中進行,網絡操做不能在主線程中調用。
不要在非 UI 線程中初始化 ViewStub,不然會返回 null。
儘可能減小不一樣 APP 之間的進程間通訊及拉起行爲。拉起致使佔用系統資源,影響用戶體驗。
新建線程時,定義能識別本身業務的線程名稱,便於性能優化和問題排查。
ThreadPoolExecutor 設置線程存活時間(setKeepAliveTime),確保空閒時線程能被釋放。
【 推 薦 】 禁 止 在 多 進 程 之 間 用 SharedPreferences 共 享 數 據 , 雖 然 可 以 (MODE_MULTI_PROCESS),但官方已不推薦。
11.謹慎使用 Android 的多進程,多進程雖然可以下降主進程的內存壓力,但會遇到以下問題:
任什麼時候候不要硬編碼文件路徑,請使用 Android 文件系統 API 訪問。 說明: Android 應用提供內部和外部存儲,分別用於存放應用自身數據以及應用產生的用 戶數據。能夠經過相關 API 接口獲取對應的目錄,進行文件操做。
當使用外部存儲時,必須檢查外部存儲的可用性。
應用間共享文件時,不要經過放寬文件系統權限的方式去實現,而應使用FileProvider。
SharedPreference 中只能存儲簡單數據類型(int、boolean、String 等),複雜數據類型建議使用文件、數據庫等其餘方式存儲。
SharedPreference 提 交 數 據 時 , 盡 量 使 用 Editor#apply() ,而非 Editor#commit()。通常來說,僅當須要肯定提交結果,並據此有後續操做時,才使 用 Editor#commit()。 說明: SharedPreference 相關修改使用 apply 方法進行提交會先寫入內存,而後異步寫入 磁盤,commit 方法是直接寫入磁盤。若是頻繁操做的話 apply 的性能會優於 commit, apply 會將最後修改內容寫入磁盤。可是若是但願馬上獲取存儲操做的結果,並據此 作相應的其餘操做,應當使用 commit。
數據庫 Cursor 必須確保使用完後關閉,以避免內存泄漏。 說明: Cursor 是對數據庫查詢結果集管理的一個類,當查詢的結果集較小時,消耗內存不 易察覺。可是當結果集較大,長時間重複操做會致使內存消耗過大,須要開發者在 操做完成後手動關閉 Cursor。 數據庫 Cursor 在建立及使用時,可能發生各類異常,不管程序是否正常結束,必須 在最後確保 Cursor 正確關閉,以免內存泄漏。同時,若是 Cursor 的使用還牽涉 多線程場景,那麼須要自行保證操做同步。
多線程操做寫入數據庫時,須要使用事務,以避免出現同步問題。 說明: Android 的經過 SQLiteOpenHelper 獲取數據庫 SQLiteDatabase 實例,Helper 中會 自動緩存已經打開的 SQLiteDatabase 實例,單個 App 中應使用 SQLiteOpenHelper 的單例模式確保數據庫鏈接惟一。因爲 SQLite 自身是數據庫級鎖,單個數據庫操做 是保證線程安全的(不能同時寫入),transaction 時一次原子操做,所以處於事務中 的操做是線程安全的。 若同時打開多個數據庫鏈接,並經過多線程寫入數據庫,會致使數據庫異常,提示 數據庫已被鎖住。
大數據寫入數據庫時,請使用事務或其餘可以提升 I/O 效率的機制,保證執行速度。
執行 SQL 語句時,應使用 SQLiteDatabase#insert()、update()、delete(),不要使用 SQLiteDatabase#execSQL(),以避免 SQL 注入風險。
10.若是 ContentProvider 管理的數據存儲在 SQL 數據庫中,應該避免將不受信任的外部數據直接拼接在原始 SQL 語句中,可以使用一個用於將 ? 做爲可替換參 數的選擇子句以及一個單獨的選擇參數數組,會避免 SQL 注入。
加載大圖片或者一次性加載多張圖片,應該在異步線程中進行。圖片的加載,涉及到 IO 操做,以及 CPU 密集操做,極可能引發卡頓。
在 ListView,ViewPager,RecyclerView,GirdView 等組件中使用圖片時,應作好圖片的緩存,避免始終持有圖片致使內存泄露,也避免重複建立圖片,引發 性 能 問 題 。 建 議 使 用 Fresco、 Glide等圖片庫。
png 圖片使用 tinypng 或者相似工具壓縮處理,減小包體積。
應根據實際展現須要,壓縮圖片,而不是直接顯示原圖。手機屏幕比較小,直接顯示原圖,並不會增長視覺上的收益,可是卻會耗費大量寶貴的內存。
使用完畢的圖片,應該及時回收,釋放寶貴的內存。
針對不一樣的屏幕密度,提供對應的圖片資源,使內存佔用和顯示效果達到合理的平衡。若是爲了節省包體積,能夠在不影響 UI 效果的前提下,省略低密度圖片。
在 Activity.onPause()或 Activity.onStop()回調中,關閉當前 activity 正在執行的的動畫。
在動畫或者其餘異步任務結束時,應該考慮回調時刻的環境是否還支持業務處理。例如 Activity 的 onStop()函數已經執行,且在該函數中主動釋放了資源,此時回調中若是不作判斷就會空指針崩潰。
使用 inBitmap 重複利用內存空間,避免重複開闢新內存。
10.使用 ARGB_565 代替 ARGB_888,在不怎麼下降視覺效果的前提下,減小內存佔用。 說明: android.graphics.Bitmap.Config 類中關於圖片顏色的存儲方式定義:
11. 儘可能減小 Bitmap(BitmapDrawable)的使用,儘可能使用純色(ColorDrawable)、 漸變色(GradientDrawable)、StateSelector(StateListDrawable)等與 Shape 結 合的形式構建繪圖。
12.謹慎使用 gif 圖片,注意限制每一個頁面容許同時播放的 gif 圖片,以及單個gif 圖片的大小。
13.大圖片資源不要直接打包到 apk,能夠考慮經過文件倉庫遠程下載,減少包體積。
14.根據設備性能,選擇性開啓複雜動畫,以實現一個總體較優的性能和體驗;
15.在有強依賴 onAnimationEnd 回調的交互時,如動畫播放完畢才能操做頁面 , onAnimationEnd 可 能 會 因 各 種 異 常 沒 被 回 調 , 建 議 加 上 超 時 保 護 或 通 過 postDelay 替 代 onAnimationEnd。
16.當 View Animation 執行結束時,調用 View.clearAnimation()釋放相關資源。
禁止使用常量初始化矢量參數構建 IvParameterSpec,建議 IV 經過隨機方式產生。 說明: 使用固定初始化向量,結果密碼文本可預測性會高得多,容易受到字典式攻擊。iv 的做用主要是用於產生密文的第一個 block,以使最終生成的密文產生差別(明文相 同的狀況下),使密碼攻擊變得更爲困難,除此以外 iv 並沒有其它用途。所以 iv 經過 隨機方式產生是一種十分簡便、有效的途徑。
將 android:allowbackup 屬性設置爲 false,防止 adb backup 導出數據。 說明: 在 AndroidManifest.xml 文件中爲了方便對程序數據的備份和恢復在 Android API level 8 之後增長了 android:allowBackup 屬性值。默認狀況下這個屬性值爲 true,故 當 allowBackup 標誌值爲 true 時,便可經過 adb backup 和 adb restore 來備份和恢 復應用程序數據。
在實現的 HostnameVerifier 子類中,須要使用 verify 函數效驗服務器主機名的合法性,不然會致使惡意程序利用中間人攻擊繞過主機名效驗。 說明: 在握手期間,若是 URL 的主機名和服務器的標識主機名不匹配,則驗證機制能夠 回調此接口的實現程序來肯定是否應該容許此鏈接。若是回調內實現不恰當,默認 接受全部域名,則有安全風險。
利用 X509TrustManager 子類中的 checkServerTrusted 函數效驗服務器端證書的合法性。 說明: 在實現的 X509TrustManager 子類中未對服務端的證書作檢驗,這樣會致使不被信 任的證書繞過證書效驗機制。
META-INF 目錄中不能包含如.apk,.odex,.so 等敏感文件,該文件夾沒有通過簽名,容易被惡意替換。
Receiver/Provider 不能在毫無權限控制的狀況下,將 android:export 設置爲 true。
數據存儲在 Sqlite 或者輕量級存儲須要對數據進行加密,取出來的時候進行解密。
阻止 webview 經過 file:schema 方式訪問本地敏感數據。
10.不要廣播敏感信息,只能在本應用使用 LocalBroadcast,避免被別的應用收到,或者 setPackage 作限制。
11.不要把敏感信息打印到 log 中。 說明: 在 APP 的開發過程當中,爲了方便調試,一般會使用 log 函數輸出一些關鍵流程的信 息,這些信息中一般會包含敏感內容,如執行流程、明文的用戶名密碼等,這會讓 攻擊者更加容易的瞭解 APP 內部結構方便破解和攻擊,甚至直接獲取到有價值的敏 感信息。
12.對於內部使用的組件,顯示設置組件的"android:exported"屬性爲 false。 說明: Android 應用使用 Intent 機制在組件之間傳遞數據,若是應用在使用 getIntent(), getAction(),Intent.getXXXExtra()獲取到空數據、異常或者畸形數據時沒有進行異 常捕獲,應用就會發生 Crash,應用不可以使用(本地拒絕服務)。惡意應用可經過向 受害者應用發送此類空數據、異常或者畸形數據從而使應用產生本地拒絕服務。
13.應用發佈前確保 android:debuggable 屬性設置爲 false。
14.使用 Intent Scheme URL 須要作過濾。 說明: 若是瀏覽器支持 Intent Scheme Uri 語法,若是過濾不當,那麼惡意用戶可能經過瀏 覽器 js 代碼進行一些惡意行爲,好比盜取 cookie 等。若是使用了 Intent.parseUri 函 數 , 獲 取 的 intent 必 須 嚴格過濾, intent 至少包含 addCategory(「android.intent.category.BROWSABLE」) , setComponent(null) , setSelector(null)3 個策略。
15.密鑰加密存儲或者通過變形處理後用於加解密運算,切勿硬編碼到代碼中。 說明: 應用程序在加解密時,使用硬編碼在程序中的密鑰,攻擊者經過反編譯拿到密鑰可 以輕易解密 APP 通訊數據。
16.將所須要動態加載的文件放置在 apk 內部,或應用私有目錄中,若是應用必需要把所加載的文件放置在可被其餘應用讀寫的目錄中(好比 sdcard),建議對不可信的加載源進行完整性校驗和白名單處理,以保證不被惡意代碼注入。
17.除非 min API level >=17,請注意 addJavascriptInterface 的使用。 說明: API level>=17,容許 js 被調用的函數必須以@JavascriptInterface 進行註解,所以 不受影響; 對於 API level < 17,儘可能不要使用 addJavascriptInterface,若是必定 要用,那麼:
18.使用 Android 的 AES/DES/DESede 加密算法時,不要使用默認的加密模式ECB,應顯示指定使用 CBC 或 CFB 加密模式。 說明: 加密模式 ECB、CBC、CFB、OFB 等,其中 ECB 的安全性較弱,會使相同的銘文 在不一樣的時候產生相同的密文,容易遇到字典攻擊,建議使用 CBC 或 CFB 模式。
19.不要使用 loopback 來通訊敏感信息。
20.對於不須要使用 File 協議的應用,禁用 File 協議,顯式設置 webView.getSettings().setAllowFileAccess(false),對於須要使用 File 協議的應用,禁止 File 協議調用 JavaScript,顯式設置 webView.getSettings().setJavaScriptEnabled(false)。
21.Android APP 在 HTTPS 通訊中,驗證策略須要改爲嚴格模式。說明:Android APP 在 HTTPS 通訊中,使用 ALLOW_ALL_HOSTNAME_VERIFIER,表示容許和 全部的 HOST 創建 SSL 通訊,這會存在中間人攻擊的風險,最終致使敏感信息可能會被劫持,以及其餘形式的攻擊。
22.Android5.0 之後安全性要求 較高的應用 應該使 用 window.setFlag (LayoutParam.FLAG_SECURE) 禁止錄屏。
23.zip 中不建議容許../../file 這樣的路徑,可能被篡改目錄結構,形成攻擊。 說明:當 zip 壓縮包中容許存在"../"的字符串,攻擊者能夠利用多個"../"在解壓時改變 zip 文件存放的位置,當文件已經存在是就會進行覆蓋,若是覆蓋掉的文件是 so、dex 或者 odex 文件,就有可能形成嚴重的安全問題。
24.開放的 activity/service/receiver 等須要對傳入的 intent 作合法性校驗。
25.加密算法:使用不安全的 Hash 算法(MD5/SHA-1)加密信息,存在被破解的風險,建議使用 SHA-256 等安全性更高的 Hash 算法。
26.Android WebView 組件加載網頁發生證書認證錯誤時,採用默認的處理方法handler.cancel(),中止加載問題頁面。 說明: Android WebView 組件加載網頁發生證書認證錯誤時,會調用 WebViewClient 類的 onReceivedSslError 方法,若是該方法實現調用了 handler.proceed()來忽略該證書 錯誤,則會受到中間人攻擊的威脅,可能致使隱私泄露。
27.直接傳遞命令字或者間接處理有敏感信息或操做時,避免使用 socket 實現,使用可以控制權限校驗身份的方式通信。
不要經過 Msg 傳遞大的對象,會致使內存問題。
不能使用 System.out.println 打印 log。
Log 的 tag 不能是" "。 說明: 日誌的 tag 是空字符串沒有任何意義,也不利於過濾日誌。