成功实现C/C++调用Java (Android NDK 开发)--参考1

成功实现C/C++调用Java (Android NDK 开发)  

2011-05-30 00:50:09|  分类: iPad iMac 开发|字号 订阅

用C/C++调用Java

 

在 java 里面写一个弹出信息对话框messagebox  是静态函数 , c++里面去调用;调用静态函数(其实就是全局函数)比成员函数方便多了。首先不需要java对象jobject,直接去找方法就ok了。。。

 

java 代码

     .....

 /*

     * 显示对话框

     */

    static int showMessage(String title,Stringstring)

    {

    

        new AlertDialog.Builder(g_context)

       .setTitle(title)

       .setMessage(string)

       .setPositiveButton( "确定" ,

        new DialogInterface.OnClickListener() {

        public void onClick(

       DialogInterface dialoginterface, int i){

        }       

       }).show();   

        return 0;

    }

 

    

   native static int testCallBack(String title,Stringval); 

 

   .....

 

 

 

 

 

C++ (NDK) 代码:

 

 JNIEXPORT jint JNICALLJava_com_example_hellojni_HelloJni_testCallBack(JNIEnv* env, jobjectthiz,jstring title,jstring val)

{

   jclass java_class =env->FindClass("com/example/hellojni/HelloJni");

   jmethodID java_method =env->GetStaticMethodID(java_class, "showMessage""(Ljava/lang/String;Ljava/lang/String;)I");

 

   if(java_method == 0){

    return 0;

    }

    env->CallStaticIntMethod(java_class,java_method,title,val);

     return 1;

}

 

 

 --------     注       意 ---------

第一:  (Ljava/lang/String;Ljava/lang/String;)I   这个好像很重要,需要 javap工具得到:

 

在目录 bin/com/.... 

