本篇将介绍在JNI编程中C调用Java实现。

源码下载地址:http://download.csdn.net/detail/xyz_lmn/4868265

关键代码:

java:

  1. public class CCallJava {
  2. public static String getTime() {
  3. Log.d("CCallJava",  "Call From C Java Static Method" +String.valueOf(System.currentTimeMillis()));
  4. return String.valueOf(System.currentTimeMillis());
  5. }
  6. public void sayHello(String msg) {
  7. Log.d("CCallJava",  "Call From C Java void Method" +String.valueOf(System.currentTimeMillis()));
  8. }
  9. }
C:
  1. #include "TestCCallJava.h"
  2. #include <android/log.h>
  3. extern JNIEnv* jniEnv;
  4. jclass TestCCallJava;
  5. jobject mTestCCallJava;
  6. jmethodID getTime;
  7. jmethodID sayHello;
  8. int GetTestCCallJavaInstance(jclass obj_class);
  9. /**
  10. * 初始化 类、对象、方法
  11. */
  12. int InitTestCCallJava() {
  13. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitTestCCallJava Begin  1" );
  14. if(jniEnv == NULL) {
  15. return 0;
  16. }
  17. if(TestCCallJava == NULL) {
  18. TestCCallJava = (*jniEnv)->FindClass(jniEnv,"com/trunkbow/ccalljava/CCallJava");
  19. if(TestCCallJava == NULL){
  20. return -1;
  21. }
  22. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitTestCCallJava Begin  2 ok" );
  23. }
  24. if (mTestCCallJava == NULL) {
  25. if (GetTestCCallJavaInstance(TestCCallJava) != 1) {
  26. (*jniEnv)->DeleteLocalRef(jniEnv, TestCCallJava);
  27. return -1;
  28. }
  29. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitTestCCallJava Begin  3 ok" );
  30. }
  31. if (getTime == NULL) {
  32. getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestCCallJava, "getTime","()Ljava/lang/String;");
  33. if (getTime == NULL) {
  34. (*jniEnv)->DeleteLocalRef(jniEnv, TestCCallJava);
  35. (*jniEnv)->DeleteLocalRef(jniEnv, mTestCCallJava);
  36. return -2;
  37. }
  38. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitTestCCallJava Begin  4 ok" );
  39. }
  40. if (sayHello == NULL) {
  41. sayHello = (*jniEnv)->GetMethodID(jniEnv, TestCCallJava, "sayHello","(Ljava/lang/String;)V");
  42. if (sayHello == NULL) {
  43. (*jniEnv)->DeleteLocalRef(jniEnv, TestCCallJava);
  44. (*jniEnv)->DeleteLocalRef(jniEnv, mTestCCallJava);
  45. (*jniEnv)->DeleteLocalRef(jniEnv, getTime);
  46. return -3;
  47. }
  48. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitTestCCallJava Begin  5 ok" );
  49. }
  50. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "InitTestCCallJava Begin  6" );
  51. return 1;
  52. }
  53. int GetTestCCallJavaInstance(jclass obj_class) {
  54. if(obj_class == NULL) {
  55. return 0;
  56. }
  57. jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, obj_class,
  58. "<init>", "()V");
  59. if (construction_id == 0) {
  60. return -1;
  61. }
  62. mTestCCallJava = (*jniEnv)->NewObject(jniEnv, obj_class,
  63. construction_id);
  64. if (mTestCCallJava == NULL) {
  65. return -2;
  66. }
  67. return 1;
  68. }
  69. /**
  70. * 获取时间 ---- 调用 Java 方法
  71. */
  72. void GetTime() {
  73. if(TestCCallJava == NULL || getTime == NULL) {
  74. int result = InitTestCCallJava();
  75. if (result != 1) {
  76. return;
  77. }
  78. }
  79. jstring jstr = NULL;
  80. char* cstr = NULL;
  81. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "GetTime Begin" );
  82. jstr = (*jniEnv)->CallStaticObjectMethod(jniEnv, TestCCallJava, getTime);
  83. cstr = (char*) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
  84. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "Success Get Time from Java , Value = %s",cstr );
  85. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "GetTime End" );
  86. (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);
  87. (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
  88. }
  89. /**
  90. * SayHello ---- 调用 Java 方法
  91. */
  92. void SayHello() {
  93. if(TestCCallJava == NULL || mTestCCallJava == NULL || sayHello == NULL) {
  94. int result = InitTestCCallJava() ;
  95. if(result != 1) {
  96. return;
  97. }
  98. }
  99. jstring jstrMSG = NULL;
  100. jstrMSG =(*jniEnv)->NewStringUTF(jniEnv, "Hi,I'm From C");
  101. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "SayHello Begin" );
  102. (*jniEnv)->CallVoidMethod(jniEnv, mTestCCallJava, sayHello,jstrMSG);
  103. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "SayHello End" );
  104. (*jniEnv)->DeleteLocalRef(jniEnv, jstrMSG);
  105. }

