2016年11月30日 星期三

ANR Example


11-20 17:13:50.988: E/ActivityManager(920): Reason: Input dispatching timed out (Waiting to send non-key event because the touched window has not finished processing certain input events Thread leak were delivered to it over 500.0ms ago.  Wait queue length: 6.  Wait queue head age: 70041.6ms.)
11-20 17:13:50.988: E/ActivityManager(920): Load: 11.95 / 12.85 / 13.07
11-20 17:13:50.988: E/ActivityManager(920): CPU usage from 0ms to 8178ms later:
11-20 17:13:50.988: E/ActivityManager(920):   53% 920/system_server: 18% user + 35% kernel / faults: 15673 minor 323 major


=> UI Thread超過5秒沒響應導致ANR了, Memory leak導致crash

Android debug

 Reading Bug Reports
https://source.android.com/source/read-bug-reports.html



Android NDK Tombstone/Crash 分析
http://woshijpf.github.io/2016/06/14/Android-NDK-Tombstone-Crash-%E5%88%86%E6%9E%90/



紀錄module info和記憶體使用量 
指令1: cd /proc/pid(check by ps) 
           cat statm 
           一共有七個欄位 
           VSS RSS Share Text Lib Data + Stack Dirty page 
  指令2: cd /proc/pid(check by ps) 
           cat status 
 
 
 
 
Call Stack
data\anr\traces.txt
data/system/dropbox
 
 
 
 
BugReport
adb bugreport > bugreport.txt
 
 
 
 
 
 
 

2016年11月17日 星期四

[轉] Java 作用域 public ,private ,protected 及不寫時的區別

在說明這四個關鍵字之前,我想就class之間的關係做一個簡單的定義,對於繼承自己的class,base class可以認為他們都是自己的子女,而對於和自己一個目錄下的classes,認為都是自己的朋友。
1、public:public表明該數據成員、成員函數是對所有用戶開放,所有用戶都可以直接進行調用
2、private:private表示私有,私有的意思就是除了class自己之外,任何人都不可以直接使用,私有財產神聖不可侵犯嘛,即便是子女,朋友,都不可以使用。
3、protected:protected對於子女、朋友來說,就是public的,可以自由使用,沒有任何限制,而對於其他的外部class,protected就變成private。
作用域   當前類 同一package 子孫類 其他package
public     √    √      √    √
protected   √    √     √    ×
friendly    √    √      ×     ×
private    √    ×      ×     ×
不寫時默認為friendly

2016年11月16日 星期三

Android遠程接口之AIDL

Android遠程接口之AIDL——Parcelable、in、out、inout說明
http://blog.csdn.net/yangzhaomuma/article/details/50576017

想像AIDL IPC機制中, clinet和server中間有一塊buffer, 以buffer對client的角度來看, client把數值寫進buffer則屬性就是in, client把數值從buffer拿出來則屬性就是out



Android Service学习之AIDL, Parcelable和远程服务
http://android.blog.51cto.com/268543/537684/



Android序列化——Serializable與Parcelable
http://blog.csdn.net/yangzhaomuma/article/details/50452651


利用Parcelable在Activity之间传输对象
http://blog.csdn.net/tounaobun/article/details/8185855

2016年11月13日 星期日

Android中使用addr2line来分析native信息

http://blog.csdn.net/andy_android/article/details/43985281


prebuilts/gcc/linux-x86/aarch64/aarch64-linux-android-4.9/bin


aarch64-linux-android-addr2line
aarch64-linux-android-ar
aarch64-linux-android-as
aarch64-linux-android-c++ -> aarch64-linux-android-g++
aarch64-linux-android-c++filt
aarch64-linux-android-cpp
aarch64-linux-android-dwp
aarch64-linux-android-elfedit
aarch64-linux-android-g++
aarch64-linux-android-gcc
aarch64-linux-android-gcc-4.9 -> aarch64-linux-android-gcc
aarch64-linux-android-gcc-4.9.x-google
aarch64-linux-android-gcc-ar
aarch64-linux-android-gcc-nm
aarch64-linux-android-gcc-ranlib
aarch64-linux-android-gcov
aarch64-linux-android-gcov-tool
aarch64-linux-android-gdb
aarch64-linux-android-gprof
aarch64-linux-android-ld -> aarch64-linux-android-ld.bfd
aarch64-linux-android-ld.bfd
aarch64-linux-android-ld.gold
aarch64-linux-android-ld.mcld
aarch64-linux-android-nm
aarch64-linux-android-objcopy
aarch64-linux-android-objdump
aarch64-linux-android-ranlib
aarch64-linux-android-readelf
aarch64-linux-android-size
aarch64-linux-android-strings
aarch64-linux-android-strip