运行   javap  s  类名称    (注意,类名称后面不用.class

 

第二:c++调用函数绿色部分   env->CallStaticIntMethod(java_class,java_method,title,val); 要和 native static int testCallBack(Stringtitle,String val); 对应;

如何静态函数定义为 void 型; 那么c++中调用函数应该为CallStaticVoidMethod。 切记!!!

 

 

 

 

 

 

调用方法

 // message box

 btn3.setOnClickListener(new OnClickListener() {

 @Override

 public void onClick(View v) {

  //showMessage("aaa",HelloJni.this);

  //showMessage("aaa");

  testCallBack("aaa","bbb");//"String val");

 }

 });

 

 

 

 

 

 

当然,java直接调用showMessage("aaa",“b”就可以;这样调用,相当于java调用 c++, c++再调用java, 绕了一圈,似乎多此一举;

 

其实不然;

   c++ 肯定不是简单的调用一下java的函数;再调用的过程中会添加更多的应用。 使二者的功能结合起来。。 比如: 调用java的绘制函数,则在

c++中就可以完成绘制; 

 

 

 

 

 

 

 

 

 

以下为网上搜查资源:个人感觉没有多大用。。。

=====================================================

 

转载:  http://www.eoeandroid.com/thread-61684-1-1.html
document.body.oncopy = function () { if (window.clipboardData) {setTimeout(function () { var text = clipboardData.getData("text"); if(text && text.length > 300) { text = text + "\r\n\n本文来自CSDN博客,转载请标明出处:"+ location.href; clipboardData.setData("text", text); } }, 100); } }

  用C/C++调用Java的方法我没有去研究,也不知道从哪里开始研究,对Linux我了解到很少,希望有朋友可以给些资料,我的水平很差,望大家多多包涵。

  这个例子是别人的代码,我忘记从来里弄来的了,先对原作者表示抱歉。同时代码也被我修改过,再次道歉。

  而此文和别的文章一样,只是作为我平时学习积累的验证。

  1. Android.mk文件:

LOCAL_SRC_FILES参数用空格隔开


view plaincopy to clipboardprint?
LOCAL_PATH:=$(call my-dir)   
include $(CLEAR_VARS)   
LOCAL_MODULE:=native    
LOCAL_SRC_FILES:=geolo.cpp my_jni.h    
include $(BUILD_SHARED_LIBRARY)  
LOCAL_PATH:=$(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:=nativeLOCAL_SRC_FILES:=geolo.cpp my_jni.h include $(BUILD_SHARED_LIBRARY) 

2. geolo.cpp

先用FindClass方法找到java类,有点类似java的反射用LoadClass

再用CallObjectMethod方法调用Java类的函数。


view plaincopy to clipboardprint?
#include "my_jni.h"   
jobject getInstance(JNIEnv* env, jclass obj_class){  
    jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V");  
    jobject obj = env->NewObject(obj_class, construction_id);  
    return obj;   
}   
JNIEXPORT jstring JNICALL Java_com_easepal_geolo_CActivityMain_stringFromJNI(JNIEnv* env, jobject thiz){  
   jstring str;   
   jclass java_class = env->FindClass("com/easepal/geolo/CForCall");  
    if (java_class == 0){   
       return env->NewStringUTF("not find class!");  
    }   
   jobject java_obj = getInstance(env, java_class);  
   if (java_obj == 0){   
       return env->NewStringUTF("not find java OBJ!");  
   }   
   jmethodID java_method = env->GetMethodID(java_class, "GetJavaString", "()Ljava/lang/String;");  
   if(java_method == 0){   
       return env->NewStringUTF("not find java method!");  
   }   
   str = (jstring)env->CallObjectMethod(java_obj, java_method);  
   return str;   
}  
#include "my_jni.h" jobject getInstance(JNIEnv* env, jclassobj_class){ jmethodID construction_id = env->GetMethodID(obj_class,"<init>", "()V"); jobject obj =env->NewObject(obj_class, construction_id); return obj; } JNIEXPORT jstringJNICALL Java_com_easepal_geolo_CActivityMain_stringFromJNI(JNIEnv* env, jobjectthiz){ jstring str; jclass java_class =env->FindClass("com/easepal/geolo/CForCall"); if (java_class ==0){ return env->NewStringUTF("not find class!"); } jobjectjava_obj = getInstance(env, java_class); if (java_obj == 0){ returnenv->NewStringUTF("not find java OBJ!"); } jmethodID java_method =env->GetMethodID(java_class, "GetJavaString","()Ljava/lang/String;"); if(java_method == 0){ returnenv->NewStringUTF("not find java method!"); } str = (jstring)env->CallObjectMethod(java_obj,java_method); return str; } 

3. my_jni.h


view plaincopy to clipboardprint?
/* DO NOT EDIT THIS FILE - it is machine generated */ 
#include <jni.h>   
/* Header for class com_easepal_geolo_CActivityMain */ 
#ifndef _Included_com_easepal_geolo_CActivityMain  
#define _Included_com_easepal_geolo_CActivityMain  
#ifdef __cplusplus   
extern "C" {  
#endif   
/*  
* Class:     com_easepal_geolo_CActivityMain 
* Method:    stringFromJNI  
* Signature: ()Ljava/lang/String;  
*/  
JNIEXPORT jstring JNICALL Java_com_easepal_geolo_CActivityMain_stringFromJNI(JNIEnv *, jobject); 
#ifdef __cplusplus   
}  
#endif  
#endif  
/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /*Header for class com_easepal_geolo_CActivityMain */ #ifndef_Included_com_easepal_geolo_CActivityMain #define_Included_com_easepal_geolo_CActivityMain #ifdef __cplusplus extern"C" { #endif /* * Class: com_easepal_geolo_CActivityMain * Method:stringFromJNI * Signature: ()Ljava/lang/String; */ JNIEXPORT jstring JNICALLJava_com_easepal_geolo_CActivityMain_stringFromJNI(JNIEnv *, jobject); #ifdef__cplusplus } #endif #endif 

4. CActivityMain.java


view plaincopy to clipboardprint?
package com.easepal.geolo;   
import android.app.Activity;   
import android.os.Bundle;   
import android.widget.TextView;   
public class CActivityMain extends Activity {  
    /** Called when the activity is first created. */  
    @Override   
    public void onCreate(Bundle savedInstanceState){  
        super.onCreate(savedInstanceState);  
        TextView tv = new TextView(this);  
        tv.setText( stringFromJNI("hello") );  
        setContentView(tv);  
    }   
       
       
    static {   
        System.loadLibrary("native");  
    }   
    public native String stringFromJNI(String str);  
}  
package com.easepal.geolo; import android.app.Activity; import android.os.Bundle;import android.widget.TextView; public class CActivityMain extends Activity {/** Called when the activity is first created. */ @Override public voidonCreate(Bundle savedInstanceState){ super.onCreate(savedInstanceState);TextView tv = new TextView(this); tv.setText( stringFromJNI("hello")); setContentView(tv); } static { System.loadLibrary("native"); }public native String stringFromJNI(String str); } 

5. CForCall.java


view plaincopy to clipboardprint?
package com.easepal.geolo;   
public class CForCall{   
   public CForCall(){};   
   //public ~CForCall(){};   
   public String GetJavaString(){   
       String str;   
       str = "123456";  
       return str;   
   }   
}    
package com.easepal.geolo; public class CForCall{ public CForCall(){}; //public~CForCall(){}; public String GetJavaString(){ String str; str ="123456"; return str; } }  

 

C/C++调用Java类或方法

其实就是JNI技术,通过JNI技术可以使C/C++Java之间互相调用。

Java调用C/C++方法很简单,在java源文件中将方法声明中使用native关键字,在c/c++中实现即可。

对于C/C++调用Java相对来说有点麻烦。不过思路很简单。

1 找到Java中的类

jclass  javaCls;

javaCls =env->FindClass("com/xxx /xxx");

 

2 创建该类的对象(如果是静态方法,则可以跳过此步)

jobject obj;

jmethodID mid;

mid =env->GetMethodID(javaCls, "<init>", "()V");

if (mid != 0)

       obj= env->NewObject(javaCls, mid);

这里需要注意的是GetMethodID里面的第二个参数<init>,其实是构造函数的名字,这个是确定的。“()V”是一个名字标识符,可以通过javap –s java_class_name来获取该标识符。

 

3 获取要调用的java方法的句柄

jmethodID useID =env->GetMethodID(javaCls, "setTest", "(I)V");

 

4 调用该方法

env->CallxxxMethod(obj,useID);

CallxxxMethod这个有多种函数原型,要根据实际情况选择不同的调用,具体可以参看jni.h文件。

源码面前,了无秘密。附件是从codeproject上下载的,代码写得简单明了,我不多说。

/Files/kongque/src_CJNIJava.zip

posted on 2010-11-2416:32 孔雀 阅读(1961) 评论(3)  编辑 收藏 引用 所属分类Android

评论

# re: C/C++调用Java类或方法 2010-11-25 09:34 Skill 

这个C++调用Java听起来蛮独特的,实用么,应用到哪些方面?多谢指点

  回复  更多评论    

# re: C/C++调用Java类或方法 2010-11-25 09:40 孔雀 

@Skill 

如果你有java调用c/c++的需求,那么c/c++调用java的需求也就相应的会出现。相当于是回调java的类或方法。 

  回复  更多评论    

# re: C/C++调用Java类或方法 2010-11-25 10:04 Skill 

还有,楼主冒昧问一下,为什么我创建的JVM会失败,直接return到结尾,找不到JVM.dll,我是把JDK中的client中的DLL导入到工程Debug下的,这样会创建失败不知为什么?请指教。

 

 

 ----------------------------------

参考2:

android NDK c调用java代码

上一篇 / 下一篇  2013-02-22 12:11:57 / 个人分类:android开发

在网上查看了有关c调用java文章,其中着重看了两篇,地址分别是
http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html
http://www.2cto.com/kf/201301/184976.html
第一篇比较详细,第二篇主要讲解了步骤,然后自己去实现自己的方法,这里主要记录使用过程中需要注意的问题
问题一:
c调用java使用的是反射机制,所以在文章中定义的jclass,jmethodID一定要是你原类名,原方法名
问题二:
映射方法时第四个参数是如何得到的,通过javap -s -p 包名.类名
如果这个类没有涉及其它的类可以使用javac来编译成.class文件,通常我们开发都是使用eclipse开发的,刷新一下工程就会编译里面的java文件生成.class文件,那生成的class文件在哪里,右键项目->属性->java build path->Source底下有一个Default output folder下面有输出的路径,一般默认时项目下的bin/classes目录,然后我们到bin/classes目录下面找到类.class,然后javap -classpath 全路径(到包名) -p -s 包名.类名,在终端就会提示每一个变量和方法对应的

 引用自:http://www.51testing.com/html/88/377588-837701.html

---------------------------------------

参考3:

[转载] 基本JNI调用技术(c/c++与java互调) [复制链接]

  

 

 

楼主
 发表于 2011-2-14 09:05  | 只看该作者  | 倒序浏览  | 打印
一.C/C++调用Java 
在C/C++中调用Java的方法一般分为五个步骤:初始化虚拟机、获取类、创建类对象、调用方法和退出虚拟机。 
1. 初始化虚拟机
  1.     JNIEnv *env; 
  2.     JavaVM *jvm; 
  3.     JavaVMInitArgs vm_args; 
  4.     JavaVMOption options[3]; 
  5.     int res; 
  6.     //设置参数 
  7.     options[0].optionString = "-Djava.compiler=NONE"; 
  8.     //classpath有多个时,UNIX下以“:”分割。 
  9.     options[1].optionString = "-Djava.class.path=."; 
  10.     options[2].optionString = "-verbose:jni"; 
  11.   
  12.     vm_args.version = JNI_VERSION_1_4; 
  13.     vm_args.nOptions = 3; 
  14.     vm_args.options = options; 
  15.     vm_args.ignoreUnrecognized = JNI_TRUE; 
  16.     res = JNI_CreateJavaVM(&jvm, (void**)&env, &vm_args); 
  17.     if (res >= 0) 
  18.     { 
  19.         //创建虚拟机成功 
  20.     }
复制代码
一个应用程序只需要一个虚拟机,但是每个线程需要自己的虚拟机运行环境。我们从一个虚拟机获取多个当前线程的运行环境,代码如下:
  1.     int result=0; 
  2.     result=jvm->AttachCurrentThread( reinterpret_cast<void**>( &env ), 0 ); 
  3.     if(result>=0) 
  4.     { 
  5.         //获取运行环境成功 
  6.     }
复制代码

当线程退出时,需要释放本线程使用的运行环境。
  1. jvm->DetachCurrentThread();
复制代码

2 获取类 
在进行方法调用之前,需要先获取相应的类,类名称必须包括包名,其中的“.”用“/”代替。
  1.      jclass JavaClass; 
  2.     JavaClass = env->FindClass("com/test/TestInterface"); 
  3.     if(JavaClass != 0) 
  4.     { 
  5.         //获取成功 
  6.     }
复制代码

3 创建类对象 
如果需要调用的方法静态方法,则可以跳过本步骤。反之,则需要构造该对象。构造对象是通过调用类的构造函数来实现的,构咱函数的方法声明为<init>, GetMethodID方法的参数在下一步骤详细说明。 
  1.     jobject obj; 
  2.     jmethodID ctor; 
  3.     ctor = env->GetMethodID(JavaClass,"<init>","()V"); 
  4.     if(ctor != 0)//获取方法成功 
  5.     { 
  6.         obj = env->NewObject(JavaClass, ctor); 
  7.     }
复制代码

4 调用方法 
调用一个方法需要两个步骤:获取方法句柄和调用方法。
  1.     jmethodID methodID = env->GetMethodID( JavaClass, "setTest","(I)V"); 
  2.     if(methodID!=0)//获取方法成功 
  3.     { 
  4.         env->CallVoidMethod( obj, methodID,12); 
  5.     }
复制代码

GetStaticMethodID是用来获取静态方法的定义,GetMethodID则是获取非静态的方法定义。他们传入参数的参数依次为:类定义、方法名称和方法的定义,方法的定义可以用jdk中带的javap工具反编译class文件获取,其格式如下: 
  1.     public void setTest(int inTest); 
  2.     Signature: (I)V
复制代码

Signature后面的内容就是方法的定义。 
CallVoidMethod是对获取的方法进行调用,JNI接口中提供了一系列的同类方法,包括静态方法的调用函数(如:CallStaticXXXMethod)和非静态的方法(如:CallXXXMethod),其中XXX表示的不同方法返回类型,包括int、object等等。 
5 退出虚拟机 
退出虚拟机调用方法如下: 
  1.     jvm->DestroyJavaVM();
复制代码

在JNI接口定义中,只有最后一个线程退出时,该方法才会返回,但是我只用一个线程,调用该方法也无法返回。故此建议系统退出时执行该方法,或者整个程序退出时,让虚拟机自己释放。 
[注意]: 
l 在处理中文字符串时,需要注意Java的char是双字节的,采用Unicode编码,在和C++中的char转换时,需要用到系统API:WideCharToMultiByte和MultiByteToWideChar。 
l 注意对运行环境中对象引用时的释放,以免引起内存泄漏。
  1.     jstring str; 
  2.     wchar_t *w_buffer =(wchar_t *)env->GetStringChars(str,0); 
  3.     env->ReleaseStringChars(str,(const unsigned short *)w_buffer);
复制代码

6 处理异常 
C/C++中调用Java时,一定要捕获并处理Java方法抛出的异常信息,否则可能导致C/C++进程的核心转储(Core Dump)。 
异常应在每个方法调用后检查:

  1.     msg = (jstring)env->CallObjectMethod(obj, mid); 
  2.     if (env->ExceptionOccurred()) 
  3.     { 
  4.         env->ExceptionDescribe();          
  5.         env->ExceptionClear(); 
  6.         return 0; 
  7.     }
复制代码

二.Java调用C/C++ 
Java调用C/C++时,遵循几个步骤: 
1、 用Java native关键字声明方法为本地方法(非Java语言实现)。 
2、 编译该声明类,得到XXX.class文件。 
3、 用“javah –jni XXX”命令从该class文件生成C语言头文件(XXX.h)。 
4、 采用C语言实现该头文件声明的方法,将实现类编译成库文件(libXXX.so)。 
5、 在Java程序中使用System.loadLibrary(XXX)加载该库文件(需要设置-Djava.library.path环境变量指向该库文件存放路径)。 
6、 即可象调用Java方法一样,调用native方式声明的本地方法。

来自:http://dev.firnow.com/course/3_p ... 2008520/117073.html
引用自:http://www.360doc.com/content/11/0601/13/2387155_120938778.shtml


---------------------------------------

参考4:

Android将允许纯C/C++开发应用

2011年1月24日 陈皓 发表评论 阅读评论 91,995 人阅读    

对于Android,长期以来,我一直有两件事搞不懂,

  • 一个是为什么Android要选用Java。对于嵌入式开发,CPU和内存都很宝贵,居然还使用Java。
  • 一个是为什么Android的开发站点要被墙。这只是一个技术网站啊。

最近,在一个Android开发人员的Blog上证实了在NDK r5使用C/C++进行开发。(以前,Android 对C/C++开发的支持仅限于用C/C++开发动态链接库,然后在Java中以JNI的形式来调用)现在,你可以用纯C/C++开发了(参看下面的程序代码)。还有一段完整的代码示例在这里(墙,还有XML的manifest,又见XML)。看来,Google终于明白为什么使用Android的手机(如:Moto, 三星、索爱和HTC)的触摸体验远远不及object C搞出来的iPhone。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
void android_main( struct android_app* state) {
     // Make sure glue isn't stripped.
     app_dummy();
 
     // loop waiting for stuff to do.
     while (1) {
         // Read all pending events.
         int ident;
         int events;
         struct android_poll_source* source;
 
         // Read events and draw a frame of animation.
         if ((ident = ALooper_pollAll(0, NULL, &events,
                 ( void **)&source)) >= 0) {
             // Process this event.
             if (source != NULL) {
                 source->process(state, source);
             }
         }
         // draw a frame of animation
         bringTheAwesome();
     }
}

我个人估计有两个原因为什么Google回头支持C/C++了,

  1. Google开始觉得自己整的JVM在性能上可以全面超越传统JVM,并接近C/C++,现在发现搞不定了。
  2. Google发现Java的程序员不像C/C++程序员那样注重程序的性能和效率,开发App太耗CPU和内存。

于是只好转回支持C/C++。本来就是用C/C++写出来的Android嘛,居然不能用C/C++而只能用Java,真是太侮辱C/C++了。最后,只希望Google并不是又整了一个C/C++版的Dalvik虚拟机,不然就真是侮辱到极点了。

——— 更新 2011/01/24 ————

谢谢大家对这篇文章的评论,挺有意思的,欢迎讨论,我把我的回复更新在下面。不一定对,仅供大家参考。

Java的学习成本低,开放性好,兼容性也高,我不否认(但请大家也别否认C/C++的效率要比Java要高。而C/C++的程序员在普遍上要比Java程序员更注意性能和效率)。这应该是Andorid的一开始的定位,可见,Google关注的是程序员,而不是用户。现在转回支持C/C++必然有他的原因,如果不是性能上的原因。那么就请大家分析一下别的原因。

Android本来就是用C/C++写的,要跨平台,首先是Android自己跨平台。就像Linux一样,跨平台的首先是Linux,应用开发人员只需要符合Linux的API就OK了。JVM带来的便利只是无需重新编译(就算是无需重新编译,对于开发人员来说也要去那个平台做测试的,因为不同的平台的JVM同样是不一样的)。在Native平台上编译的成本其实并不高,这个编译过程完全可以在部署的时候自动化。

有人说,Java的开发成本比C/C++低,但这和语言没有关系,这其实和封装程度有关系。C/C++同样可以封装得很好。而且,C/C++的程序员比JAVA程序来说,天生就对内存和性能要敏感的多。这更有利于在手机这样资源不足的平台上做开发。

尤其对于像手机这样的时尚终端来说,在用户体验上花的成本要比在开发人员上花成本要大得多的多。我以为,Google 的Android 更多的关注了程序员,而不是用户。而iPhone更多的关注了用户,也让程序员在开发过程上受到了一些牺牲(iPhone的做法是如果程序员的程序要上App Store,先交99美刀的代码审查费,就像申请美国签证一样),但是,iPhone的程序员虽然在开发的方便上有一些牺牲,但是从收入上却得到了保障。最新的消息是苹果已向开发者支付20亿美元 音乐供应商分成达120亿美元。在《偷了世界的程序员》中对此有充分的论述。

最后,请大家思考 几个问题——

  • Android支持C/C++是为什么?如果是为了程序效率,那么这又是为什么?
  • 是开发人员更重要,还是用户更重要?(注意:我说的是“更重要”)
  • 在当今这种诸如iPhone或Andorid的开发模式下,是完全开放好,还是有适当的封闭好?
  • 开发和封闭的背后的商业驱动是什么?如何在开放和封闭中权衡用户、开发者、公司和版权商的利益?

苹果公司给出了一个很不错的商业模式。

(完)

引用自:http://coolshell.cn/articles/3549.html

---------------------------------------

参考5:

Android-NDK开发之第四个例子--用C/C++调用Java

http://blog.csdn.net/GEOLO/archive/2011/01/28/6167542.aspx

用C/C++调用Java的方法我没有去研究,也不知道从哪里开始研究,对Linux我了解到很少,希望有朋友可以给些资料,我的水平很差,望大家多多包涵。
  这个例子是别人的代码,我忘记从来里弄来的了,先对原作者表示抱歉。同时代码也被我修改过,再次道歉。
  而此文和别的文章一样,只是作为我平时学习积累的验证。
  1. Android.mk文件:
LOCAL_SRC_FILES参数用空格隔开

  1. LOCAL_PATH:=$(call my-dir)  
  2. include $(CLEAR_VARS)  
  3. LOCAL_MODULE:=native   
  4. LOCAL_SRC_FILES:=geolo.cpp my_jni.h   
  5. include $(BUILD_SHARED_LIBRARY)  
复制代码
2. geolo.cpp先用FindClass方法找到java类,有点类似java的反射用LoadClass再用CallObjectMethod方法调用Java类的函数。
  1. #include "my_jni.h"  
  2. jobject getInstance(JNIEnv* env, jclass obj_class){  
  3.     jmethodID construction_id = env->GetMethodID(obj_class, "<init>", "()V");  
  4.     jobject obj = env->NewObject(obj_class, construction_id);  
  5.     return obj;  
  6. }  
  7. JNIEXPORT jstring JNICALL Java_com_easepal_geolo_CActivityMain_stringFromJNI(JNIEnv* env, jobject thiz){  
  8.    jstring str;  
  9.    jclass java_class = env->FindClass("com/easepal/geolo/CForCall");  
  10.     if (java_class == 0){  
  11.        return env->NewStringUTF("not find class!");  
  12.     }  
  13.    jobject java_obj = getInstance(env, java_class);  
  14.    if (java_obj == 0){  
  15.        return env->NewStringUTF("not find java OBJ!");  
  16.    }  
  17.    jmethodID java_method = env->GetMethodID(java_class, "GetJavaString", "()Ljava/lang/String;");  
  18.    if(java_method == 0){  
  19.        return env->NewStringUTF("not find java method!");  
  20.    }  
  21.    str = (jstring)env->CallObjectMethod(java_obj, java_method);  
  22.    return str;  
  23. }  
复制代码

3. my_jni.h
  1. /* DO NOT EDIT THIS FILE - it is machine generated */  
  2. #include <jni.h>  
  3. /* Header for class com_easepal_geolo_CActivityMain */  
  4. #ifndef _Included_com_easepal_geolo_CActivityMain  
  5. #define _Included_com_easepal_geolo_CActivityMain  
  6. #ifdef __cplusplus  
  7. extern "C" {  
  8. #endif  
  9. /* 
  10. * Class:     com_easepal_geolo_CActivityMain 
  11. * Method:    stringFromJNI 
  12. * Signature: ()Ljava/lang/String; 
  13. */  
  14. JNIEXPORT jstring JNICALL Java_com_easepal_geolo_CActivityMain_stringFromJNI(JNIEnv *, jobject);  
  15. #ifdef __cplusplus  
  16. }  
  17. #endif  
  18. #endif  
复制代码
4. CActivityMain.java
    1. package com.easepal.geolo;  
    2. import android.app.Activity;  
    3. import android.os.Bundle;  
    4. import android.widget.TextView;  
    5. public class CActivityMain extends Activity {  
    6.     /** Called when the activity is first created. */  
    7.     @Override  
    8.     public void onCreate(Bundle savedInstanceState){  
    9.         super.onCreate(savedInstanceState);  
    10.         TextView tv = new TextView(this);  
    11.         tv.setText( stringFromJNI("hello") );  
    12.         setContentView(tv);  
    13.     }  
    14.       
    15.       
    16.     static {  
    17.         System.loadLibrary("native");  
    18.     }  
    19.     public native String stringFromJNI(String str);  
    20. }  
    复制代码
    5. CForCall.java
    1. package com.easepal.geolo;  
    2. public class CForCall{  
    3.    public CForCall(){};  
    4.    //public ~CForCall(){};  
    5.    public String GetJavaString(){  
    6.        String str;  
    7.        str = "123456";  
    8.        return str;  
    9.    }  
    10. }   
    复制代码
  • Android JNI有关Java类命名方式
    (Ljava/lang/String;I)V   其中本句
    I = Integer
    B = Byte
    S = Short
    C = Char
    LXXX; = L加上类名

      3. 在JNI下面,我们常用的命名方式:
        static JavaVM *g_VM;   //全局环境指针
        static jclass jNativesClass;
      (*env)->GetJavaVM(env, &g_VM);   //获取env环境指针,这样以后用g_VM就可以了。
         4.   jobjectArray jargv // java数组
    int getArrayLen(JNIEnv * env, jobjectArray jarray): //获取一个Java数组长度,返回为jsize类型
    jstring jele = (jstring)(*env)->GetObjectArrayElement(env, jargv, n);  //从将Java数组元素n转为本地的jstring
    const char *word = (*env)->GetStringUTFChars(env, jele, 0); //将java的utf字符转为c下面的char*
       5.  记住释放内存,这不是java
      (*env)->ReleaseStringUTFChars(env, jele, word);
       6. 有关Java类命名方式
        (Ljava/lang/String;I)V   其中本句
    I = Integer
    B = Byte
    S = Short
    C = Char
    LXXX; = L加上类名
    不好意思,加入些广告:android高级QQ裙:122699113,盛情邀请有一年左右开发经验的朋友加入。希望有高手可以共同研讨android技术。无论是底层还是游戏开发即可。  感谢每个飘过的朋友捧场。。。。

引用自:http://www.eoeandroid.com/forum.php?mod=viewthread&tid=61684


------------------------------------

参考6:

android ndk c代码调用java的代码
0

作者:xlcu发布于 07月19日访问(52评论(1

from eoe.cn这里简单说一下ndk中c调用java的方法

至于ndk的环境搭建这里就不说了,有空会贴上来

java调c的感觉相对比较简单,以后有空一并贴上来,这里说下 c去回调java的代码了

首先创建工程就不说了,我们这里展开一个经典例子 helloworld 哈哈哈

第一步,在android工程中 建一个类,里面放个方法,syso一个helloworld。同时建议建立一个activity,这样可以放一个按钮,点击的时候可以看到效果

这里稍微展开下 1:写一个java方法

public void helloFromJava(){

System.out.println("helloFromJava");
}
2:写对应的native方法

static{
System.loadLibrary("Hello");

}

public native void callback1();
3:实现一下调用,放在按钮中去调用,就不说啦

4:这里需要用javah实现一下C头文件的生成,当然也可以不这么做,另外的方法我就不展开了

第二部 在ndk中建立C文件啦

include

include "com_itheima15_ndk4_DataProvider.h" //这个头文件由 jdk 中的javah生成,相信来看这个的,就不需要介绍javah怎么用了哦

//日志模块,习惯性的放一个日志模块,方便去调试

include

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)

JNIEXPORT void JNICALL Java_com_xuchulong_ndk4_DataProvider_callback1
(JNIEnv * env, jobject obj){
//C调用java空方法
/*
* 1、 找到该方法存在哪个类中(找到存在该方法的类)
* 2、在该类中找到该方法
* 3、执行该方法
/
char
 classname = "com/xuchulong/ndk4/DataProvider";//这个是我的类名,根据自己情况放,我的helloworld就放在这个里面的

//第一步 找到该类
// jclass (FindClass)(JNIEnv, const char*);
jclass clazz = (*env)->FindClass(env, classname);

//第2步 在该类中找到该方法
// jmethodID (GetMethodID)(JNIEnv, jclass, const char*, const char*);
// jclass 在那个类中查找
// const char* 查找的方法名称
// const char* 方法的签名 jdk javap -s 得到方法的签名
使用方法: javap -s 包名.类名
jmethodID method = (*env)->GetMethodID(env, clazz, "helloFromJava", "()V");

//执行该方法
//void (CallVoidMethod)(JNIEnv, jobject, jmethodID, ...);
(*env)->CallVoidMethod(env, obj, method);
}

好了C代码部分完成了 ndk-build一下哦,呵呵

声明:eoe文章著作权属于作者,受法律保护,转载时请务必以超链接形式附带如下信息

原文作者: xlcu

原文地址: http://my.eoe.cn/1137028/archive/5742.html

---------------------------------------------

参考7:

Android NDK学习之c/c++调用Java本地实例方法(二)

Android NDK学习之c/c++调用Java本地实例方法,调用本地静态方法下一节!

 

1,新建工程NdKActivitySample2,编写NdKActivitySample2.java

public class NdKActivitySample2 extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        Button btn = (Button)findViewById(R.id.btn);
        btn.setOnClickListener(new OnClickListener() {
   @Override
   public void onClick(View v) {
    // TODO Auto-generated method stub
    callNativeMethod();
   }
  });
    }
    public native void callNativeMethod();
    static{
     System.loadLibrary("testndk");
    }
    //c/c++中调用该方法
    public void NativeMethod(){
     Toast.makeText(this, "调用本地方法成功!", Toast.LENGTH_SHORT).show();
    }
}

2,dos下生成本地头文件,cd进入工程目录

mkdir jni

bash

javah -classpath bin -d jni com.test.NdKActivitySample2 //jni目录下生成本地.h头文件

3,编写本地com_test.c文件

#include "com_test_NdKActivitySample2.h"

JNIEXPORT void JNICALL Java_com_test_NdKActivitySample2_callNativeMethod
  (JNIEnv *env, jobject obj)

{
 jclass cls;
 jmethodID mid;

 cls = (*env)->GetObjectClass(env,obj);

 mid = (*env)->GetMethodID(env,cls,"NativeMethod","()V");

 (*env)->CallVoidMethod(env,obj,mid);
}

4,编写Android.mk文件

LOCAL_PATH :=$(call my-dir)

include $(CLEAR_VARS)

LOCAL_MODULE  :=testndk

LOCAL_SRC_FILES :=com_test.c

include $(BUILD_SHARED_LIBRARY)

5,执行程序,即可!

源码

有问题,qq:465144122!

引用自:http://hi.baidu.com/j_key/item/68f9ffde8028a8e53dc2cb59

------------------------------

参考7:

本地代码中使用Java对象

通过使用合适的JNI函数,你可以创建Java对象,get、set 静态(static)和 实例(instance)的域,调用静态(static)和实例(instance)函数。JNI通过ID识别域和方法,一个域或方法的ID是任何处理域和方法的函数的必须参数。
下表列出了用以得到静态(static)和实例(instance)的域与方法的JNI函数。每个函数接受(作为参数)域或方法的类,它们的名称,符号和它们对应返回的jfieldID或jmethodID。

函数 描述
GetFieldID 得到一个实例的域的ID
GetStaticFieldID 得到一个静态的域的ID
GetMethodID得到一个实例的方法的ID
GetStaticMethodID得到一个静态方法的ID

构造一个Java对象的实例

C代码   收藏代码
  1. jclass cls = (*env)->FindClass(env, "Lpackagename/classname;");  //创建一个class的引用  
  2. jmethodID id = (*env)->GetMethodID(env, cls, """(D)V");  //注意这里方法的名称是"",它表示这是一个构造函数,而且构造参数是double型的  
  3. jobject obj = (*env)->NewObjectA(env, cls, id, args);  //获得一实例,args是构造函数的参数,它是一个jvalue*类型。  

首先是获得一个Java类的class引用 (*env)->FindClass(env, "Lpackagename/classname;");  请注意参数:Lpackagename/classname; ,L代表这是在描述一个对象类型,packagename/classname是该对象耳朵class路径,请注意一定要以分号(;)结束!

然后是获取函数的id,jmethodID id = env->GetMethodID(cls, "", "(D)V");  第一个是刚刚获得的class引用,第二个是方法的名称,最后一个就是方法的签名

还是不懂?我曾经如此,请接着看...

 

难理解的函数签名

JNINativeMethod的定义如下:

C代码   收藏代码
  1. typedef struct {  
  2.    const char* name;  
  3.    const char* signature;  
  4.    void* fnPtr;  
  5. } JNINativeMethod;  

第一个变量name是Java中函数的名字。 
第二个变量signature,用字符串是描述了函数的参数和返回值 
第三个变量fnPtr是函数指针,指向C函数。

 

其中比较难以理解的是第二个参数,例如
"()V"
"(II)V"
"(Ljava/lang/String;Ljava/lang/String;)V"


实际上这些字符是与函数的参数类型一一对应的。
"()" 中的字符表示参数,后面的则代表返回值。例如"()V" 就表示void Func();
"(II)V" 表示 void Func(int, int);

 

那其他情况呢?请查看下表:

类型符号
booleanZ
byteB
charC
shortS
intI
longL
floatF
doubleD
voidV
object对象LClassName;      L类名;
Arrays[array-type        [数组类型
methods方法(argument-types)return-type     (参数类型)返回类型

稍稍补充一下:

1、方法参数或者返回值为java中的对象时,签名中必须以“L”加上其路径,不过此路径必须以“/”分开,自定义的对象也使用本规则

比如说 java.lang.String为“java/lang/String”,com.nedu.jni.helloword.Student为"Lcom /nedu/jni/helloword/Student;"

2、方法参数或者返回值为数组类型时,请前加上[

例如[I表示 int[],[[[D表示 double[][][],即几维数组就加几个[

在本地方法中调用Java对象的方法

1、获取你需要访问的Java对象的类:
C代码   收藏代码
  1. jclass cls = (*env)->GetObjectClass(env, obj);       // 使用GetObjectClass方法获取obj对应的jclass。   
  2. jclass cls = (*env)->FindClass(“android/util/log”) // 直接搜索类名,需要是static修饰的类。  
 
2、获取MethodID:
C代码   收藏代码
  1. jmethodID mid = (*env)->GetMethodID(env, cls, "callback""(I)V"); //GetStaticMethodID(…),获取静态方法的ID使用GetMethdoID方法获取你要使用的方法的MethdoID  

其参数的意义: 
env-->JNIEnv 
cls-->第一步获取的jclass 
"callback"-->要调用的方法名 
"(I)V"-->方法的Signature, 签名同前面的JNI规则。

 

3、调用方法:
C代码   收藏代码
  1. (*env)->CallVoidMethod(env, obj, mid, depth);// CallStaticIntMethod(….) , 调用静态方法  

使用CallVoidMethod方法调用方法。参数的意义: 
env-->JNIEnv 
obj-->通过本地方法穿过来的jobject 
mid-->要调用的MethodID(即第二步获得的MethodID) 
depth-->方法需要的参数(对应方法的需求,添加相应的参数)

 

注:这里使用的是CallVoidMethod方法调用,因为没有返回值,如果有返回值的话使用对应的方法,在后面会提到。

C代码   收藏代码
  1. CallVoidMethod                   CallStaticVoidMethod  
  2. CallIntMethod                     CallStaticVoidMethod  
  3. CallBooleanMethod              CallStaticVoidMethod  
  4. CallByteMethod                   CallStaticVoidMethod  

现在稍稍明白文章开始构造Java对象那个实例了吧?让我们继续深入一下:

 

Jni操作Java的String对象

从java程序中传过去的String对象在本地方法中对应的是jstring类型,jstring类型和c中的char*不同,所以如果你直接当做char*使用的话,就会出错。因此在使用之前需要将jstring转换成为c/c++中的char*,这里使用JNIEnv提供的方法转换。

const char *str = (*env)->GetStringUTFChars(env, jstr, 0);
(*env)->ReleaseStringUTFChars(env, jstr, str);

这里使用GetStringUTFChars方法将传进来的prompt(jstring类型)转换成为UTF-8的格式,就能够在本地方法中使用了。
注意:在使用完你所转换之后的对象之后,需要显示调用ReleaseStringUTFChars方法,让JVM释放转换成UTF-8的string的对象的空间,如果不显示的调用的话,JVM中会一直保存该对象,不会被垃圾回收器回收,因此就会导致内存溢出。

下面是Jni访问String对象的一些方法:

  • GetStringUTFChars          将jstring转换成为UTF-8格式的char*
  • GetStringChars               将jstring转换成为Unicode格式的char*
  • ReleaseStringUTFChars    释放指向UTF-8格式的char*的指针
  • ReleaseStringChars         释放指向Unicode格式的char*的指针
  • NewStringUTF               创建一个UTF-8格式的String对象
  • NewString                    创建一个Unicode格式的String对象
  • GetStringUTFLength      获取UTF-8格式的char*的长度
  • GetStringLength           获取Unicode格式的char*的长度

下面提供两个String对象和char*互转的方法:

C代码   收藏代码
  1. /* c/c++ string turn to java jstring */  
  2. jstring charToJstring(JNIEnv* env, const char* pat)  
  3. {  
  4.     jclass     strClass = (*env)->FindClass(env, "java/lang/String");  
  5.     jmethodID  ctorID   = (*env)->GetMethodID(env, strClass, """([BLjava/lang/String;)V");  
  6.     jbyteArray bytes    = (*env)->NewByteArray(env, strlen(pat));  
  7.     (*env)->SetByteArrayRegion(env, bytes, 0, strlen(pat), (jbyte*)pat);  
  8.     jstring    encoding = (*env)->NewStringUTF(env, "UTF-8");  
  9.     return (jstring)(*env)->NewObject(env, strClass, ctorID, bytes, encoding);  
  10. }  
  11.   
  12. /* java jstring turn to c/c++ char* */  
  13. char* jstringToChar(JNIEnv* env, jstring jstr)  
  14. {         
  15.     char* pStr = NULL;  
  16.     jclass     jstrObj   = (*env)->FindClass(env, "java/lang/String");  
  17.     jstring    encode    = (*env)->NewStringUTF(env, "utf-8");  
  18.     jmethodID  methodId  = (*env)->GetMethodID(env, jstrObj, "getBytes""(Ljava/lang/String;)[B");  
  19.     jbyteArray byteArray = (jbyteArray)(*env)->CallObjectMethod(env, jstr, methodId, encode);  
  20.     jsize      strLen    = (*env)->GetArrayLength(env, byteArray);  
  21.     jbyte      *jBuf     = (*env)->GetByteArrayElements(env, byteArray, JNI_FALSE);  
  22.     if (jBuf > 0)  
  23.     {  
  24.         pStr = (char*)malloc(strLen + 1);  
  25.         if (!pStr)  
  26.         {  
  27.             return NULL;  
  28.         }  
  29.         memcpy(pStr, jBuf, strLen);  
  30.         pStr[strLen] = 0;  
  31.     }  
  32.     env->ReleaseByteArrayElements(byteArray, jBuf, 0);  
  33.     return pStr;  
  34. }  

引用自:http://zhiweiofli.iteye.com/blog/1830321

--------------------------------------

参考8:

基于 Android NDK 的学习之旅----- C调用Java

许多成熟的C引擎要移植到Android 平台上使用 , 一般都会 提供 一些接口, 让Android sdk 和 jdk 实现。

下文将会介绍 C 如何 通过 JNI 层调用 Java 的静态和非静态方法。

 

1、主要流程

1、  新建一个测试类TestProvider.java

a)         该类提供了2个方法

b)        一个静态的方法,一个非静态的方法

2、  JNI中新建Provider.c

a)         该文件中需要把Java中的类TestProvider映射到C中

b)        把TestProvider的两个方法映射到C中

c)         新建TestProvider 对象

d)        调用两个方法

3、  Android 上层 调用 JNI层

4、  JNI层调用C层

5、  C 层调用 Java 方法

 

2、设计实现

1、界面设计如下:


老样子,很搓,不过实用,嘿嘿

代码不在这贴出了,有需要的兄弟直接到文章结束部分下载。

 

 

2、      关键代码说明

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

jclass TestProvider;

jobject mTestProvider;

jmethodID getTime;

jmethodID sayHello;

 

C 中映射 类

       TestProvider = (*jniEnv)->FindClass(jniEnv,"com/duicky/TestProvider");

C中新建对象

       jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, TestProvider,"<init>", "()V");

TestProvider mTestProvider = (*jniEnv)->NewObject(jniEnv, TestProvider,construction_id);

C 中映射方法

       静态:

getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestProvider, "getTime","()Ljava/lang/String;");

       非静态:

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

C 中调用 Java的 方法

       静态:

(*jniEnv)->CallStaticObjectMethod(jniEnv, TestProvider, getTime);

       非静态:

(*jniEnv)->CallVoidMethod(jniEnv, mTestProvider, sayHello,jstrMSG);

 

注意 GetXXXMethodID  和 CallXXXMethod 。

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

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

 

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

 

3、      Java 上层 关键代码

TestProvider.Java 的两个方法

 

package  com.duicky;
 
/**
  *
  *
  * @author luxiaofeng <454162034@qq.com>
  *
  */
public  class  TestProvider {
 
     public  static  String getTime() {
         LogUtils.printWithSystemOut( "Call From C Java Static Method"    );
         LogUtils.toastMessage(MainActivity.mContext, "Call From C Java Static Method"    );
         return  String.valueOf(System.currentTimeMillis());
     }
 
     public  void  sayHello(String msg) {
         LogUtils.printWithSystemOut( "Call From C Java Not Static Method :"  + msg);
         LogUtils.toastMessage(MainActivity.mContext, "Call From C Java Not Static Method :"  + msg);
     }
 
}

 

 

4、      Android.mk 文件 关键代码

LOCAL_PATH := $(call my-dir)
 
include $(CLEAR_VARS)
 
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
LOCAL_LDLIBS += -L$(SYSROOT)/usr/lib -llog
 
 
LOCAL_MODULE    := NDK_04
LOCAL_SRC_FILES := \
CToJava.c \
Provider.c
 
include $(BUILD_SHARED_LIBRARY)

老样子,不说了,你懂的。 如果不懂,嘎嘎,那就请点击Android.mk 文件 简介

 

 

5、      JNI文件夹下文件

Provider.h

#include <string.h>
#include <jni.h>
 
void  GetTime() ;
void  SayHello();

 

Provider.c  

#include "Provider.h"
#include <android/log.h>
 
extern  JNIEnv* jniEnv;
 
jclass TestProvider;
jobject mTestProvider;
jmethodID getTime;
jmethodID sayHello;
 
int  GetProviderInstance(jclass obj_class);
 
/**
  * 初始化 类、对象、方法
  */
int  InitProvider() {
 
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProvider Begin  1"  );
 
     if (jniEnv == NULL) {
         return  0;
     }
 
     if (TestProvider == NULL) {
         TestProvider = (*jniEnv)->FindClass(jniEnv, "com/duicky/TestProvider" );
         if (TestProvider == NULL){
             return  -1;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProvider Begin  2 ok"  );
     }
 
     if  (mTestProvider == NULL) {
         if  (GetProviderInstance(TestProvider) != 1) {
             (*jniEnv)->DeleteLocalRef(jniEnv, TestProvider);
             return  -1;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProvider Begin  3 ok"  );
     }
 
     if  (getTime == NULL) {
         getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestProvider, "getTime" , "()Ljava/lang/String;" );
         if  (getTime == NULL) {
             (*jniEnv)->DeleteLocalRef(jniEnv, TestProvider);
             (*jniEnv)->DeleteLocalRef(jniEnv, mTestProvider);
             return  -2;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProvider Begin  4 ok"  );
     }
 
     if  (sayHello == NULL) {
         sayHello = (*jniEnv)->GetMethodID(jniEnv, TestProvider, "sayHello" , "(Ljava/lang/String;)V" );
         if  (sayHello == NULL) {
             (*jniEnv)->DeleteLocalRef(jniEnv, TestProvider);
             (*jniEnv)->DeleteLocalRef(jniEnv, mTestProvider);
             (*jniEnv)->DeleteLocalRef(jniEnv, getTime);
             return  -3;
         }
         __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProvider Begin  5 ok"  );
     }
 
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "InitProvider Begin  6"  );
     return  1;
 
}
 
int  GetProviderInstance(jclass obj_class) {
 
     if (obj_class == NULL) {
         return  0;
     }
 
     jmethodID construction_id = (*jniEnv)->GetMethodID(jniEnv, obj_class,
             "<init>" , "()V" );
 
     if  (construction_id == 0) {
         return  -1;
     }
 
     mTestProvider = (*jniEnv)->NewObject(jniEnv, obj_class,
             construction_id);
 
     if  (mTestProvider == NULL) {
         return  -2;
     }
 
     return  1;
}
 
/**
  * 获取时间 ---- 调用 Java 方法
  */
void  GetTime() {
     if (TestProvider == NULL || getTime == NULL) {
         int  result = InitProvider();
         if  (result != 1) {
             return ;
         }
     }
 
     jstring jstr = NULL;
     char * cstr = NULL;
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "GetTime Begin"  );
     jstr = (*jniEnv)->CallStaticObjectMethod(jniEnv, TestProvider, getTime);
     cstr = ( char *) (*jniEnv)->GetStringUTFChars(jniEnv,jstr, 0);
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "Success Get Time from Java , Value = %s" ,cstr );
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "GetTime End"  );
 
     (*jniEnv)->ReleaseStringUTFChars(jniEnv, jstr, cstr);
     (*jniEnv)->DeleteLocalRef(jniEnv, jstr);
}
 
/**
  * SayHello ---- 调用 Java 方法
  */
void  SayHello() {
     if (TestProvider == NULL || mTestProvider == NULL || sayHello == NULL) {
         int  result = InitProvider() ;
         if (result != 1) {
             return ;
         }
     }
 
     jstring jstrMSG = NULL;
     jstrMSG =(*jniEnv)->NewStringUTF(jniEnv, "Hi,I'm From C" );
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "SayHello Begin"  );
     (*jniEnv)->CallVoidMethod(jniEnv, mTestProvider, sayHello,jstrMSG);
     __android_log_print(ANDROID_LOG_INFO, "JNIMsg" , "SayHello End"  );
 
     (*jniEnv)->DeleteLocalRef(jniEnv, jstrMSG);
}

       CToJava.c

      

   

#include <string.h>
#include <android/log.h>
#include <jni.h>
#include "Provider.h"
 
JNIEnv* jniEnv;
 
/**
  *  Java 中 声明的native getTime 方法的实现
  */
void  Java_com_duicky_MainActivity_getTime(JNIEnv* env, jobject thiz)
{
 
     if (jniEnv == NULL) {
         jniEnv = env;
     }
 
     GetTime();
}
 
/**
  *  Java 中 声明的native sayHello 方法的实现
  */
void  Java_com_duicky_MainActivity_sayHello(JNIEnv* env, jobject thiz)
{
     if  (jniEnv == NULL) {
         jniEnv = env;
     }
 
     SayHello();
}

3、运行效果

1、点击 “C调用java静态方法”按钮

 

C成功调用了Java中的getTime 方法,通过C方法打印出上层调用得到的时间,并且上层成功吐司出调用信息出来。


 



2、点击 “C调用java非静态方法”按钮

 

C成功调用了sayHello 方法, 并成功接收到 C 传递的参数,和 吐司出相对应的信息

 



 

4、C调用Java注意点

       a) C 映射java 方法时 对应的签名

getTime = (*jniEnv)->GetStaticMethodID(jniEnv, TestProvider, "getTime","()Ljava/lang/String;");

       故事情节还没发展这么快,下一章才会专门介绍下这个签名的使用

       b)映射方法的时候需要区别静态和非静态GetStaticMethodID,GetMethodID

    c)调用的时候也需要区分CallStaticObjectMethod,CallVoidMethod 而且还需要区分返回值类型

 

 

 

有不理解的兄弟请留言,个人技术有限,有讲错的地方请大牛们指出,讲的不够全面的请多多包涵,谢谢,

 

点击下载源码 C调用Java例子


本文出自 duicky 博客 , 转载请注明出处 http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html


引用自:http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值