Android——Android下的NDK開發(一)
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。
- 將NDK添加到Android Studio環境中
配置環境變量,方便cmd中的操作,在環境變量Path添加ndk目錄
在cmd中檢查是否安裝成功,輸入ndk-build,出現如下效果即
ok,環境安裝好了我們來創建項目,和我們創建Android工程類似,只不過我們要勾選“include c/c++”
一路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,這樣我們就寫完了,看一下我們運行的效果
OK,今天就給大家分享簡單的NDK環境搭建和簡單的數據獲取,由於我自己也不怎麼會寫c/c++文件(都忘光了),所以後面我邊學習邊給大家繼續分享NDK開發知識(有好的NDK開發知識的同學求共享呀,謝了啊)