native学习

该博客主要介绍了Native层与Java层的交互操作,包括在Native层返回字符串、返回int型二维数组,以及在Native层操作Java层的类,如读取/设置类属性和回调Java方法,并给出了相关代码和运行结果。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

一、在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

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值