JNI开发java与c的基础交互

本文主要介绍JNI开发中java与c进行如下所示的交互,代码中注释很详细,很好理解

 

JniDemo.c

#include "com_example_barry_jnidemo_JniDemo.h"
#include <stdlib.h>
//c文件中打印log
#include <android/log.h>
#define LOG_TAG "System.out"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)

//
// Created by Barry on 2016/8/7.
//
JNIEXPORT jint JNICALL Java_com_example_barry_jnidemo_JniDemo_Add
        (JNIEnv * env, jobject obj, jint a, jint b)
{
    LOGD("%d+%d=%d", a, b, a+b);
    return a+b;
}
//  把jstr 转换成char*
char*   Jstring2CStr(JNIEnv*   env,   jstring   jstr)
{
    char*   rtn   =   NULL;
    jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");
    jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");
    jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B");
    jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");
    jsize   alen   =   (*env)->GetArrayLength(env,barr);
    jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
    if(alen   >   0)
    {
        rtn   =   (char*)malloc(alen+1);         //"\0"
        memcpy(rtn,ba,alen);
        rtn[alen]=0;
    }
    (*env)->ReleaseByteArrayElements(env,barr,ba,0);  //
    return rtn;
}
JNIEXPORT jstring JNICALL Java_com_example_barry_jnidemo_JniDemo_SayHelloC
        (JNIEnv *env, jobject obj, jstring str)
{
    //jstring转换成char*
    char* cstr = Jstring2CStr(env, str);
    //拼接字符串
    strcat(cstr, "hello");
    //char*转为jstring
    jstring newstr = (*env)->NewStringUTF(env, cstr);
    return newstr;
}

JNIEXPORT jintArray JNICALL Java_com_example_barry_jnidemo_JniDemo_AddTen
        (JNIEnv *env, jobject obj, jintArray intArray)
{
    //  需要获取的数组的长度
    int len=(*env)->GetArrayLength(env,intArray);
    //   遍历数组   void* -> jinit*
    //   jint*       (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
    int* array=(*env)->GetIntArrayElements(env,intArray,JNI_FALSE);
    int i=0;
    for(;i<len;i++){
        // 遍历的过程中让数组每个元素+10
        *(array+i)+=10;
    }
    return intArray;
}
//回调java方法原理是反射机制
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod1
(JNIEnv *env, jobject obj)
{
// Class<?> loadClass = MainActivity.class.getClassLoader().loadClass("com.itheima.ndkcallback.DataProvider");
//  1 反射类的字节码 jclass      (*FindClass)(JNIEnv*, const char*);
jclass clazz=(*env)->FindClass(env,"com/example/barry/jnidemo/JniDemo");
//       Method method = loadClass.getMethod("helloFromJava", (Class[]) null);
// 2 加载方法    jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
//   参数 env  参数2 类的字节码 参数3 方法名 参数4 方法的签名
jmethodID  methodID= (*env)->GetMethodID(env,clazz,"Method1","()V");
//       method.invoke(loadClass.newInstance(), (Object[]) null );
//  3 调用方法  void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env,obj,methodID);
}
//与方法一差不多,只是函数签名,传参不一样了
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod2
(JNIEnv *env, jobject obj)
{
// 步骤1 获取类的字节码
jclass clazz=(*env)->FindClass(env,"com/example/barry/jnidemo/JniDemo");
// 步骤2 获取方法的id
jmethodID  methodID= (*env)->GetMethodID(env,clazz,"Method2","(II)I");
//  步骤3
jint result=(*env)->CallIntMethod(env,obj,methodID,3,5);
}
//与方法一差不多,函数签名,传参不一样了,注意非基本类型传参Ljava/lang/String;
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod3
(JNIEnv *env, jobject obj)
{
jclass clazz=(*env)->FindClass(env,"com/example/barry/jnidemo/JniDemo");
jmethodID  methodID= (*env)->GetMethodID(env,clazz,"Method3","(Ljava/lang/String;)V");
(*env)->CallVoidMethod(env,obj,methodID,(*env)->NewStringUTF(env,"jni"));
}
//调用静态方法有专门(GetStaticMethodID)的方法
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod4
(JNIEnv *env, jobject obj)
{
jclass clazz=(*env)->FindClass(env,"com/example/barry/jnidemo/JniDemo");
jmethodID  methodID= (*env)->GetStaticMethodID(env,clazz,"Method4","()V");
(*env)->CallStaticVoidMethod(env,clazz,methodID);
}
//调用其他类的函数需要新创建那个类,googel不建议这么做,
//尽量让native方法和要回调的方法在同一个类中
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod5
(JNIEnv *env, jobject obj)
{
jclass clazz=(*env)->FindClass(env,"com/example/barry/jnidemo/MainActivity");
jmethodID  methodID= (*env)->GetMethodID(env,clazz,"Method5","()V");
//  由于obj 是代表的dataProvider  我们期望Mainactivity
// jobject     (*AllocObject)(JNIEnv*, jclass);  尽量让native方法和要回调的方法在同一个类中
jobject mainObj=(*env)->AllocObject(env,clazz);  //new Mainctivity()
(*env)->CallVoidMethod(env,mainObj,methodID);
}

