1. 程式人生 > >【原創】如何檢測Android應用是32位還是64位

【原創】如何檢測Android應用是32位還是64位

本文為個人原創,歡迎轉載,但請務必在明顯位置註明出處!

http://www.jianshu.com/p/8686931d31f0

1、前言

從Android 4.4宣佈支援64位系統以來,各終端方案廠商逐步推出了各自的64位soc解決方案。Google為了相容之前32位系統的應用,在64位系統上也實現了對32位應用的支援。那麼問題就來了,在一個64位系統的Android手機上如何檢測應用是執行在32位還是64位環境?本博文將為大家解答這個問題。

本文會分別對Android系統中的App、Native程序以及動態連結庫的32/64位檢測方法進行介紹。

2、檢測App

任何一個Android手機使用者對APK檔案肯定不會陌生,它是一個Android應用資源的封裝檔案。當你下載安裝一個App之後,從Launcher啟動該應用,系統會由Zygote分叉出一個子程序來提供App執行的虛擬機器和Runtime環境。與32位系統不同的是,在64系統中會同時存在兩個Zygote程序——zygote和zygote64,分別對應32位和64位應用。所以,要進行App的32/64位檢測,只需要看它的父程序是哪個Zygote即可。

下面的例子通過App的PPID資訊——2759,檢測出了終端系統中所有的64位應用,且該方式無需root許可權。

$ adb shell ps |grep zygote
root      2759  1     2131692 87052          0 0000000000 S zygote64
root      2760  1     1574048 53740          0 0000000000 S zygote

$ adb shell ps|grep 2759
root      2759  1     2131692 87052          0 0000000000 S zygote64
system    3257  2759  2339956 158936          0 0000000000 S system_server
radio     3393  2759  1601272 96220          0 0000000000 S com.android.phone
u0_a85    3407  2759  1564856 88740          0 0000000000 S com.android.inputmethod.latin
u0_a20    3422  2759  1970228 167288          0 0000000000 S com.android.systemui
u0_a7     3769  2759  1548288 63384          0 0000000000 S android.ext.services
u0_a13    3958  2759  1896704 131832          0 0000000000 S com.android.launcher3
u0_a6     3989  2759  1562416 94060          0 0000000000 S android.process.acore
u0_a17    4046  2759  1563300 88504          0 0000000000 S android.process.media
u0_a28    4112  2759  1555640 82004          0 0000000000 S com.android.quicksearchbox
u0_a64    4157  2759  1554484 72944          0 0000000000 S com.android.calendar
u0_a57    4215  2759  1572160 83532          0 0000000000 S com.android.email
u0_a77    4231  2759  1554408 67192          0 0000000000 S com.android.exchange
u0_a5     4279  2759  1549136 66072          0 0000000000 S com.android.onetimeinitializer
u0_a10    4299  2759  1552472 74088          0 0000000000 S com.android.providers.calendar
u0_a94    4325  2759  1869948 112984          0 0000000000 S com.android.soundrecorder
system    4345  2759  1561180 73680          0 0000000000 S com.sprd.engineermode
u0_a15    4887  2759  1874612 106196          0 0000000000 S com.android.packageinstaller
u0_a73    5133  2759  2425904 205912          0 0000000000 S com.android.browser

3、檢測Native程序

Andorid手機開機啟動之後,init程序會啟動一些後臺守護程序。通常,這些程序會對整個Android系統起到重要作用,例如Zygote、MediaServer和ServiceManager等。因為這些Native程序並不是通過安裝APK獲得,所以上一章節的方法在這裡並不適用。我們知道Andorid Framework層以下都是繼承自Linux,因此可以採用Linux系統的一些工具和方法來對Native程序進行32/64位系統的檢測。

方法一,通過readelf工具來分析Native程序對應的bin檔案,下面以mediaserver為例

$readelf -h mediaserver 
ELF Header:
  Magic:   7f 45 4c 46 01 01 01 00 00 00 00 00 00 00 00 00 
  Class:                             ELF32
  Data:                              2's complement, little endian
  Version:                           1 (current)
  OS/ABI:                            UNIX - System V
  ABI Version:                       0
  Type:                              DYN (Shared object file)
  Machine:                           ARM
  Version:                           0x1
  Entry point address:               0x1e24
  Start of program headers:          52 (bytes into file)
  Start of section headers:          20980 (bytes into file)
  Flags:                             0x5000000, Version5 EABI
  Size of this header:               52 (bytes)
  Size of program headers:           32 (bytes)
  Number of program headers:         9
  Size of section headers:           40 (bytes)
  Number of section headers:         29
  Section header string table index: 28