关键代码说明:

 

C中定义映射的类、方法、对象

  1. jclass TestCCallJava;
  2. jobject mTestCCallJava;
  3. jmethodID getTime;
  4. jmethodID sayHello;

InitTestCCallJava()方法初始化类、方法、对象

初始化类:
  1. TestCCallJava = (*jniEnv)->FindClass(jniEnv,"com/trunkbow/ccalljava/CCallJava");

初始化对象:

  1. mTestCCallJava = (*jniEnv)->NewObject(jniEnv, obj_class,construction_id);
 

初始化方法:

静态方法:
  1. getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestCCallJava, "getTime","()Ljava/lang/String;");

非静态方法:

  1. sayHello = (*jniEnv)->GetMethodID(jniEnv, TestCCallJava, "sayHello","(Ljava/lang/String;)V");
 

C 中调用 Java的 方法

调用静态方法:

  1. jstring jstr = NULL;
  2. char* cstr = NULL;
  3. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "GetTime Begin" );
  4. jstr = (*jniEnv)->CallStaticObjectMethod(jniEnv, TestCCallJava, getTime);
  5. cstr = (char*) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
  6. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "Success Get Time from Java , Value = %s",cstr );
  7. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "GetTime End" );

调用非静态方法

 
  1. jstring jstrMSG = NULL;
  2. jstrMSG =(*jniEnv)->NewStringUTF(jniEnv, "Hi,I'm From C");
  3. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "SayHello Begin" );
  4. (*jniEnv)->CallVoidMethod(jniEnv, mTestCCallJava, sayHello,jstrMSG);
  5. __android_log_print(ANDROID_LOG_INFO, "JNIMsg", "SayHello End" );

注意 GetXXXMethodID  和 CallXXXMethod 。

第一个XXX 表示的是映射方法的类型,如: 静态 跟非静态

第二个 XXX 表示 调用方法的返回值 ,如:Void,Object,等等。(调用静态方法的时候Call后面要加Static)

详细 映射方法 和 调用方法 请参考 JNI 文档 ,这个很重要 !

 
工程的其他代码可在http://download.csdn.net/detail/xyz_lmn/4868265下载
 
参考:
 
 

/**
* @author 张兴业
*  iOS入门群:83702688
*  android开发进阶群:241395671
*  我的新浪微博:@张兴业TBOW
*/

