一、在Native层返回字符串
1、MainActivity.kt
package com.guide.test
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
import kotlinx.android.synthetic.main.activity_main.*
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
sample_text.text = stringFromJNI()
}
external fun stringFromJNI(): String
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
2、native-lib.cpp
extern "C" JNIEXPORT jstring JNICALL Java_com_guide_test_MainActivity_stringFromJNI(
JNIEnv *env,
jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
运行结果:
说明:将native层的字符串传递到java层。
二、在Native层返回一个int型二维数组(inta[ ][ ])
1、MainActivity.kt
package com.guide.test
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
private var name = "I am at Java" //类属性
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
val array = getTwoArray(6)
for (s in array) {
for (a in s) {
Log.d(TAG, "a:" + a)
}
}
}
//参数代表几行几列数组 ,形式如:int a[dimon][dimon]
external fun getTwoArray(dimon: Int): Array<IntArray>
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
2、native-lib.cpp
/*
* Class:
* Method: getTwoArray
* Signature: (I)[[I
*/
//通过构造一个数组的数组, 返回 一个二维数组的形式
extern "C" JNIEXPORT jobjectArray JNICALL Java_com_guide_test_MainActivity_getTwoArray
(JNIEnv *env, jobject object, jint dimion) {
jclass intArrayClass = env->FindClass("[I"); //获得一维数组 的类引用,即jintArray类型
//构造一个指向jintArray类一维数组的对象数组,该对象数组初始大小为dimion
jobjectArray obejctIntArray = env->NewObjectArray(dimion, intArrayClass, NULL);
//构建dimion个一维数组,并且将其引用赋值给obejctIntArray对象数组
for (int i = 0; i < dimion; i++) {
//构建jint型一维数组
jintArray intArray = env->NewIntArray(dimion);
jint temp[10]; //初始化一个容器,假设 dimion < 10 ;
for (int j = 0; j < dimion; j++) {
temp[j] = i + j; //赋值
}
//设置jit型一维数组的值
env->SetIntArrayRegion(intArray, 0, dimion, temp);
//给object对象数组赋值,即保持对jint一维数组的引用
env->SetObjectArrayElement(obejctIntArray, i, intArray);
env->DeleteLocalRef(intArray); //删除局部引用
}
return obejctIntArray; //返回该对象数组
}
运行结果:
a:0
a:1
a:2
a:3
a:4
a:5
a:1
a:2
a:3
a:4
a:5
a:6
a:2
a:3
a:4
a:5
a:6
a:7
a:3
a:4
a:5
a:6
a:7
a:8
a:4
a:5
a:6
a:7
a:8
a:9
a:5
a:6
a:7
a:8
a:9
a:10
三、在Native层操作Java层的类 :读取/设置类属性
1、MainActivity.kt
package com.guide.test
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
private var name = "I am at Java" //类属性
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
//sample_text.text = stringFromJNI()
Log.d(TAG, "before name:$name")
setName()
Log.d(TAG, "after name:$name")
}
external fun setName()
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
}
2、native-lib.cpp
/*
* Class: com_feixun_jni_HelloJni
* Method: set_name
* Signature: ()V
*/
//在Native层操作Java对象,读取/设置属性等
extern "C" JNIEXPORT void JNICALL Java_com_guide_test_MainActivity_setName
(JNIEnv *env, jobject obj) //obj代表执行此JNI操作的类实例引用
{
//获得jfieldID 以及 该字段的初始值
jfieldID nameFieldId;
jclass cls = env->GetObjectClass(obj); //获得Java层该对象实例的类引用,即HelloJNI类引用
nameFieldId = env->GetFieldID(cls, "name", "Ljava/lang/String;"); //获得属性句柄
if (nameFieldId == NULL) {
LOGD("没有得到name 的句柄Id\n");
}
jstring javaNameStr = (jstring) env->GetObjectField(obj, nameFieldId); // 获得该属性的值
const char *c_javaName = env->GetStringUTFChars(javaNameStr, NULL); //转换为 char *类型
//string str_name = c_javaName;
//cout << "the name from java is " << str_name << endl; //输出显示
LOGD("the name from java is==>%s", c_javaName);
env->ReleaseStringUTFChars(javaNameStr, c_javaName); //释放局部引用
//构造一个jString对象
char *c_ptr_name = "I come from Native";
jstring cName = env->NewStringUTF(c_ptr_name); //构造一个jstring对象
env->SetObjectField(obj, nameFieldId, cName); // 设置该字段的值
}
结果:
before name:I am at Java
the name from java is==>I am at Java
after name:I come from Native
四、在Native层操作Java层的类:回调Java方法
1、MainActivity.kt
package com.guide.test
import android.os.Bundle
import android.support.v7.app.AppCompatActivity
import android.util.Log
class MainActivity : AppCompatActivity() {
private val TAG = "MainActivity"
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_main)
doCallBack()
}
external fun doCallBack() //Native层会调用callback()方法
companion object {
// Used to load the 'native-lib' library on application startup.
init {
System.loadLibrary("native-lib")
}
}
//Native层回调的方法实现
fun callback(fromNative: String) {
Log.d(TAG, " I was invoked by native method ############# " + fromNative)
}
}
2、native-lib.cpp
/*
* Class: com_feixun_jni_HelloJni
* Method: doCallBack
* Signature: ()V
*/
//Native层回调Java类方法
extern "C" JNIEXPORT void JNICALL Java_com_guide_test_MainActivity_doCallBack
(JNIEnv *env, jobject obj) {
//回调Java中的方法
jclass cls = env->GetObjectClass(obj);//获得Java类实例
jmethodID callbackID = env->GetMethodID(cls, "callback", "(Ljava/lang/String;)V");//或得该回调方法句柄
if (callbackID == NULL) {
LOGD("getMethodId is failed \n");
}
jstring native_desc = env->NewStringUTF(" I am Native");
env->CallVoidMethod(obj, callbackID, native_desc); //回调该方法,并且传递参数值
}
结果:
I was invoked by native method ############# I am Native