Android JNI入门第六篇——C调用Java

本篇将介绍在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
*/
上一篇:JavaScript学习笔记(5)——JavaScript语法之数据类型


下一篇:写给大忙人的CentOS 7下最新版(6.2.4)ELK+Filebeat+Log4j日志集成环境搭建完整指南