Android JNI入门第六篇——C调用Java的更多相关文章

  1. Android JNI入门第五篇——基本数据类型使用

    前面讲到了java和native数据类型,这里就开始做一下使用: 第一步:新建工程 第二部:书写 java方法: public class NativeMethod { static { System ...

  2. Android JNI入门第三篇——jni头文件分析

    一. 首先写了java文件: public class HeaderFile { private native void  doVoid(); native int doShort(); native ...

  3. Android JNI入门第四篇——Android.mk文件分析

    ndroid.mk文件是在使用NDK编译C代码时必须的文件,Android.mk文件中描述了哪些C文件将被编译且指明了如何编译.掌握Android.mk文件的编写主要是掌握其里头将要使用的一些关键字, ...

  4. Android jni c/c++线程通过CallVoidMethod调用java函数出现奔溃问题

    最近在移植网络摄像机里的p2p库到android平台,需要用到jni,最近在c线程了调用java函数的时候 出现一个问题,假如在同一个线程调用java函数是没问题的,但在一个c线程了调用java函数就 ...

  5. Android JNI开发之C/C++层调用JAVA

    一.从C/C++层调用JAVA层代码(无参数调用) //在c代码里面调用java代码里面的方法 // java 反射 // 1 . 找到java代码的 class文件 // jclass (*Find ...

  6. Android入门第六篇之ListView (一)

    本文来自http://blog.csdn.net/hellogv/ ListView是一个经经常使用到的控件,ListView里面的每一个子项Item能够使一个字符串,也能够是一个组合控件.先说说Li ...

  7. # hadoop入门第六篇:Hive实例

    前言   前面已经讲了如何部署在hadoop集群上部署hive,现在我们就做一个很小的实例去熟悉HIVE QL.使用的数据是视频播放数据包括视频编码,播放设备编码,用户账号编码等,我们在这个数据基础上 ...

  8. Visualforce入门第六篇_2017.3.1

    Visualforce实现过滤.数据列表显示.分页功能 可以参考salesforce官网开发文档:https://trailhead.salesforce.com/modules/visualforc ...

  9. JavaMail入门第五篇 解析邮件

    上一篇JavaMail入门第四篇 接收邮件中,控制台打印出的内容,我们无法阅读,其实,让我们自己来解析一封复杂的邮件是很不容易的,邮件里面格式.规范复杂得很.不过,我们所用的浏览器内置了解析各种数据类 ...

随机推荐

  1. requirejs 一个拆分js项目的类库

    http://www.requirejs.cn/ http://requirejs.org/docs/start.html

  2. Linux添加用户user到用户组group

    添加用户:useradd niot 添加到组:usermod -a -G root niot 改密码:passwd niot 切换:su - niot 查看用户组:groups 将一个用户添加到用户组 ...

  3. 把perl脚本编译成exe

    来源:http://www.veryhuo.com/a/view/38338.html 今天想把 perl 脚本编译成 exe 以便脱离 perl 解释器独立运行.都可以生成PERL的PE文件,在PE ...

  4. Docker 简介及安装

    Docker简介: 什么是Docker?将应用程序自动部署到容器 go语言开源引擎  Github地址:https://github.com/docker/docker 2013年初 dotCloud ...

  5. Django 分页功能

    Django 分页功能比较强大,这边是结合官网的内容写的可以参考 https://docs.djangoproject.com/en/1.9/topics/pagination/ 分页命令行练习案列 ...

  6. Oracle 锁

    select  for update对某行加锁之后: select语句可以执行: select  for update 这行不可以: 会一直等待锁释放 select for update wait 3 ...

  7. Object.setPrototypeOf 方法的使用

    将一个指定的对象的原型设置为另一个对象或者null(既对象的[[Prototype]]内部属性). 语法 Object.setPrototypeOf(obj, prototype) 参数 obj 将被 ...

  8. 【欧拉函数】 poj 2478

    递推法求欧拉函数: #include <iostream> #include <cstdio> #include <cstring> using namespace ...

  9. servlet & javabean

    1.servelet 什么是Servlet?① Servlet就是JAVA 类② Servlet是一个继承HttpServlet类的类③这个在服务器端运行,用以处理客户端的请求 Servlet相关包的 ...

  10. XListview的下拉刷新、上拉加载、用Pull解析XML

    做之前需要导入XListview的文件,此是用第三方的xListview实现的,东西没写全.此是在Fragment中实现的 //--------------XListView的布局---------- ...