輕鬆實現動態獲取Android手機CPU架構型別
阿新 • • 發佈:2019-02-11
1、什麼是動態庫(.so檔案)? .so檔案是unix的動態連線庫,是二進位制檔案,作用相當於windows下的.dll檔案。 他使用了C/C++程式碼編寫的可以操作硬體比java更高階的 底層程式碼,執行速度和效率比其他語言要高。 在Android中呼叫動態庫檔案(*.so)都是通過jni的方式。 Android中載入so檔案的提供的API: void System.load(String pathName); 說明:pathName:檔名+檔案路徑; void System.loadLibrary("libraryName"); 說明:libraryName:動態庫的名字,是原始動態庫去掉前面的lib和.so後的名字,如: “libnative-lib.so”庫,要載入是應寫成“native-lib”, 即System.loadLibrary("native-lib"), 而不能是System.loadLibrary("libnative-lib.so"); 2、為什麼需要動態庫? 有時候原生的Java程式碼編寫的程式不能滿足需求時,如計算量很大,效能要求高, 常見於遊戲開發,我們就需要考慮使用C/C++開發程式,然後通過JNI的方式 來呼叫。 3、載入動態庫能做什麼? 1)、能直接操作硬體,如攝像頭,音視訊編碼和解碼; 2)、更安全,so庫是二進位制的檔案,不容易破解,人無法看懂,程式碼安全度更高。 3)、執行效率高,運算速度快,C/C++編寫的程式可以直接操作記憶體。 4)、Android中提供的好多java介面呼叫的API底層都是通過JNI的方式來呼叫, 如bitmap的壓縮。 5、Android開發為什麼需要NDK開發,什麼是CPU架構型別? 有時候我們需要動態獲取Android手機的cpu型號,這種需求不常見; Android系統中做app開發很多時候我們會整合三方的sdk,少不了因為適配而提供給不 同架構cpu的動態庫(.so檔案),比方說分型類,即時通訊類, Android系統在載入app 中的動態庫的時候,會檢查對應的cpu架構的型號,然後在到對應的lib目錄下載入對應 的庫,這是為什麼,應為Android底層是用C/C++實現的,生成不同架構的cpu可以載入 的庫時使用的指令不一樣(體現在ndk編譯生成多個版本的.so檔案),如: ------------------------------------------------- arm64-v8a armeabi-v7a armeabi mips mips64 x86 x86_64 ------------------------------------------------- 當某個手機載入的庫不是當前手機cpu對應的指令編譯出來的.so檔案見時,程式就會異常 ,所以為了保證程式的穩定性,必須保證動態庫編譯時使用的指令和當前手機cpu可支援的 cpu執行對應,這樣才不會造成程式異常的情況。 6、為甚需要動態獲取CPU架構型別; 當我們在整合三方sdk是,由於有多個版本的.so庫,如果同時匯入我們的工程,那麼造成 的後過就是我們生成的app的體積瞬間會暴漲,比如環信即時通訊IM的動態庫,我查看了一下 ,每個架構的cpu對應的.so動態庫總大小都是12M以上,那麼可想而知,如果我們匯入了3個 不同架構的動態庫,瞬間app就增加了30多M,還不算我們應用自己的大小,對有些使用者來說 在應用市場上下載app第一反應都會看app的大小,至少對我自己來說是這樣,如果某些應用的 app超過30M的樣子我就不想下載了,所用app包的大小直接關係到使用者的體驗,除了支付寶,淘 寶,京東必須的軟體為,基本都會考慮是不是放棄下載。 為了解決三方庫對本應用包的大小營銷,我已我們可以考慮把不懂版本的動態庫壓縮放到我們的服 務器上,讓後在使用者執行我們app的時候動態的獲取使用者手機CPU的架構型別,然後從伺服器下載對 應的動態庫到SDCar上,Android也提供了載入外部的動態庫的API,這樣的話我們app的大小就會減 少二分之一以上,另一個好處就是當我們把對應的庫壓縮有,體積還會減少到原來庫大小的1/3,這 樣的話我們單從載入三庫增加的大小來講,如果原來有3個架構庫,庫總大小為30M,單個大小為10M, 使用壓縮的方式就會減少的單個大小的1/3,即3M多不到4M的樣子,姑且按4M來算吧,而如果全部打包 進app,總大小會在30M,即使壓縮過了還是比較大,如果採用壓縮的話,就會是原來的30/4四捨五入 與等於7,即大小減少到原來的1/7的大小,這樣的話就大大減少了app的大小,同時也不影響程式的運 行。 一下我我分裝的庫,使用了ndk的方式,其他方式目前我還沒發發現,檢測cpu的程式碼是從Android底層 原始碼中找出來的,然後經過自己封裝,通過JNI的方式來完成呼叫:使用很方便,如下; 1、匯入不同架構的.so庫:架構包括 ----------------------------------- arm64-v8a armeabi-v7a armeabi mips mips64 x86 x86_64 ----------------------------------- 每個資料夾下都有一個libnative-lib.so檔案。 2、匯入呼叫so庫的jar包,並新增到lib中: cpu.jar 注意:需要在gradle中的Android標籤下加入: // 設定Jni so檔案路徑 sourceSets { main{ jniLibs.srcDirs = ['libs'] } } 3、呼叫: 通過CPUFrameworkHelper類來完成呼叫,如:CPUFrameworkHelper.isArmCpu(),會返回一個 boolean值 注意: 可以直接整合的庫地址: 專案下載地址在:https://github.com/pgyszhh/CPUTypeHelper/tree/master/mycpu 裡邊有需要的各個版本的.so庫和cpu.jar的包,直接匯入就可以使用。 庫原始碼地址: 編譯動態庫和JIN的原始碼地址為:https://github.com/pgyszhh/CPUTypeHelper下的app目錄,該 目錄下是所有的原始碼, 在CPUFrameworkHelper類中提供的方法有: public static native boolean isArmCpu(); public static native boolean isArm7Compatible(); public static native boolean isMipsCpu(); public static native boolean isX86Cpu(); public static native boolean isArm64Cpu(); public static native boolean isMips64Cpu(); public static native boolean isX86_64Cpu();
效果圖如下: