前言
現(xiàn)在我們從零開始NDK開發(fā)早歇,本篇博客將介紹如何創(chuàng)建一個native方法,并在Activity中調(diào)用。如果大家對于NDK開發(fā)的配置不了解的話,可以查看:
Android Studio NDK開發(fā)(一):NDK開發(fā)準(zhǔn)備工作(CMake方式)
Welcome to JNI
1.新建c文件
這里我們不使用Android Studio默認(rèn)創(chuàng)建的C/C++文件native-lib.cpp沾歪,鼠標(biāo)點擊cpp文件夾(如果沒有可在main文件夾下新建),右擊new -> C/C++ Source File雾消,輸入文件名zhangpan(可自定義)灾搏,type我選的是.c,點擊ok立润,然后就可以看見cpp文件夾下生成了zhangpan.c文件狂窑,此時該文件頂部是有提示文字的,提醒你去配置CMakeLists桑腮。
2.配置CMakeLists.txt
在CMakeList(如果沒有可在app下新建)中添加:
add_library( # Sets the name of the library.
zhangpan
# Sets the library as a shared library.
SHARED
# Provides a relative path to your source file(s).
src/main/cpp/zhangpan.c)
target_link_libraries( # Specifies the target library.
zhangpan
# Links the target library to the log library
# included in the NDK.
${log-lib} )
點擊Snyc Now泉哈,以上就將添加了自己寫的庫,并將自己的庫與NDK中的庫進行連接破讨。
3.配置build.gradle
如果新建工程的時候丛晦,已經(jīng)勾選了include C/C++ support,這里就已經(jīng)生成了添忘,可跳過采呐。如果沒有,可在app下的build.gradle如下添加搁骑。
在android下defaultConfig下添加:
externalNativeBuild {
cmake {
//默認(rèn)是cppFlags ""
//如果要修改Customize C++ support部分,可在這里加入
cppFlags ""
}
}
再在android下添加:
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
}
4.native方法的聲明
我在MainActity中聲明了一個native方法(可自定義)
public native String getStringFromJNI();
這里我做的就是Java中調(diào)用C的函數(shù)又固,從而返回一個字符串仲器,并展示在界面中。
光標(biāo)定位在getStringFromJNI中仰冠,Alt + Enter選中第一個乏冀,創(chuàng)建native函數(shù)。
#include "jni.h"
#include <stdlib.h>
JNIEXPORT jstring JNICALL
Java_com_zhangpan_myjnicmake_MainActivity_getStringFromJNI(
JNIEnv *env,
jobject jobj) {
//JNIEnv 結(jié)構(gòu)體指針
//env二級指針(對應(yīng)c洋只,在C++是一個結(jié)構(gòu)體的一級指針)辆沦,由于需要用到JNIEnv變量,而JNIEnv是結(jié)構(gòu)體指針识虚,需要一個變量來表示JNIEnv肢扯,所以這個變量就是二級指針,而C++中有this關(guān)鍵字的担锤,直接可以表示
//每個native函數(shù)蔚晨,都至少有兩個參數(shù)(JNIEnv*,jclass或者jobject)
//1.當(dāng)native方法為靜態(tài)方法時肛循,jclass代表native方法所屬類的class對象(MainActivity.class)
//2.當(dāng)native方法為非靜態(tài)方法時铭腕,jobject代表native方法所屬類的對象
return (*env)->NewStringUTF(env, "Welcome to JNI");
}
注意:
(以下所述银择,方法代表Java中的方法,函數(shù)代表C/C++中的函數(shù))
1.添加頭文件jni.h(用于關(guān)聯(lián)Java和C/C++)和stdlib.h
2.JNIEXPORT jstring JNICALL中jstring是函數(shù)的返回值累舷,其余兩個可不用管浩考,類似于Java中的關(guān)鍵字作用。
3.點擊參數(shù)中的JNIEnv進入jni.h中被盈,可以看出JNIEnv是一個結(jié)構(gòu)體指針析孽,因此env就是一個二級指針,記住這里是C的代碼害捕,如果是C++绿淋,這里的env只是一個結(jié)構(gòu)體的一級指針。有人可能會問尝盼,為什么在C和C++中會不一樣呢吞滞,這是因為C++中已經(jīng)有了this關(guān)鍵字了,而C中是不存在的盾沫,而這里又需要用到JNIEnv的變量裁赠,所以為了表示它,在C中就有了env這個二級指針赴精。其實C++中雖然傳入了this關(guān)鍵字佩捞,但是其函數(shù)內(nèi)部還是調(diào)用了C的代碼,也就是說C++在C的基礎(chǔ)上還封裝了一層蕾哟。
4.每個native函數(shù)都至少有兩個參數(shù)JNIEnv*一忱,jclass或者jobject。
5.當(dāng)native方法為靜態(tài)方法時谭确,jclass代表native方法所屬類的class對象(MainActivity.class)帘营;
當(dāng)native方法為非靜態(tài)方法時,jobject代表native方法所屬類的對象逐哈。
5.MainActivity
添加靜態(tài)代碼塊芬迄,加載自己寫的庫,調(diào)用并展示在TextView中昂秃。
/**
* A native method that is implemented by the 'native-lib' native library,
* which is packaged with this application.
*/
public native String getStringFromJNI();
// Used to load the 'native-lib' library on application startup.
static {
System.loadLibrary("zhangpan");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.sample_text);
tv.setText(getStringFromJNI());
}
點擊運行
展望
Welcome to JNI已經(jīng)完成禀梳,也知道了Java是如何調(diào)用C/C++中的函數(shù)的,但是我們是不是存在疑問肠骆,比如jstring到底是什么算途,C/C++怎樣訪問Java中的屬性和方法呢?請看接下來的博客哗戈。