Android JNI和NDK學習(一):NDK學習

概述

想要學習JNI和NDK,首先要知道JNI和NDK分別是什麼,都有什麼做用,這樣才能夠更好的學習和理解JNI和NDK,本篇文章主要做爲學習筆記,以防之後忘記html

JNI介紹

定義:JNI即 Java Native Interface java本地接口java

做用:可讓java和其餘類型語言(例如C和C++)進行交互android

注意:JNI是屬於java的,跟 android 沒有關係bash

NDK 介紹

定義:NDK即 Native Development Kit 是一個android的一個開發工具包app

做用:快速開發C/C++動態庫,並自動把so和應用打包成APKide

注意:NDK是屬於android的和java無關工具

JNI和NDK的聯繫

能夠經過NDK工具  在Android中使用JNI與本地代碼(C、C++)進行交互
 
 JNI是實現的目的,NDK是實現JNI的手段
 
 即在Android 的開發環境中(Android Studio)經過NDK實現JNI的功能
複製代碼

使用Android Studio 建立一個NDK項目

因爲Android Studio2.2以上已經內部集成了NDK 因此只須要在Android Studio內部配置便可,我目前演示的版本爲3.5.3學習

通過這三個步驟就能夠自動生成一個NDK項目開發工具

和普通的項目相比多了這個文件夾,其中native-lib.cpp是C、C++代碼,CMakelist.txt是編譯腳本gradle

下面分析下這個項目

MainActivity

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

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包名類名_方法名的形式,後面再繼續講其餘的註冊方式

整個調用流程

  • Gradle調用外部構建腳本CMklist.txt
  • CMake按照腳本中的命令將C++源文件native-lib.cpp編譯成native-lib.so動態庫,並把它編譯到APK中
  • 運行時首先加載native-lib.so,而後調用so中的stringFromJNI方法,最後把這個方法返回的值顯示在TextView

配置Gradle支持NDK

咱們先看下上面創建的項目的gradle

其中裏面紅色框是配置NDK的,也就是說須要配置externalNativeBuild {}添加到gradle中,並使用 cmake {}進行配置

咱們能夠看到Gradle中倆個地方用了externalNativeBuild {},一個在defaultConfig裏面一個在defaultConfig外面

  • defaultConfig外面的externalNativeBuild {}代碼塊用cmake制定了CMakeList.txt的路徑
  • defaultConfig裏面的externalNativeBuild {}代碼塊用cmake主要是填寫CMake命令參數

CMakeLists.txt 文件分析

# 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_minimum_required(VERSION 3.4.1)

設置CMake的最低版本

add_library

第一個參數:設置這個庫的名字 第二個參數:設置庫的類型,SHARE 動態庫.so後綴 ,STATIC 靜態庫 .a後綴 第三個參數:源文件的相對路徑

能夠定義多個庫,CMake會構建他們,Gradle將自動把共享庫打入APK中

find_library

找到一個NDK庫,而且把這個庫的路徑儲存在一個變量中,例如例子中就是找到一個NDK中的log庫(支持android的日誌庫),而且把變量儲存在log-lib變量中

target_link_libraries

關聯庫,將指定的庫關聯起來,好比上邊的例子,第一個參數:目標庫,第二個參數:將目標庫連接到日誌庫包含在NDK中。

這是一個最基礎的CMakeLists.txt,其實他能夠很是的強大,好比能夠自定義命令,查找文件,設置變量等,推薦參考CMAKE手冊

參考:

blog.csdn.net/carson_ho/a…

blog.csdn.net/afei__/arti…

www.jianshu.com/p/b4431ac22…

相關文章
相關標籤/搜索