1.创建xxx.jni包并在该包下实现一些Java的方法,和要调用的本地方法

2.实现MainActivity中的按钮点击事件—即点击按钮调用本地的方法

3.在C文件中的方法中回调Java的方法

  3.1:通过env获取字节码对象—>jclass   (*FindClass)(JNIEnv*, const char*)

    第二个参数为要回调Java方法所在类的全路径如:jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/jni/JNI");

  3.2:通过字节码对象获取方法ID—>jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);

    第二个参数是由3.1获取的字节码对象,第三个对象是要回调的Java方法名,第四个参数该Java方法签名,因为Java中有重载,需要此参数确定具体是哪个方法如:jmethodID methodId = (*env)->GetMethodID(env, claz, "helloFromJava", "()V")

    注:对应方法签名,需要到工程目录下的bin/classes目录下执行:javap -s com.rocky.jniccallbackdemo.jni.JNI(该方法所在类的全类名)

  3.3:通过字节码对象创建Java对象—>jobject (*AllocObject)(JNIEnv*, jclass);
    如:jobject obj = (*env)->AllocObject(env, claz);

注:如果本地方法和要回调的Java方法在同一个类中,则第二参数就是本地方法传过来的第二个参数,即第三步可以可以省略。

  3.4:通过Java对象回调Java方法

  调用Java的无返回值方法:void  (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...),如: (*env)->CallVoidMethod(env, clazz, methodId);

DEMO:

JNI.java

public class JNI
{
static {
System.loadLibrary("callback");
}
private Context mContext = null;
public JNI(Context context)
{
this.mContext = context;
}
public void helloFromJava()
{
System.out.println("Hello From Java");
}
public void printString(String str)
{
System.out.println(str);
}
public void showToast(String str)
{
Toast.makeText(mContext, str, Toast.LENGTH_SHORT).show();
}
public native void callbackVoidMethod();
public native void callbackStringMethod();
public native void callbackIntMethod();
public native void callbackShowToastMethod();
}

MainActivity.java

public class MainActivity extends Activity implements OnClickListener
{
Context mContext = null;
Button bt_callback_void = null;
Button bt_callback_string = null;
Button bt_callback_int = null;
Button bt_callback_toast = null;
JNI jni = null;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mContext = this;
jni = new JNI(mContext);
bt_callback_void = (Button) findViewById(R.id.bt_callback_void);
bt_callback_void.setOnClickListener(this);
bt_callback_int = (Button) findViewById(R.id.bt_callback_int);
bt_callback_int.setOnClickListener(this);
bt_callback_string = (Button) findViewById(R.id.bt_callback_string);
bt_callback_string.setOnClickListener(this);
bt_callback_toast = (Button) findViewById(R.id.bt_callback_toast);
bt_callback_toast.setOnClickListener(this);
}
public int add(int x, int y)
{
return x + y;
}
@Override
public void onClick(View v)
{
switch (v.getId())
{
case R.id.bt_callback_void:
jni.callbackVoidMethod();
break;
case R.id.bt_callback_int:
jni.callbackIntMethod();
break;
case R.id.bt_callback_string:
jni.callbackStringMethod();
break;
case R.id.bt_callback_toast:
jni.callbackShowToastMethod();
break; default:
break;
}
}
}

callback.c