aarch64-linux-android-addr2line 用法
aarch64-linux-android-addr2line -e [file_to_check] [program_count (pc)]

ex.
Error Log:  AEE/AED: #00 pc 0000abcd /system/bin/testcrashd
Check Code Error: aarch64-linux-android-addr2line -e testcrashd abcd


2016年11月8日 星期二

你都去哪裡看技術文章?

https://vinta.ws/code/where-to-find-great-content-to-read.html

[轉] Android 打包流程

Ⅱ Apk 的組成結構
本文脈絡採用的是一個由結果反推至過程的流程。 在開始時,我們需要先弄明白,apk 文件也就是 Android 打包流程的產物,是一個什麼類型的文件,它包含了一些什麼內容。 弄清楚了這些,我們就可以帶著目的性,去分析打包流程,可以更好的關注 apk 文件中的這些內容是在打包流程的哪個過程中產生,以及是如何產生的。
眾所周知,apk 文件本質上其實是一個 zip 包。想要知道其中包含了什麼,改後綴直接解壓便可以看到了。 這裡筆者挑軟柿子,解壓了某個未經過加固或者其他手段加密的 Android 安裝包文件,以下為結果截圖:

主要注意紅色標註部分,這一些文件和文件夾是一個 Android 應用基本都具備的。而其他的一些文件和文件夾則是一些第三方庫,或者是其他一些代碼生成的。 接下來,依次大概介紹一下這些文件和文件夾的作用。


2.1. AndroidManifest.xml

這是 Android 應用的全局配置文件,它包含了這個應用的很多配置信息,例如包名、版本號、所需權限、註冊的服務等。可以根據這個文件在相當程度上了解這個應用的一些信息。該文件目前狀態是被編譯為二進位的 XML 文件,可以通過一些工具(如 apktool)反編譯後進行查看。
這裡強烈安利大家升級一下 Android Studio 2.2 Preview,其新功能 Analyze apk是一個很不錯的 apk 分析(~~hack 入門~~)工具。我們可以通過它直接反編譯看到原始的 AndroidManifest.xml 文件,如下圖。

2.2. assets 文件夾

assets 文件夾用於保存需要保持原始文件的資源文件夾,開發過程中拖了什麼到裡面,打包完之后里面還是什麼。一般用於存放音頻,網頁(幫助頁面之類的),字體等文件。主要需要知道的點是,它與 res 文件夾的區分以及如何在應用中訪問該文件夾的資源,如它可以有多級目錄而 res 則只有兩級。

2.3. dex 文件

classes.dex 文件是 Android 系統運行於 Dalvik Virtual Machine 上的可執行文件,也是Android 應用程式的核心所在。項目工程中的 Java 源碼通過 javac 生成 class 文件,再通過 dx 工具轉換為 classes.dex,注意到我們這裡有 classes2.dex 和 classes3.dex。這是方法數超過一個 dex 的上限,分 dex 的結果。分 dex 在 Android 5.0 之前需要開發者自行完成,5.0 後 dx 自帶支持。dex 文件的數據結構不算複雜,如下圖所示。目前一些熱補丁有關的技術,主要便是對 dex 做各種處理。

2.4. lib 文件夾

該目錄存放著應用需要的 native 庫文件。比如一些底層實現的圖片處理、音視頻處理、數據加密的庫以 so 庫的形式在該文件夾中。而該文件夾下有時會多一個層級,這是根據不同CPU 型號而劃分的,如 ARM,ARM-v7a,x86等,如下圖:

