1. 程式人生 > >輕鬆實現動態獲取Android手機CPU架構型別

輕鬆實現動態獲取Android手機CPU架構型別

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();

效果圖如下: