一、Jni簡介
Jni全稱是java Native Interface(Java本地接口),它是java平臺的一部分,允許Java代碼和其他語言編寫的代碼進行交互,它使得在Java虛擬機(JVM)內部運行的Java代碼可以和其他語言編寫的應用程序或庫進行交互操作。
二、hello-jni項目簡介
截圖如下:

這里先對各個文件夾進行分析:
1、jni文件夾
要想在Java項目里或是Android項目里面調用native代碼必須在項目下面新建一個jni目錄,在這個目錄里面編寫有關native代碼,并且編寫編譯規則(Android.mk文件),這里重點細說一下這個文件~
這個文件主要是規定編譯器如何去生成.so文件、引用的頭文件目錄、需要編譯的.c .cpp .a等文件,hello-jni里面的Android.mk文件很簡單并且只有一個,所以先簡單分析一下hello-jni提供的Android.mk文件~
LOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_MODULE := hello-jniLOCAL_SRC_FILES := hello-jni.cinclude $(BUILD_SHARED_LIBRARY)LOCAL_PATH := $(call my-dir)
LOCAL_PATH這個變量用于給定當前文件的路徑,my-dir這個宏是由Build System提供的,用于指出當前文件夾所在的路徑。
include $(CLEAR_VARS)
這個include的作用就是指向一個編譯腳本,指向哪個腳本由括號內的變量決定,CLEAR_VARS指向了一個清理以LOCAL_開頭的變量(LOCAL_PATH這個變量排除在外,因為每個模塊都會用到當前文件的路徑)。在Android.mk中可能會存在很多的模塊,每個模塊都會有一些變量,而且這些變量又都是全局的,Build System每次只能編譯一個模塊,所以在每一個模塊的最開始都要執行CLEAR_VARS這個腳本來清理其他模塊的變量。
LOCAL_MODULE :=hello-jni
這個變量是規定Android.mk文件執行完成之后生成的so文件的名字,在生成so文件的過程中Build System會自動加上lib和.so后綴,比如這個,最后會生成libhello-jni.so這個文件,這個文件可以再代碼里面加載,代碼如下:
/* this is used to load the 'hello-jni' library on application * startup. The library has already been unpacked into * /data/data/com.example.hellojni/lib/libhello-jni.so at * installation time by the package manager. */ static { System.loadLibrary("hello-jni"); }LOCAL_SRC_FILES :=hello-jni.c這個變量規定要打包的Native的源碼,如示例中的hello-jni.c,這里不需要列出頭文件,因為Build System會自動加載頭文件的,缺省的C++擴展名為cpp,要想改變C++的擴展名,修改LOCAL_CPP_EXTENSION就可以了。
include $(BUILD_SHARED_LIBRARY)
這個BUILD_SHARED_LIBRARY是由Build System提供的一個變量,指向一個編譯腳本,用來收集上一次執行CLEAR_VARS這個腳本之后所有的LOCAL信息,并且決定編譯生成什么類型的文件。
BUILD_SHARED_LIBRARY 編譯為動態庫
BUILD_STATIC_LIBRARY 編譯為靜態庫
BUILD_EXECUTABLE 編譯為Native程序
這個hello-jni的Android.mk文件就說完了~
Application.mk:這個文件是描述你的應用程序中所需要的模塊(靜態庫還是動態庫)
APP_ABI :=all 這個表示編譯出所有平臺。
我們知道,這個ABI表示ApplicationBinaryInterface(應用程序二進制接口),一個應用程序一般是由高級語言編寫完成之后,經過編譯生成匯編程序,然后在鏈接生成二進制文件,這個生成二進制文件的過程中有一個ABI的概念,決定了生成的二進制程序可以運行在哪個CPU架構上(也就是不同的平臺)
這個Application.mk文件就說完了~
hello-jni.c文件是Native源碼文件
/* * Copyright (C) 2009 The Android Open Source PRoject * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * */#include <string.h>#include <jni.h>/* This is a trivial JNI example where we use a native method * to return a new VM String. See the corresponding Java source * file located at: * * apps/samples/hello-jni/project/src/com/example/hellojni/HelloJni.java */jstringJava_com_example_hellojni_HelloJni_stringFromJNI( JNIEnv* env, jobject thiz ){#if defined(__arm__) #if defined(__ARM_ARCH_7A__) #if defined(__ARM_NEON__) #if defined(__ARM_PCS_VFP) #define ABI "armeabi-v7a/NEON (hard-float)" #else #define ABI "armeabi-v7a/NEON" #endif #else #if defined(__ARM_PCS_VFP) #define ABI "armeabi-v7a (hard-float)" #else #define ABI "armeabi-v7a" #endif #endif #else #define ABI "armeabi" #endif#elif defined(__i386__) #define ABI "x86"#elif defined(__x86_64__) #define ABI "x86_64"#elif defined(__mips64) /* mips64el-* toolchain defines __mips__ too */ #define ABI "mips64"#elif defined(__mips__) #define ABI "mips"#elif defined(__aarch64__) #define ABI "arm64-v8a"#else #define ABI "unknown"#endif return (*env)->NewStringUTF(env, "Hello from JNI ! Compiled with ABI " ABI ".");}這個源文件的編寫和普通的C文件不太一樣,因為是和Java打交道的嘛~這個jstring是jvm里面的字符串,下面是Java和C++的類型在JVM里面的映射:
函數名稱之所以要這么寫是因為要和調用這個函數的java代碼交互,截圖如下:
Java是固定的,com_example_hellojni這個是包名,HelloJni這個是類名,stringFromJNI這個就是Java的native方法了~
這個說完了函數名稱編寫,然后看一下這個函數的參數
第一個JNIEnv類型的參數,通過這個參數我們可以在Native代碼里面獲取一些Java代碼的信息。我們在Java端的函數是沒有這個參數的,這個參數是從Java端自動傳過來的,作用是提供給JNI一個Java的運行環境,在Java里面就是JVM,在Android里面就是Dalvik VM。
第二個jobject類型的參數的意思是,如果這個Native方法是靜態的話,jobject表示的就是這個包含這個Native方法的類的實例,如果這個Native方法不是靜態的話,jobject表示的就是這個類的對象的實例。
hello-jni.c就到這里了。
有什么疑問可以加我QQ:763949771,一起交流學習。如有錯誤請留言指正~
新聞熱點
疑難解答