#include <jni.h>
#include <android/log.h>
#define LOG_TAG "rocky"
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR, LOG_TAG, __VA_ARGS__)
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN, LOG_TAG, __VA_ARGS__)
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
#define LOGV(...) __android_log_print(ANDROID_LOG_VERBOSE, LOG_TAG, __VA_ARGS__) JNIEXPORT void JNICALL Java_com_rocky_jniccallbackdemo_jni_JNI_callbackVoidMethod
(JNIEnv *env, jobject clazz)
{
//1.获取字节码对象 jclass (*FindClass)(JNIEnv*, const char*);
jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/jni/JNI");
//2.通过字节码对象获取方法ID jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
jmethodID methodId = (*env)->GetMethodID(env, claz, "helloFromJava", "()V");
//3.通过字节码对象创建Java对象(此处因为本地方法和回调方法在同一个类中,可以省略)
//4.通过Java对象回调Java方法 void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env, clazz, methodId);
}
/*
* Class: com_rocky_jniccallbackdemo_jni_JNI
* Method: callbackIntMethod
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_rocky_jniccallbackdemo_jni_JNI_callbackIntMethod
(JNIEnv *env, jobject clazz)
{
jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/MainActivity");
jmethodID methodId = (*env)->GetMethodID(env, claz, "add", "(II)I");
//3.通过字节码对象创建Java对象(此处为MainActivity对象) jobject (*AllocObject)(JNIEnv*, jclass);
// jobject obj = (*env)->AllocObject(env, claz);
//4.通过Java对象回调Java方法 void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
jobject obj = (*env)->AllocObject(env, claz);
jint res = (*env)->CallIntMethod(env, obj, methodId, , );
LOGI("res = %d\n", res);
}
JNIEXPORT void JNICALL Java_com_rocky_jniccallbackdemo_jni_JNI_callbackStringMethod
(JNIEnv *env, jobject clazz)
{
jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/jni/JNI");
jmethodID methodId = (*env)->GetMethodID(env, claz, "printString", "(Ljava/lang/String;)V");
jstring result = (*env)->NewStringUTF(env, "cccccccccccccc");
(*env)->CallVoidMethod(env, clazz, methodId, result);
}
JNIEXPORT void JNICALL Java_com_rocky_jniccallbackdemo_jni_JNI_callbackShowToastMethod
(JNIEnv *env, jobject clazz)
{
jclass claz = (*env)->FindClass(env, "com/rocky/jniccallbackdemo/jni/JNI");
jmethodID methodId = (*env)->GetMethodID(env, claz, "showToast", "(Ljava/lang/String;)V");
jstring result = (*env)->NewStringUTF(env, "rocky--------rocky");
(*env)->CallVoidMethod(env, clazz, methodId, result);
}

Android.mk

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE    := callback
LOCAL_SRC_FILES := callback.c LOCAL_LDLIBS += -llog include $(BUILD_SHARED_LIBRARY)

JNI系列——C文件中的方法调用Java中方法的更多相关文章

  1. 不用static,巧用对象.方法调用java中的函数

    先生成一个对象,用"对象.方法()"的方式调用. java中的main方法是静态的,用于程序的入口,在静态方法中无法调用非静态方法,只能调用静态方法.想调用静态方法的话就要先生成该 ...

  2. C通过JNI反向调用JAVA程序方法

    JNI反向调用JAVA程序 引述:上文讲过java线程---OS线程的关系,然后C怎样反向调用JAVA程序方法是我们这篇讲的重点 1.ThreadTest中添加run()方法 2.编译ThreadTe ...

  3. 在ASP.Net环境中,当用户点击报表中的超链接时如何调用Java Script方法?

    问题描述:在ASP.Net环境中,当用户点击报表中的超链接时如何调用Java Script方法? 问题解答: 你可以在TextObject.Hyperlink对象中编写js代码(javascript: ...

  4. 第7.22节 Python中使用super调用父类的方法

    第7.22节 Python中使用super调用父类的方法 前面章节很多地方都引入了super方法,这个方法就是访问超类这个类对象的.由于super方法的特殊性,本节单独谈一谈super方法. 一.su ...

  5. vue中methods一个方法调用另外一个方法

    转自http://blog.csdn.net/zhangjing1019/article/details/77942923 vue在同一个组件内: methods中的一个方法调用methods中的另外 ...

  6. 为什么static方法中不可以调用非static方法

    Java是面向对象的语言,所有的变量,方法都是针对对象而言的.一般来说,要调用一个方法,你需要new 这个方法的对象. 什么时候用static? 如果你想要: 对于一个类的所有对象共享一个变量或者是方 ...

  7. vue methods 方法中 方法 调用 另一个方法。

    vue在同一个组件内: methods中的一个方法调用methods中的另外一个方法. 可以在调用的时候 this.$options.methods.test(); this.$options.met ...

  8. PySpark 的背后原理--在Driver端,通过Py4j实现在Python中调用Java的方法.pyspark.executor 端一个Executor上同时运行多少个Task,就会有多少个对应的pyspark.worker进程。

    PySpark 的背后原理 Spark主要是由Scala语言开发,为了方便和其他系统集成而不引入scala相关依赖,部分实现使用Java语言开发,例如External Shuffle Service等 ...

  9. JNI NDK (AndroidStudio+CMake )实现C C++调用Java代码流程

    JNI/NDK Java调用C/C++前言  通过第三篇文章讲解在实际的开发过程中Java层调用C/C++层的处理流程.其实我们在很大的业务里也需要C/C+ +层去调用Java层,这两层之间的相互调用 ...

随机推荐

  1. shell编程入门

    背景知识 Shell 是用户与内核进行交互操作的一种接口,是 Linux 最重要的软件之一.目前最流行的 Shell 称为 bash Shell,bash Shell 脚本编程以其简洁.高效而著称,多 ...

  2. Linux压缩指令

    1.windows系统和Linux系统的压缩文件只有zip格式的是通用的 2.windows系统可以解压几乎所有的Linux压缩格式 3.Linux压缩指令 gzip 指令 格式: gzip 压缩的文 ...

  3. CTO和技术副总裁应该如何分工?谁才是技术领导者?

    谁是初创公司的技术领导者,是CTO还是技术副总裁?任何在创业公司工作的人都知道,我们不应该去问这个问题.因为这两个是非常不同的角色,角色本身会随着创业公司的发展而变化,两者对于业务规模都很重要. 简单 ...

  4. 《100种过度医疗大公开》:转译自日文版,日文版依据的是美国的“Choosing Wisely”项目。三星推荐

    本书转译自日文,日文版则是在美国的“Choosing Wisely”项目中选择了100个相对常见的过度医疗项目做解说.Choosing Wisely项目,是由美国多个专业医学组织发起的列出过度医疗项目 ...

  5. 【CSS】使用CSS选择器

    CCS选择器的作用是找出某类元素.以便使我们使用style元素或者外部样式表对这类元素设置样式. 1.使用CSS基本选择器 有些选择器使用起来非常简单,我们把这部分选择器称为基本选择器(basic s ...

  6. 【温故而知新-Javascript】使用地理定位

    地理定位(Geolocation)API让我们可以获取用户当前地理位置的信息(或者至少是正在运行浏览器的系统的位置).它不是HTML5规范的一部分,但经常被归组到与HTML5相关的新功能中. 1. 使 ...

  7. 《Python核心编程》部分错误纠正(勘误表)(持续更新)

    Chapter 3: 例3-1 makeTextFile.py #!/usr/bin/env python 'makeTextFile.py' import os ls = os.linesep #g ...

  8. Vijos1451圆环取数[环形DP|区间DP]

    背景 小K攒足了路费来到了教主所在的宫殿门前,但是当小K要进去的时候,却发现了要与教主守护者进行一个特殊的游戏,只有取到了最大值才能进去Orz教主…… 描述 守护者拿出被划分为n个格子的一个圆环,每个 ...

  9. .NET(C#) File类的常用方法

    MSDN的File类 File类在MSDN:https://msdn.microsoft.com/zh-cn/library/system.io.file_methods(v=vs.110).aspx ...

  10. Windows 批处理(bat)语法大全

    本文是学习bat整理的笔记,由于内容较多,建议结合右侧文章大纲查看. %~dp0[获取当前路径] %~dp0 “d”为Drive的缩写,即为驱动器,磁盘.“p”为Path缩写,即为路径,目录 cd % ...