Android中Jni的基本使用详解

来源:互联网 发布:白额高脚蛛淘宝 编辑:程序博客网 时间:2024/05/16 18:35

今天就介绍下jni编程的基本使用,如果你还不知道NDK的环境怎么搭建就看我的上一篇博客,有详细的介绍怎么搭建环境,生成So库的详细过程,上一篇博客的地址点击打开链接,下面介绍jni的基本使用:

在调用So库之前需要先加载So库

static {    System.loadLibrary("JniTests");}
静态代码块,先执行。

MainActivity.java

public class MainActivity extends AppCompatActivity implements View.OnClickListener {    private TextView tv_call,call,call2;    static {        System.loadLibrary("JniTests");    }    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        tv_call=(TextView)findViewById(R.id.tv_call);        call=(TextView)findViewById(R.id.call);        call2=(TextView)findViewById(R.id.call2);        tv_call.setOnClickListener(this);        call.setOnClickListener(this);        call2.setOnClickListener(this);    }    public native String javaCallC();    public native void javaC();    public native int callAdd();    public void cCallJava(String s){        Toast.makeText(MainActivity.this,s,Toast.LENGTH_SHORT).show();    }    public int addInt(int x, int y){      Toast.makeText(MainActivity.this,"C调用了java的方法,x:"+x+"y:"+y),Toast.LENGTH_SHORT).show();       return x+y;    }    @Override    public void onClick(View v) {        switch (v.getId()){            case R.id.tv_call:                String s=javaCallC();                Toast.makeText(MainActivity.this,s,Toast.LENGTH_SHORT).show();                break;            case R.id.call:                System.out.println("Java调用了C,C反调了java的方法");                javaC();                break;            case R.id.call2:                int add=callAdd();                System.out.println("Java调用了C,C反调了java的方法,求和为:"+add);                break;        }    }}

JAVA调用C语言的是native方法

先说第一个方法:public native String javaCallC();

在C语言中对应的方法名就是Java_包名_类名_方法名,这个如果怕写错的话可以生成.h文件,从.h文件中直接copy出来C中对应的方法如下:

JNIEXPORT jstring JNICALL Java_com_wdkj_test_jniproject_MainActivity_javaCallC(JNIEnv *env, jobject object){  return (*env)->NewStringUTF(env, "JAVAcallC");  }
javaCallC()返回的是String类型,在C中对应的是jstring,在点击第一个textview的时候调用了这个javaCallC()的方法,调用了C对应方法
Java_com_wdkj_test_jniproject_MainActivity_javaCallC
,得到返回的字符串JAVAcallC,在手机端会弹出一个Toast提示“JAVAcallC”,效果如下:


第二个java调C的方法:public native void javaC(),也包含了C调Java的方法cCallJava(String s);

来C中对应的方法如下:

JNIEXPORT void JNICALL Java_com_wdkj_test_jniproject_MainActivity_javaC(JNIEnv *env, jobject jobject){         jclass clazz=(*env)->FindClass(env,"com/wdkj/test/jniproject/MainActivity");         jmethodID methodId=(*env)->GetMethodID(env,clazz,"cCallJava","(Ljava/lang/String;)V");         // jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);         jstring str=(*env)->NewStringUTF(env,"hello 我调用了java的方法");         (*env)->CallVoidMethod(env,jobject,methodId,str);  }
C中对应的方法同样调用了java中的cCallJava方法,使用到了反射获取到MainActivity,根据方法名和参数得到方法ID,str是传参的变量值,cCallJava是void方法所以使用CallVoidMethodCallVoidMethod传入了方法ID和变量值,调用了MainActivitycCallJava方法。我点击第二个textview会调用javaC方法,C会执行Java_com_wdkj_test_jniproject_MainActivity_javaC,而Java_com_wdkj_test_jniproject_MainActivity_javaC方法中又使用反射调用了cCallJava方法,在手机端会弹出一个Toast提示“hello 我调用了java的方法”,效果如下:


第三个java调C的方法:public native int callAdd(),也包含了C调Java的方法addInt(int x,int  y);

来C中对应的方法如下:

JNIEXPORT jint JNICALL Java_com_wdkj_test_jniproject_MainActivity_callAdd  (JNIEnv *env, jobject jobject) {         jclass clazz=(*env)->FindClass(env,"com/wdkj/test/jniproject/MainActivity");         //这里的方法签名中有几个I表示有几个参数         jmethodID methodId=(*env)->GetMethodID(env,clazz,"addInt","(II)I");         // jint   返回值是int(*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);         return (*env)->CallIntMethod(env,jobject,methodId,3,5);}
java调C返回值是int所以C的返回值是jint,最后调用的是CallIntMethod,我点击第三个textview会调用callAdd方法,C会执行Java_com_wdkj_test_jniproject_MainActivity_callAdd,而Java_com_wdkj_test_jniproject_MainActivity_callAdd方法中又使用反射调用了addInt方法,在手机端会弹出一个Toast提示C调用了java的方法,x:”+y:,展示C调addInt传的参数,java调C最后返回的一个int值,在控制台输出,效果如下:



希望对大家能有帮助,源码地址:点击打开链接,下载必须选C币我也没办法,有需要源码的可以留言,我直接发你们邮箱。








原创粉丝点击