NDK基础(一)——方法调用

2020-06-29  本文已影响0人  王志强_9380

方法定义

public native void unstaticFunction();
public static native void staticFunction();
extern "C"
JNIEXPORT void JNICALL
Java_com_example_ffmpegapplication_NativeStudy_unstaticFunction(JNIEnv *env, jobject instance) {

    // TODO

}
extern "C"
JNIEXPORT void JNICALL
Java_com_example_ffmpegapplication_NativeStudy_staticFunction(JNIEnv *env, jclass type) {

    // TODO

}

方法调用

env->GetObjectClass(nativeStudyTest);
env->GetObjectClass(env, nativeStudyTest);

JNI操作Java类

java代码

package com.example.ffmpegapplication;

import android.os.Handler;
import android.util.Log;

public class NativeStudyTest {

    private static NativeStudyTest mNativeStudyTest;
    private static Handler mHandler;
    public static int mIntfield = -1;
    public boolean mBooleanfield = false;

    private NativeStudyTest(){
        Log.e("","NativeStudyTest Construct");
    }

    private NativeStudyTest(Handler h, int intfield){
        Log.e("","NativeStudyTest Construct with field:"+intfield);
        mHandler = h;
        mIntfield = intfield;
    }

    private void playNativeStudyTest1() {
        Log.e("","NativeStudyTest playNativeStudyTest1");
    }

    private int playNativeStudyTest2() {
        Log.e("","NativeStudyTest playNativeStudyTest2");
        return 0;
    }

    private NativeStudyTest playNativeStudyTest3(Handler h, int intfield) {
        Log.e("","NativeStudyTest playNativeStudyTest3");
        if(mNativeStudyTest == null)
            mNativeStudyTest = new NativeStudyTest(h, intfield);
        return mNativeStudyTest;
    }

    public static void playNativeStudyTestStatic() {
        Log.e("","NativeStudyTest playNativeStudyTestStatic");
    }

    public static NativeStudyTest getInstance(Handler h, int intfield) {
        if(mNativeStudyTest == null)
            mNativeStudyTest = new NativeStudyTest(h, intfield);
        return mNativeStudyTest;
    }
}
创建一个对象
extern "C"
JNIEXPORT jobject JNICALL
Java_com_example_ffmpegapplication_NativeStudy_newJaveClass(JNIEnv *env, jclass type) {

    // TODO 创建一个对象
    jclass aClass = env->FindClass("com/example/ffmpegapplication/NativeStudyTest");
    jmethodID pConstructMethodID = env->GetMethodID(aClass, "<init>", "()V");
    jobject pJobject = env->NewObject(aClass, pConstructMethodID);

    return pJobject;
}

调用:

public static native NativeStudyTest newJaveClass();

NativeStudyTest mNativeStudyTest = newJaveClass();
Log.e("","NativeStudyTest newJaveClass mBooleanfield:"+mNativeStudyTest.mBooleanfield + "  mIntfield:" + mNativeStudyTest.mIntfield);    

打印:

01-19 12:44:07.024: E/www(28743): NativeStudyTest Construct
01-19 12:36:16.355: E/www(28743): NativeStudyTest newJaveClass mBooleanfield:false  mIntfield:-1

可以看到,创建了一个类的对象,并且调用了构造方法
注意这句GetMethodID(aClass, "<init>", "()V");第二个参数本应该是填方法名,这里填的却是<init>,这是因为java的构造函数是有名字,而且不是类名,构造函数的方法名字是<init>

修改属性
extern "C"
JNIEXPORT void JNICALL
Java_com_example_ffmpegapplication_NativeStudy_setJavaFeild(JNIEnv *env, jclass type,
                                                            jobject nativeStudyTest) {
    // TODO 改变参数
    jclass pJclass = env->GetObjectClass(nativeStudyTest);

    jfieldID pID_Booleanfield = env->GetFieldID(pJclass, "mBooleanfield", "Z");
    env->SetBooleanField(nativeStudyTest, pID_Booleanfield, true);

    jfieldID pID_Intfield = env->GetStaticFieldID(pJclass, "mIntfield", "I");
    jint intField = env->GetStaticIntField(pJclass, pID_Intfield);
    env->SetStaticIntField(pJclass, pID_Intfield, intField + 100);

}

