Android Debug 時追蹤 SDK Source Code

不管是除錯還是學習,能夠看到完整的原始碼總是比較方便。Android 本身是開放原始碼,所以可以自行下載後再 attach source code。
自 4.0 以後,Android SDK Manager 也提供了 Sources for Android SDK 的選項,可以直接勾選安裝。

ADT 安裝好後,如果你嘗試追蹤一個 Android Framework 的類別,會看到類似如下的畫面:
source not found

這時,先確認有安裝 SDK 原始碼:
install Sources for Android SDK

然後,到專案裡面的 Android SDK 按右鍵,選擇 Properties:
android sdk properties

在 External location 選擇 SDK 路徑底下的 sources/android-[你要的版本]
set sdk source folder

這時隨便挑一個類別,按右鍵選擇 Open Declaration
Open Declaration

接著應該就會顯示出這個類別的原始碼了:
display the source code

在 Debug 時,若是 Trace 進入了 SDK 原始碼,卻發生了跑錯行號的現象,那麼有兩點需要確認:

  1. 你選擇的原始碼版本有對應到目前 Debug 執行的 Android 版本,例如 Debug 的環境是 Android 4.3.1,那就要使用 android-18 的原始碼。
  2. 用來 Debug 的機器最好是官方提供的模擬器,若在實體裝置上執行,那裝置上安裝的版本不一定是官方版本。我自己在 Nexus 7 上面測試倒是都能對的上就是了…

Android Studio 越來越接近正式發行,這個時候寫 ADT 的筆記好像沒什麼價值了 (?

Android ToyVpn by native code

今兒個練習使用 Android 的 VpnService,為了能使用手邊現有的 C++ 程式碼,需要使用 NDK 來寫原生程式。弄一弄覺得在 Java 與 C 之間切換實在有夠麻煩,索性把 Android SDK 裡面附的 ToyVpn 改用 C 語言重寫一次。Java 部份就只負責 UI 的互動,與一些初始化的動作而已,其餘的部份都交給 C 去執行,應該效能也會更好(吧?)。

大致上運作方式都沒有變,傳輸也依然沒有加密,使用者密碼也還是寫死狀態。
只加上了一個 Keep Alive 的功能,讓它閒置一段時間也不會斷線。

完整的程式碼在 GitHub:
https://github.com/weichenlin/NativeToyVpn

2013/12/20 更新:
增加了一個支援多 client 的 server
主要差異在於需要給每個 client 不同的 ip 做區別
另外還需要稍微分析一下封包的位址才能分辨到底是要給誰的
程式碼一樣放在 GitHub

[參考資料]
一篇很好的 tun/tap 入門教學:http://backreference.org/2010/03/26/tuntap-interface-tutorial/
比較詳細的運作原理:http://www.ibm.com/developerworks/cn/linux/l-tuntap/index.html
tcp/ip stack:https://github.com/saminiir/level-ip

JNI Type Signatures

想要從 C 語言呼叫 Java 時會用到這個。
基本上就是用一些代號來表達函式的參數與回傳值。

各個資料型態與對應的代號:

要注意的地方:

  • 物件名稱以L開頭後面接上完整的名稱,並以分號結尾。
  • 除了表示物件以外,其它的資料型態不需要分號,直接連著就可以。

一些參考網站:
http://docs.oracle.com/javase/1.5.0/docs/guide/jni/spec/types.html
http://87showmin.blogspot.tw/2009/06/java-java-native-interfacejni.html

Android NDK Eclipse 開發環境自動編譯設定

NDK不太常用,每次要用時都要重新翻資料找設定方法,乾脆寫一篇記錄下來。

環境設定,只需要一開始做一次:
1. 先確認 NDK 有安裝好:http://developer.android.com/sdk/ndk/index.html

2. 安裝 Eclipse 需要的套件:
CDT package
NDK package

3. 設定 NDK 路徑,工具列 Window -> Preferences -> Android -> NDK ,輸入 NDK 的路徑:
ndk path

專案設定,每個要使用 NDK 的專案都要做:
1. 專案上面按右鍵,Android Tools -> Add Native Support :
add_ndk_support
然後設定一個 library 的名稱:
enter library name
這時 Android.mk 與 C++ 原始碼檔案都幫你建立好了。

2. 設定 C++ Include 路徑,進入專案 Properties ,C/C++ General -> Paths and Symbols,加入:

include path
${env_var:ANDROID_NDK} 是我在系統 PATH 裡設定好的 NDK 所在位置。

額外的工具:使用 javah 自動產生 .h 檔
1. 設定 Eclipse External Tools ,工具列 Run -> External Tools -> External Tools Configurations :

  • Name 取一個與專案有關的比較好記。
  • Location 填入 javah 執行檔的路徑。
  • Working Directory 填入

    其中 NdkProject 是專案名稱。
  • Arguments 填入

    external tool 1
    最後的 com.example.ndkproject.MainActivity 是要使用 NDK 的類別的 fully qualified class name 。(若是在 Linux 底下,classpath 要改成 ${workspace_loc:/NdkProject/bin/classes})
  • 切換到 Refresh 分頁,勾選 Refresh resources upon completion ,使用 Specific resources 選項,在右邊選擇 jni 資料夾
    external tool 2

2. 在需要呼叫 NDK 的 Java 原始碼中加入程式,用來載入 library 並定義原生函式:

3. 按下工具列的 Run -> External Tools -> 剛剛設定的 javah ,即會幫你產生 Native 用的 .h 檔案。

可能遇到的問題
1. 出現警告: Android NDK: WARNING: APP_PLATFORM android-14 is larger than android:minSdkVersion 8 in ./AndroidManifest.xml
解決方法:在 jni 資料夾中新增 Application.mk 檔案,指定 SDK 的版本

以上都設定好,就會看到每次執行 debug 時,會自動使用 ndk 編譯了。