Android——Android下的NDK開發(一)

編程語言 Java Android Studio C語言 科技優家 2017-04-20

1,NDK是什麼?為什麼要進行NDK開發?

NDK:Native Development Kit。Android應用運行在Dalvik虛擬機中。NDK允許開發人員使用本地代碼語言(例如C和C++)實現應用的部分功能。這樣以代碼重用的形式能夠給某類應用提供方便,而且在某些情況下能提高運行速度。

在實際開發中,那為什麼要學習JNI,JNI會學習到比較底層的東西,java可以實現上層應用的開發,但是不能寫底層驅動,有些android項目必須和底層硬件打交道,比如要精確快速的獲取某種傳感器的值,那麼java是不能辦到的,那怎麼辦,就通過JNI開發,通過c/c++完成底層驅動或者值得獲取,然後將值傳回到java層。同樣java層也可以將數據傳遞給c/c++層,這樣通過JNI完成數據的交互。常見的產品如藍牙、運動手環等。

2,NDK環境搭建

在Android studio2.2之後就可以使用我們的Android開發工具來開發了

  • 安裝NDK

Tools->Android->SDK Manager->SDK Tools選中CMake和NDK,點擊確認,軟件會自動安裝NDK。

Android——Android下的NDK開發(一)
  • 將NDK添加到Android Studio環境中
Android——Android下的NDK開發(一)

配置環境變量,方便cmd中的操作,在環境變量Path添加ndk目錄

Android——Android下的NDK開發(一)

在cmd中檢查是否安裝成功,輸入ndk-build,出現如下效果即

Android——Android下的NDK開發(一)

ok,環境安裝好了我們來創建項目,和我們創建Android工程類似,只不過我們要勾選“include c/c++”

Android——Android下的NDK開發(一)

一路Next ,最後創建項目,創建項目之後我們坑定有些文件沒有見過,首先看一下native-lib.cpp類

#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_qianmo_ndktest_MainActivity_stringFromJNI(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "Hello from C++";
    return env->NewStringUTF(hello.c_str);
}

什麼?一臉懵逼!嗯,我現在也和你一樣,不過我們查查網上的資料來看看裡面的代表什麼意思

其中extern “C” 是表示可以供外部調用。 
jstring是返回值,maxFromJNI是Java代碼中定義的函數。(過會兒會寫在MainActivity裡,一般是Java_包名_使用地方的類名_方法名) 
Java_com_qianmo_ndktest_MainActivity_這一段是調用這個函數的java類以及它所在的包。 
JNIEnv* env 和 jobject object是啥我也不知道,很顯然這倆必須要用,貌似第一個代表的是什麼指針什麼的,後面以object類型命名的猜測可能是對象吧(手動微笑)。 

繼續看我們Activity中調用

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 = (TextView) 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裡的函數和東西
    static {
        System.loadLibrary("native-lib");
    }
//這就是對應的c++文件中的方法了
public native String stringFromJNI;

CMakeLists.txt,等等,這怎麼生成了一個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).
 src/main/cpp/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最低版本,如果不知道就複製吧
cmake_minimum_required(VERSION 3.4.1)

# 第一個native-lib是供java調用的文件, SHARED 表示將代碼編譯成動態庫即so庫,相對 的還有一個STATIC表示靜態
# 最後倆是所有cpp的名字和相對本文件的位置,這裡在一個文件夾中就直接寫名字了,文件有多少寫多少
add_library(native-lib SHARED native-lib.cpp Max.cpp)

# 我的理解是java要連接到native-lib,和一些其它的東西
target_link_libraries(native-lib)

OK,上面把基本的一些意思讀懂了,那麼我們就依葫蘆畫瓢,仿照著寫一個試試唄,首先創建NDKUtils.java類,添加c++方法getStringFromC,添加hello-jin.cpp文件導入,代碼如下:

public class NDKUtils {

    static {
        System.loadLibrary("hello-jni");//導入生成的鏈接庫文件
    }

    public staticnative String getStringFromC;


}

繼續我們創建hello-jin.cpp文件,並創建 getStringFromC方法,代碼如下:

#include <jni.h>
#include <string>

extern "C"
JNIEXPORT jstring JNICALL
Java_com_qianmo_ndktest_NDKUtils_getStringFromC(
        JNIEnv *env,
        jobject /* this */) {
    std::string hello = "這裡是來自與c++";
    return env->NewStringUTF(hello.c_str);
}

在CMakeLists.txt文件中添加java和c++文件的鏈接

add_library(hello-jni SHARED src/main/cpp/hello-jni.cpp)

target_link_libraries(hello-jni)

ok,這樣我們就寫完了,看一下我們運行的效果

Android——Android下的NDK開發(一)

OK,今天就給大家分享簡單的NDK環境搭建和簡單的數據獲取,由於我自己也不怎麼會寫c/c++文件(都忘光了),所以後面我邊學習邊給大家繼續分享NDK開發知識(有好的NDK開發知識的同學求共享呀,謝了啊)

相關推薦

推薦中...