调用

public static native void setJavaFeild(NativeStudyTest nativeStudyTest);

setJavaFeild(mNativeStudyTest);
Log.e("","NativeStudyTest setJavaFeild mBooleanfield:"+mNativeStudyTest.mBooleanfield + "  mIntfield:" + mNativeStudyTest.mIntfield);

打印:

01-19 12:36:16.355: E/www(28743): NativeStudyTest setJavaFeild mBooleanfield:true  mIntfield:99

注意,获取属性的id以及设置属性值的时候,静态属性和非静态属性的方法是不一样的,如果搞错了,运行的时候会异常

调用方法
extern "C"
JNIEXPORT jobject JNICALL
Java_com_example_ffmpegapplication_NativeStudy_callJavaMethod(JNIEnv *env, jclass type, jobject h,
                                                              jint intfield) {
    // TODO 调用方法

    jclass aClass = env->FindClass("com/example/ffmpegapplication/NativeStudyTest");
    jobject dpobj = env->AllocObject(aClass);

    jmethodID pJmethodID1 = env->GetMethodID(aClass, "playNativeStudyTest1", "()V");
    env->CallVoidMethod(dpobj, pJmethodID1);

    jmethodID pJmethodID2 = env->GetMethodID(aClass, "playNativeStudyTest2", "()I");
    env->CallIntMethod(dpobj, pJmethodID2);

    //use of deleted weak global reference
    jmethodID pJmethodID3 = env->GetMethodID(aClass, "playNativeStudyTest3",
                                             "(Landroid/os/Handler;I)Lcom/example/ffmpegapplication/NativeStudyTest;");
    env->CallObjectMethod(dpobj, pJmethodID3, h, intfield);

    jmethodID pJmethodID4 = env->GetStaticMethodID(aClass, "playNativeStudyTestStatic", "()V");
    env->CallStaticVoidMethod(aClass, pJmethodID4);

    return dpobj;

}

调用

public static native NativeStudyTest callJavaMethod(Handler h, int intfield);

NativeStudyTest mNativeStudyTest2 = callJavaMethod(null, 10086);
Log.e("","NativeStudyTest callJavaMethod mBooleanfield:"+mNativeStudyTest.mBooleanfield + "  mIntfield:" + mNativeStudyTest.mIntfield);

打印:

01-19 12:36:16.355: E/www(28743): NativeStudyTest playNativeStudyTest1
01-19 12:36:16.355: E/www(28743): NativeStudyTest playNativeStudyTest2
01-19 12:36:16.355: E/www(28743): NativeStudyTest playNativeStudyTest3
01-19 12:36:16.355: E/www(28743): NativeStudyTest Construct with field:10086
01-19 12:36:16.355: E/www(28743): NativeStudyTest playNativeStudyTestStatic
01-19 12:36:16.355: E/www(28743): NativeStudyTest callJavaMethod mBooleanfield:true  mIntfield:10086
参数相关

env->GetMethodID(aClass, "playNativeStudyTest3",
"(Landroid/os/Handler;I)Lcom/example/ffmpegapplication/NativeStudyTest;");

private NativeStudyTest playNativeStudyTest3(Handler h, int intfield);

我们看到,要找到一个方法,最后一个参数需要传入一个值来避免重载方法,这个值叫做方法的签名。
格式是:(参数1类型参数2类型参数3类型。。。)返回值类型
如果是Object类型的参数,那么就需要填 (L参数类的路径;),注意最后要加分号。
如果是基本类型,就是首字母的大写,比如byte就是B,int就是I
特殊的:boolean是Z,type[]是[Type,

上一篇 下一篇

猜你喜欢

热点阅读