MainActivity

package com.example.barry.jnidemo;

import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.util.Log;
import android.view.View;
import android.widget.TextView;

public class MainActivity extends AppCompatActivity {
    JniDemo jd = null;
    TextView tv = null;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        jd = new JniDemo();
        tv = (TextView)findViewById(R.id.tv);
    }
    public void add(View v)
    {
        int n = jd.Add(1,1);
        tv.setText("add:"+n);
    }
    public void str(View v)
    {
        String str = jd.SayHelloC("jni");
        tv.setText(str);
    }
    public void intarray(View v)
    {
        int[] ia = new int[]{1,2,3};
        jd.AddTen(ia);
        for (int i=0;i<ia.length;i++)
        {
            System.out.println(ia[i]+"");
        }
    }
    public void callmethod1(View v)
    {
        jd.CallMethod1();
    }
    public void callmethod2(View v)
    {
        jd.CallMethod2();
    }
    public void callmethod3(View v)
    {
        jd.CallMethod3();
    }
    public void callmethod4(View v)
    {
        jd.CallMethod4();
    }
    public void Method5()
    {
        System.out.println("Mainactivity method");
    }
    public void callmethod5(View v)
    {
        jd.CallMethod5();
    }
}

activity_main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:orientation="vertical"
    tools:context="com.example.barry.jnidemo.MainActivity">

    <TextView
        android:id="@+id/tv"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="Hello World!" />
    <Button
        android:id="@+id/btn_add"
        android:layout_marginTop="20dp"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="传递int:add"
        android:onClick="add"/>
    <Button
        android:id="@+id/btn_str"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="拼接str"
        android:onClick="str"/>
    <Button
        android:id="@+id/btn_intarray"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="int数组"
        android:onClick="intarray"/>
    <Button
        android:id="@+id/btn_callmethod1"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="调用空参数方法"
        android:onClick="callmethod1"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="调用int参数方法"
        android:onClick="callmethod2"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="调用string参数方法"
        android:onClick="callmethod3"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="调用静态方法"
        android:onClick="callmethod4"/>
    <Button
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:text="调用其他类中的方法"
        android:onClick="callmethod5"/>
</LinearLayout>

JniDemo

package com.example.barry.jnidemo;

/**
 * Created by Barry on 2016/8/7.
 */
public class JniDemo {
    static {
        System.loadLibrary("JniDemo");
    }
    public void Method1()
    {
        System.out.println("null param method");
    }
    public int Method2(int a,int b)
    {
        System.out.println("two int param method:"+ (a+b));
        return a+b;
    }
    public void Method3(String str)
    {
        str += "hello";
        System.out.println("string param method:"+str);
    }
    public static void Method4()
    {
        System.out.println("static method");
    }
    public native int Add(int a, int b);
    public native String SayHelloC(String str);
    public native int[] AddTen(int[] iNum);
    public native void CallMethod1();
    public native void CallMethod2();
    public native void CallMethod3();
    public native void CallMethod4();
    public native void CallMethod5();
}

com_example_barry_jnidemo_JniDemo.h

/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_barry_jnidemo_JniDemo */

#ifndef _Included_com_example_barry_jnidemo_JniDemo
#define _Included_com_example_barry_jnidemo_JniDemo
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_barry_jnidemo_JniDemo
 * Method:    Add
 * Signature: (II)I
 */
JNIEXPORT jint JNICALL Java_com_example_barry_jnidemo_JniDemo_Add
  (JNIEnv *, jobject, jint, jint);

/*
 * Class:     com_example_barry_jnidemo_JniDemo
 * Method:    SayHelloC
 * Signature: (Ljava/lang/String;)Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_barry_jnidemo_JniDemo_SayHelloC
  (JNIEnv *, jobject, jstring);

/*
 * Class:     com_example_barry_jnidemo_JniDemo
 * Method:    AddTen
 * Signature: ([I)[I
 */
JNIEXPORT jintArray JNICALL Java_com_example_barry_jnidemo_JniDemo_AddTen
  (JNIEnv *, jobject, jintArray);

/*
 * Class:     com_example_barry_jnidemo_JniDemo
 * Method:    CallMethod1
 * Signature: ()V
 */
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod1
  (JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod2
(JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod3
(JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod4
(JNIEnv *, jobject);
JNIEXPORT void JNICALL Java_com_example_barry_jnidemo_JniDemo_CallMethod5
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Barry__

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值