1. 程式人生 > >Android之JNI① AS3.0以下DNK下載配置和第一個JNI程式

Android之JNI① AS3.0以下DNK下載配置和第一個JNI程式

一、JNI介紹

JNI(Java Native Interface):一個協議,這個協議用來溝通java程式碼和外部的原生代碼(c/c++), 外部的c/c++程式碼也可以呼叫java程式碼。

1.1 C語言的優勢:

①效率上 C/C++是本地語言,比java更高效;

②程式碼移植,如果之前用C語言開發過模組,可以複用已經存在的c程式碼;

③java反編譯比C語言容易,一般加密演算法都是用C語言編寫,不容易被反編譯;

1.2 Java基本資料型別與C語言基本資料型別的對應:

Java型別

JNI型別

C/C++型別

大小

Boolean

jboolean

unsigned char

無符號8位

Byte

jbyte

(signed) char

有符號8位

Char

jchar

unsigned short

無符號16位

Short

jshort

short

有符號16位

Integer

jint/jsize

int / (一說為long)

有符號32位

Long

jlong

long long/(一說_int64)

有符號64位

Float

jfloat

float

32位浮點值

Double

jdouble

double

64位雙精度浮點值

1.3 引用型別對應

              

1.4堆記憶體和棧記憶體的概念

      棧記憶體:系統自動分配和釋放,儲存全域性、靜態、區域性變數,在棧上分配記憶體叫靜態分配大小一般是固定的

      堆記憶體:程式設計師手動分配(malloc/new)和釋放(free/java不用手動釋放,由GC回收),在堆上分配記憶體叫動態分配,一般硬體記憶體有多大堆記憶體就有多大。

二、NDK

 JNI的使用一定要先下載NDK,NDK是什麼:

  • NDK是一系列工具的集合
  • NDK提供了一份穩定、功能有限的API標頭檔案宣告
  • NDK的釋出,使“Java+C”的開發方式終於轉正,成為官方支援的開發方式
  • NDK將使Android平臺支援C開發的開端

2.1 兩種下載方式(第一種不耽誤AS的使用,第二種傻瓜式操作):

點選SDK Manger -> SDK Tools -> NDK -> 點選Apply,等待,NDK下載完成

2.2 NDK的目錄結構:

          docs: 幫助文件

          build/tools:linux的批處理檔案

          platforms:編譯c程式碼需要使用的標頭檔案和類庫

          prebuilt:預編譯使用的二進位制可執行檔案

          sample:jni的使用例子

          source:ndk的原始碼

          toolchains:工具鏈

          ndk-build.cmd:編譯打包c程式碼的一個指令,需要配置系統環境變數

三、NDK配置(AS 3.0版本以下可用,3.0之後需要Android.mk+ndk-build配置編譯

  • 我們先建立一個專案,裡面只有一個MainActivity

  • 右鍵專案 -> Open Module -> Android NDK Location -> OK -> 等待編譯

我們發現根目錄local.properties裡面多了NDK路徑如下圖:

接著我們在根目錄gradle.properties下面加上如下圖:
android.useDeprecatedNdk=true(AS 3.0以上不支援)

繼續我們在module下面的build.gradle下面加上ndk節點如下圖:

ndk {
        moduleName "JNISample"
       
    }

四、編寫JNI介面

  • 我們建立一個JNIUtil的類,編寫一個native方法如下圖:

我們Build -> Make Project一下,我們會發現在/JniTestSample/app/build/intermediates/下面多了一個classes資料夾.我們可以開啟AS下面的Terminal進入到classes下面的debug資料夾下
如下圖:

前面有重點有彎道,請注意
我們在Terminal執行一下javah com.xiaoyuan.jnitestsample.JNIUtil javah是後面是我的包名
你們一替換成自己的包名,執行完這句話以後會有個.h檔案生成出來如下圖所示:

我們基本已經完成一半了,但是我們發現很多小夥伴執行javah的時候會出現不少內部或者外部命令這樣的問題,這樣的問題大多數都是由於java環境變數沒有配好,如何配置環境變數,需要小夥伴自己百度一下了。

  • 生成.h檔案不夠,這只是聲明瞭這個方法,我們還需要實現它,我在main檔案下新建一個jni資料夾如下圖:

新建以後,我們把剛才生成的.h檔案移動到你新建的jni資料夾下,緊接著我們建立一個c++類來實現.h裡面宣告的方法.
我們把.h類純複製一份,把字尾名改成.cpp。裡面實現它的方法,我們在方法裡面返回一句話;
如下圖:

上面include就是咱們的導包,我們看他的方法名是有規律的就是java+包名+類名+方法名

接著我們在JNIUtil裡面加上

static
{
    System.loadLibrary("JNITestSample");//名字注意,需要跟你的build.gradle ndk節點       下面的名字一樣
}

讓系統載入我們編譯成的so。

最後我們來使用一下,看是否可以編譯so. 我們需要在MainActivity來使用一下如下圖:

我們執行一下:OK 我們已經順利的編譯出so如下圖:

並且我們的手機端已經顯示出了我們的“HelloWorld!”。

參考連結:

1. https://www.jianshu.com/p/81a97a43c176