2.5. META-INF 文件夾

該目錄的主要作用是用於保證 APK 的完整性以及安全性。該文件夾下,主要有三個文件。如下圖:

先說 MANIFEST.MF,這個文件保存了整個 apk 文件中所有文件的文件名 + SHA-1後的 base64 編碼值。這也就意味著,MANIFEST.MF 象徵著 apk 包的完整性。再說 CERT.RSA,這個文件保存了公鑰和加密方式的信息。最後說 CERT.SF,這個文件與 MANIFEST.MF 的結構一樣,只是其編碼會被被私鑰加密。這樣一來每次安裝時,通過該文件夾中的文件,就可以完成驗證的過程。如果 apk 包被改變了,而篡改者沒有私鑰生成 CERT.SF,則無法完成校驗。

2.6. res 文件夾

顧名思義,該文件夾是資源文件夾。它裡面存放的所有文件都會被映射到 R 文件中,生成對應的資源 ID,便於代碼中通過 ID 直接訪問。其中的資源文件包括了動畫(anim),圖像(drwable),布局(layout),常量值(values),顏色值(colors),尺寸值(dimens),字符串(strings),自定義樣式(styles)等。

2.7. resource.arsc 文件

這個文件可以說是所有文件中結構最複雜的。

它記錄了資源文件,資源文件位置(各個維度的路徑)和資源 id 的映射關係。並且將所有的 string 都存放在了 string pool 中,節省了在查找資源時,字符串處理的開銷。

我們可以使用 Androdi Studio 2.2 Preview 中的新功能 Analyze apk (這個新功能用來分析 apk 非常好用,強烈推薦各位讀者可以嘗試一下)來看看它到底包含了些什麼,一圖勝過千言:

我們可以看到,首先是有個 package 可選,實際上 resource.arsc 是可以包含多個 package 的資源的。 然後可以看到一個 Resource Types 的列表。這裡看到的是 drawable 的 type。 右邊顯示了有多少個 drawable 以及多少項 configurations,以及表的具體內容為 ID - Name - 各個維度的值(在這裡即是資源的路徑),通過這個,我們可以完成通過 id + 對應的 configuration 獲取對應資源的操作。

而後面要提到資源混淆的原理,就是修改這裡各個維度的值,並修改對應 res 裡面的文件夾以及文件名實現的。

具體其完整的數據結構比較複雜,在這裡就不展開說了,有興趣的讀者可以自行查閱信息,甚至寫一個 parser 出來也是非常有意思的。
Ⅲ Android 打包流程
在了解了 apk 文件的結構後,我們開始分析 Android 的打包流程。

3.1 資源

Android 打包流程的第一步,是處理資源文件。

在這個步驟中,起主要作用的是 aapt。

剛剛提及的 AndroidManifest.xml, res 文件夾,resource.arsc 文件的生成都與其有關,簡單來說,aapt 解析項目代碼中的 AndroidManifest.xml,收集項目中 res 文件夾的資源文件及 xml 文件,對其做壓縮以及編譯的處理。在此過程中,分配了資源 id 並生成了 R.java 文件 以及 arsc 文件。

3.2 代碼

上一步得到了 R.java 文件後,將其與項目代碼一起編譯得到 .class文件,然後打包為 jar 包。這個過程中,還會有混淆代碼這一步驟。之後,再通過 dx 工具,將生成的 jar 包與第三方庫的 jar 包一起編譯為 dex 文件。這個過程中,如果是 5.0 以前的系統且超過了 65535 方法數的限制,需要人為的分 dex,5.0 以後則由 dx 工具包辦。
到這一步,實際上 apk 所需要的主要內容已經大致齊全了。只需要把上面生成的 AndroidManifest.xml,classes.dex,res文件夾,resource.arsc 打包進 apk,並且將項目工程中的 assets 以及 lib 目錄一併放入,就有了一個未經簽名的 Android 安裝包了。

3.3 簽名

接下來還缺簡單但是卻關鍵的最後一步,那便是 apk 包的簽名,這一步在之前對 META-INF 的介紹中,實際已有提及。只需要按步驟生成 MANIFEST.MF, CERT.RSA,CERT.SF 並放入META-INF 文件夾即可。
以上便是 Android 打包的基本流程,宏觀來看實際並不複雜,但是其中的一些步驟展開來講,卻是很有內容的,比如 appt 對資源處理的那個部分,R.java 是如何生成的,resource.arsc 又是如何生成的,Android 是怎樣完成對資源的獲取的,這些內容筆者之後會繼續整理分享。
Ⅳ 業內有關技術小結
分析完流程之後,我們來看看目前業內有哪一些與編譯有關的技術可以運用起來的。

4.1 apk 加固

目前業內已經有很多 apk 加固的服務,這裡提及最常見的一種加固方案。

一個比較典型的加固流程如下圖:

實際上是通過外包一層解殼 apk,將我們自己的 dex 文藏在加密 apk 的 dex 中。由於破壞了正常的 dex 結構,所以一般的反編譯工具,如 apktool 並不能直接反編譯 apk。但是如果了解了加密的方式以及方案,實際上要破解得到脫殼 dex 並不複雜,這只是一定程度上提高了 hack 的成本,不過針對一般的 hack 依然很有效。

4.2 快速多渠道包

由於國內有著數不勝數的 Android 應用市場,所以越來越多的渠道包成為了每一個應用的必須。

在之前,開發者一般通過 AndroidManifest.xml 中的meta 信息來區分渠道。在了解了打包流程後,大家應該明白,一旦改變了 AndroidManifest.xml 就意味著要重新打包。

ts(多渠道包的時間) = t (打每個包的耗時) * n (n為渠道數量), n 在大到一定程度後,ts 就會變得非常的大。這顯然是讓開發者十分痛苦的。

要解決這個問題,實際上需要攻破的是,META-INF 的完整性校驗機制。

目前業界比較常用的兩種方案是:

1. META-INF 下添加空文件不會破壞簽名(文件名為渠道號,若 Google 更改簽名機制,有可能失效)

2. apk 文件末尾寫入信息(本質是利用了 zip 文件可以添加 comment 數據結構的特點)
這兩種改動方案都不會導致 MANIFEST.MF 文件的改變,也就不需要再次打包,只需要簡單的讀改文件即可。為廣大開發者節省了上線前漫長的等待渠道包的時間。

4.3 資源混淆

資源混淆通過混淆資源路徑名以及資源文件名,比如:
res/drawable/icon -> r/s/a
這樣不但可以減少安裝包的體積,一定程度上也可以提高破解難度。

該方案目前業內也有兩種實現,但是原理基本一致。入手點皆為resource.arsc。

第一種方案是修改我們剛剛提及的 aapt,使得在生成 resource.arsc 的過程中,就修改掉項目中資源的名稱,實現了資源的混淆。

第二種方案則是在打出 apk 包之後,讀入已生成的 resource.arsc 文件,進行混淆,改寫,同時修改掉 res 文件夾下的資源名稱,完成混淆。最後再重新打包得到混淆資源後的新 apk 文件。
既可以減小體積,又可以一定程度增加被 hack 的難度,如果還有沒有用起來的同學,可以嘗試用起來了。

4.4 熱補丁

由於移動平台的特性,移動應用版本的升級率並不高。這種時候,如果應用應用也可以像網頁那般動態部署,無疑可以帶來非常大的優勢,比如在線修復 bug,小版本的升級,臨時特性的上線等。

目前業界已經有比較多的技術方案了,在這裡我們提及兩種比較有代表性的方案。

1. 通過 native hook 的方式,替換 class 中的方法實現完成熱補丁。

2. classloader 加載新 dex 覆蓋原有 class 完成替換的方案。

因為實際上每種方案都並非幾句話可以講解清楚,本文主要目的也只是做個大概介紹,若讀者有興趣可以谷歌后進一步研究,這裡就不具體展開講了。
實際上還有一些技術,比如使用 Anotation 自動生成代碼,buck exopackage 提高打包速度等。有興趣的話,可以自行查閱,相信可以學到不少知識的。