想要學習JNI和NDK,首先要知道JNI和NDK分別是什麼,都有什麼做用,這樣才能夠更好的學習和理解JNI和NDK,本篇文章主要做爲學習筆記,以防之後忘記html
定義:JNI即 Java Native Interface
java本地接口java
做用:可讓java和其餘類型語言(例如C和C++)進行交互android
注意:JNI是屬於java的,跟 android 沒有關係bash
定義:NDK即 Native Development Kit
是一個android的一個開發工具包app
做用:快速開發C/C++動態庫,並自動把so和應用打包成APKide
注意:NDK是屬於android的和java無關工具
能夠經過NDK工具 在Android中使用JNI與本地代碼(C、C++)進行交互
JNI是實現的目的,NDK是實現JNI的手段
即在Android 的開發環境中(Android Studio)經過NDK實現JNI的功能
複製代碼
因爲Android Studio2.2以上已經內部集成了NDK 因此只須要在Android Studio內部配置便可,我目前演示的版本爲3.5.3學習
通過這三個步驟就能夠自動生成一個NDK項目開發工具
和普通的項目相比多了這個文件夾,其中native-lib.cpp
是C、C++代碼,CMakelist.txt
是編譯腳本gradle
public class MainActivity extends AppCompatActivity {
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
// Example of a call to a native method
TextView tv = findViewById(R.id.sample_text);
tv.setText(stringFromJNI());
}
/** * A native method that is implemented by the 'native-lib' native library, * which is packaged with this application. */
public native String stringFromJNI();
}
複製代碼
首先加載native-lib.so
,而後調用so中的stringFromJNI
方法,最後把這個方法返回的值顯示在TextView
上
其中native-lib.so
,這個庫的名稱是在CMklist.txt中指定的, stringFromJNI
是一個java中native
方法,其真正的實如今native-lib.cpp
中
#include <jni.h>
#include <string>
extern "C" JNIEXPORT jstring JNICALL Java_com_taobao_alinnkit_ndk1_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
複製代碼
上面的public native String stringFromJNI()
的實現就是在這裏,那麼如何肯定java中的Native方法對應C中的哪一個方法呢,這裏用的是靜態註冊,即Java包名類名_方法名
的形式,後面再繼續講其餘的註冊方式
native-lib.cpp
編譯成native-lib.so
動態庫,並把它編譯到APK中native-lib.so
,而後調用so中的stringFromJNI
方法,最後把這個方法返回的值顯示在TextView
上咱們先看下上面創建的項目的gradle
其中裏面紅色框是配置NDK的,也就是說須要配置externalNativeBuild {}
添加到gradle中,並使用 cmake {}
進行配置
咱們能夠看到Gradle中倆個地方用了externalNativeBuild {}
,一個在defaultConfig
裏面一個在defaultConfig
外面
defaultConfig
外面的externalNativeBuild {}
代碼塊用cmake
制定了CMakeList.txt
的路徑defaultConfig
裏面的externalNativeBuild {}
代碼塊用cmake
主要是填寫CMake
命令參數# For more information about using CMake with Android Studio, read the
# documentation: https://d.android.com/studio/projects/add-native-code.html
# Sets the minimum version of CMake required to build the native library.
cmake_minimum_required(VERSION 3.4.1)
# Creates and names a library, sets it as either STATIC
# or SHARED, and provides the relative paths to its source code.
# You can define multiple libraries, and CMake builds them for you.
# Gradle automatically packages shared libraries with your APK.
add_library( # Sets the name of the library.
native-lib
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
native-lib.cpp)
# Searches for a specified prebuilt library and stores the path as a
# variable. Because CMake includes system libraries in the search path by
# default, you only need to specify the name of the public NDK library
# you want to add. CMake verifies that the library exists before
# completing its build.
find_library( # Sets the name of the path variable.
log-lib
# Specifies the name of the NDK library that
# you want CMake to locate.
log)
# Specifies libraries CMake should link to your target library. You
# can link multiple libraries, such as libraries you define in this
# build script, prebuilt third-party libraries, or system libraries.
target_link_libraries( # Specifies the target library.
native-lib
# Links the target library to the log library
# included in the NDK.
${log-lib})
複製代碼
設置CMake的最低版本
第一個參數:設置這個庫的名字 第二個參數:設置庫的類型,SHARE 動態庫.so後綴 ,STATIC 靜態庫 .a後綴 第三個參數:源文件的相對路徑
能夠定義多個庫,CMake會構建他們,Gradle將自動把共享庫打入APK中
找到一個NDK庫,而且把這個庫的路徑儲存在一個變量中,例如例子中就是找到一個NDK中的log庫(支持android的日誌庫),而且把變量儲存在log-lib變量中
關聯庫,將指定的庫關聯起來,好比上邊的例子,第一個參數:目標庫,第二個參數:將目標庫連接到日誌庫包含在NDK中。
這是一個最基礎的CMakeLists.txt,其實他能夠很是的強大,好比能夠自定義命令,查找文件,設置變量等,推薦參考CMAKE手冊