從上面的資訊中我們看到mediaserver檔案的Class欄位為ELF32,Machine欄位為ARM。由此可知,在Android 64位系統中,mediaserver執行在32位環境中。

方法二,在執行時通過列印Native程序的記憶體對映列表(maps)來檢測32/64位,這個方法同樣也適用於App的32/64位檢測。這裡以com.android.email為例,從上一章節的程序列表列印可以看到,com.android.email的PID為4215。

u0_a57    4215  2759  1572160 83532          0 0000000000 S com.android.email

然後,通過proc檔案系統便可查詢到PID=4215的記憶體對映列表 (擷取片段)

$adb root
$adb shell cat /proc/4215/maps
......
71ebcb1000-71ebcb3000 r-xp 00000000 103:15 1453                          /system/lib64/libOpenSLES.so
71ebcb3000-71ebcb4000 r--p 00001000 103:15 1453                          /system/lib64/libOpenSLES.so
71ebcb4000-71ebcb5000 rw-p 00002000 103:15 1453                          /system/lib64/libOpenSLES.so
71ebcb5000-71ebcd5000 r--s 00000000 00:12 282                            /dev/__properties__/u:object_r:logd_prop:s0
71ebcd5000-71ebcf5000 r--s 00000000 00:12 287                            /dev/__properties__/u:object_r:log_tag_prop:s0
71ebcf5000-71ebcf6000 r--p 00000000 00:00 0                              [anon:linker_alloc]
71ebcf6000-71ebcf7000 rw-p 00000000 00:00 0                              [anon:linker_alloc_vector]
71ebcf7000-71ebcf8000 r--p 00000000 00:00 0                              [anon:linker_alloc]
71ebcf8000-71ebcf9000 rw-p 00000000 00:00 0                              [anon:linker_alloc]
71ebcf9000-71ebcfb000 r-xp 00000000 103:15 1452                          /system/lib64/libOpenMAXAL.so
71ebcfb000-71ebcfc000 r--p 00001000 103:15 1452                          /system/lib64/libOpenMAXAL.so
71ebcfc000-71ebcfd000 rw-p 00002000 103:15 1452                          /system/lib64/libOpenMAXAL.so
71ebcfd000-71ebcff000 rw-p 00000000 00:01 22281                          /dev/ashmem/dalvik-indirect ref table (deleted)
71ebcff000-71ebd00000 r-xp 00000000 103:15 1565                          /system/lib64/libjnigraphics.so
71ebd00000-71ebd01000 r--p 00000000 103:15 1565                          /system/lib64/libjnigraphics.so
71ebd01000-71ebd02000 rw-p 00001000 103:15 1565                          /system/lib64/libjnigraphics.so
71ebd02000-71ebd04000 rw-p 00000000 00:01 22280                          /dev/ashmem/dalvik-indirect ref table (deleted)
71ebd04000-71ebd05000 r-xp 00000000 103:15 1644                          /system/lib64/libsigchain.so
71ebd05000-71ebd06000 r--p 00000000 103:15 1644                          /system/lib64/libsigchain.so
71ebd06000-71ebd07000 rw-p 00001000 103:15 1644                          /system/lib64/libsigchain.so
......

從上面的列印中可以看出,com.android.email載入的動態連結庫均位於/system/lib64。由此便可判斷com.android.email運行於64位環境。需要注意的是這個方法要root許可權才能檢測。

4、檢測動態連結庫(*.so檔案)

如果想要對一個.so檔案的進行32/64位檢測,那麼採用上一章節中的方法一就可以做到。但是,有native開發經驗的讀者應該知道,64位系統中動態連結庫通常會同時存在32位和64位兩個版本,它們分別位於/system/lib和/system/lib64路徑中。所以,孤立地對某一個.so檔案進行32位/64位檢測並沒有現實意義,應該將其與載入該.so檔案的App或Native程序作為一個整體來分析。

5、後語

本文分別對Android系統中App、Native程序和動態連結庫進行32/64位檢測的方法進行了介紹,希望對大家的學習開發工作有所幫助。