android JNI 资料大全

不操千曲而后晓声,观千剑而后识器。这篇文章主要讲述android JNI 资料大全相关的知识,希望能为你提供帮助。
AndroidJNI 通过C++调用JAVA1. JNIEnv对象   
  对于本地函数     JNIEXPORT void JNICALL java_video1_TestNative_sayHello(JNIEnv * env, jobject obj)     {         cout< < "Hello Native Test !"< < endl;       }             JNIEnv类型代表Java环境。
通过这个JNIEnv*指针,就能够对Java端的代码进行操作。如,创建Java类得对象,调用Java对象的方法,获取Java对象的属性等。

      JNIEnv的指针会被JNI传送到本地方法的实现函数中来对Java端的代码进行操作 
            JNIEnv类中的函数:       NewObject/NewString/New< TYPE> Array    :new新对象         Get/Set< TYPE> Field:获取属性         Get/SetStatic< TYPE> Field  :获取静态属性       Call< TYPE> Method/CallStatic< TYPE> Method:调用方法       2. Java数据类型与C/C++数据类型的相应关系 
 能够參考  jni.h  文件:http://home.pacifier.com/~mmead/jni/cs510ajp/jni.h  

android JNI 资料大全

文章图片
Java类型            别名                      C++本地类型        字节(bit)   
boolean            jboolean                        unsigned  char    8,  unsigned   
byte          jbyte               signed  char     8   
char          jchar               unsigned  short     16,  unsigned   
short        jshort                            short             16   
int          jint                                long             32   
long          jlong               __int64          64   
float        jfloat                            float         32   
double        jdouble               double             64   
void                  void                                      n/a 
android JNI 资料大全

文章图片
Object                _jobject                        *jobject    

 
  3. 获取jclass 
    为了可以在C/C++使用Java类。jni.h头文件里专门定义了jclass类型来表示Java中的Class类     jclass的取得:     JNIEnv类中有例如以下几个简单的函数能够取得jclass     jclass FindClass(const char* clsName)   依据类名来查找一个类,完整类名。     jclass GetObjectClass(jobject obj)   依据一个对象,获取该对象的类     jclass GetSuperClass(jclass obj)     获取一个类的父类           FindClass 会在classpath系统环境变量下寻找类,须要传入完整的类名,注意包与包之间是用"/"而不是"."来切割 如:jclass cls_string= env-> FindClass("java/lang/String");   获取jclass又什么用,比方你要调用类的静态方法,静态属性就须要通过这种方法来获取一个类。

 
  4. 本地代码訪问Java类中的属性与方法   
  有了类和对象之后。怎样才干訪问java中的对象的属性和方法呢,这就须要用到下面这些方法了。   JNI在jni.h头文件里定义了jfieldID。jmethodID类表示Java端的属性和方法 怎样获取属性: 在訪问或设置Java属性的时候,首先就要如今本地代码中取得代表Java属性的jfieldID。然后才干在本地代码中进行Java属性操作。 怎样调用java的方法:调用Java端的方法时,须要取得代表方法的jmethodID才干进行Java方法调用   JNIEnv获取对应的fieldID和jmethodID的方法:     GetFieldID/GetMethodID     GetStaticFieldID/GetStaticMethodID     GetMethodID也能够取得构造函数的jmethodID。
创建Java对象时调用指定的构造函数。
    如:env-> GetMethodID(data_Clazz,"method_name","()V")     (*jniEnv)-> GetMethodID(jniEnv, Clazz,"< init> ", "()V");       这个比較特殊。这个是默认构造函数的方法,一般用这个来初始化对象,可是再实际过程中,为了高速生成一个实例,一般通过工厂方法类创建jobject           jni.h 对GetMethodID的定义:     jmethodID (JNICALL *GetMethodID)       (JNIEnv *env, jclass clazz, const char *name, const char *sig);             这就引入了一个新的问题。什么是sig,我们后面再说。举个样例说明     前提说明: JAVA类  TestProvider  ,该类有2个方法分别为String getTime( )  ,  void saysayHello( String str)       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");
              //通过NewObject来创建对象
              jobject  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)         5. sign签名     对于  jmethodID GetMethodID(jclass clazz, const char *name, const char *sign)       clazz代表该属性所在的类,name表示方法名称,sign是签名     那什么是签名。签名是对函数參数和返回值的描写叙述,对同一个函数。在java中同意重载。这个时候就须要这个sign来进行区分了。     下面是java类型签名的描写叙述       用来表示要取得的属性/方法的类型    
android JNI 资料大全

文章图片
类型           对应的签名   
boolean                Z   
byte            B   
char            C   
short          S   
int            I   
long            J   
float          F   
double          D   
void            V   
object          L用/分隔包的完整类名:      Ljava/lang/String;  
Array           [签名                    [I            [Ljava/lang/Object;    
Method                  (參数1类型签名  參数2类型签名···)返回值类型签名  
android JNI 资料大全

文章图片


  特别注意:Object后面一定有分号(。)结束的,多个对象參数中间也用分号(; )来分隔 
  样例: 方法签名void  f1()                         ()V
int  f2(int,  long)                 (IJ)I
boolean  f3(int[])                 ([I)B
double  f4(String,  int)             (Ljava/lang/String; I)D
void  f5(int,  String  [],  char)        (I[Ljava/lang/String; C)V      图解签名:
android JNI 资料大全

文章图片
 
 
  使用javap命令来产生签名         javap -s -p [full class Name]       -s 表示输出签名信息       -p 同-private,输出包含private訪问权限的成员信息       样例:
android JNI 资料大全

文章图片
  C:\\E\\java\\workspaces\\myeclipseblue\\JNITest\\bin> javap  -s  -private  video1.TestNative   
Compiled  from  "TestNative.java"   
public  class  video1.TestNative  extends  java.lang.Object{   
public  java.lang.String  name;    
    Signature:  Ljava/lang/String;    
public  video1.TestNative();    
    Signature:  ()V   
public  int  signTest(int,  java.util.Date,  int[]);    
    Signature:  (ILjava/util/Date; [I)I   
public  native  void  sayHello();    
    Signature:  ()V   
public  static  void  main(java.lang.String[]);    
    Signature:  ([Ljava/lang/String; )V   
}    
android JNI 资料大全

文章图片
    TestNative完整代码:
 
android JNI 资料大全

文章图片
package  video1;    
import  java.util.Date;    
public  class  TestNative  {   
        public  String  name="Test";    
        public  int  number  =100;    
        public  int  signTest(int  i,Date  date,int[]  arr){   
                System.out.println("Sign  Test");    
                return  0;    
        }   
        //nativekeyword修饰的方法,其内容是C/C++编写的,java中不必为它编写详细的实现   
        public  native  void  sayHello();    
        public  static  void  main(String[]  args)  {   
                System.loadLibrary("NativeCode");    
                TestNative  tn  =  new  TestNative();    
                tn.sayHello();    
        }   
}
android JNI 资料大全

文章图片
    C/C++代码
 
 
android JNI 资料大全

文章图片
#include  "video1_TestNative.h"   
#include  < iostream>    
using  namespace  std;    
JNIEXPORT  void  JNICALL  Java_video1_TestNative_sayHello(JNIEnv  *  env,  jobject  obj){   
        cout< < "Hello  Native  Test  !"< < endl;    
        //由于test不是静态函数,所以传进来的就是调用这个函数的对象   
        //否则就传入一个jclass对象表示native()方法所在的类   
        jclass  native_clazz  =  env-> GetObjectClass(obj);    
   
        //得到jfieldID   
        jfieldID  fieldID_prop  =  env-> GetFieldID(native_clazz,"name","Ljava/lang/String; ");    
        jfieldID  fieldID_num  =  env-> GetFieldID(native_clazz,"number","I");    
   
        //得到jmethodID   
        jmethodID  methodID_func=env-> GetMethodID(native_clazz,"signTest","(ILjava/util/Date; [I)I");    
        //调用signTest方法   
        env-> CallIntMethod(obj,methodID_func,1L,NULL,NULL);    
   
        //得到name属性   
        jobject  name  =  env-> GetObjectField(obj,fieldID_name);    
        //得到number属性   
        jint  number=  env-> GetIntField(obj,fieldID_num);      
   
        cout< < number< < endl; //100   
        //改动number属性的值   
        env-> SetIntField(obj,fieldID_num,18880L);        
        number=  env-> GetIntField(obj,fieldID_num);        
        cout< < number< < endl; //18880   
  }  
android JNI 资料大全

文章图片
  本文地址,转载请注明出处:
http://www.cnblogs.com/likwo/archive/2012/05/21/2512400.html 
 
參考资料: http://zzqrj.iteye.com/blog/1285262 
  jni.h 头文件: http://home.pacifier.com/~mmead/jni/cs510ajp/jni.h 
相关样例: 
http://www.pacifier.com/~mmead/jni/cs510ajp/index.html Programmming in C/C++ with the Java Native Interface (3 个练习) http://www.pacifier.com/~mmead/jni/cs510ajp/exercises/index.html 
  JNI 文档: http://files.cnblogs.com/luxiaofeng54/JNI_Docs.rar 
  基于 android NDK 的学习之旅----- C调用Java http://www.cnblogs.com/luxiaofeng54/archive/2011/08/17/2142000.html 
  Linux下JNI的使用:比較基础 http://www.cnblogs.com/bastard/archive/2012/05/17/2506877.html 
  怎样在Android下使用JNI:解说比較具体,可是代码里有些错误,空格没处理好 http://blog.csdn.net/xnwyd/article/details/7086384 这篇文章有些地方不清楚的參考下这篇文章   Android Jni代码演示样例解说 http://developer.51cto.com/art/201001/181355.htm 
JNI callMethod參考文档
 
其它推荐学习站点
 
JNI的提高,Java类型和C(C++)类型转换源码
http://blog.csdn.net/ostrichmyself/article/details/4557851 
 
JNI 的多线程
  http://blog.csdn.net/popop123/article/details/1511180 
 
Android NDK 开发 
 
 
使用 Java Native Interface 的最佳实践:描写叙述了JNI性能和缓存的一些东西 
  https://www.ibm.com/developerworks/cn/java/j-jni/
 
JNI 攻略系列
JNI全攻略之中的一个--建立一个简单的JNI程序 
http://blog.csdn.net/yjkwf/article/details/7006260 
JNI全攻略之二――JNI基础 
http://blog.csdn.net/yjkwf/article/details/7006261 
  JNI全攻略之三--JNI头文件分析
  http://blog.csdn.net/yjkwf/article/details/7006264
  JNI攻略之四――JNI操作数组
http://blog.csdn.net/yjkwf/article/details/7006266 
 
【android JNI 资料大全】http://disanji.net/2011/01/26/android-jni-programming-2/ 
 
  JNI Examples for Android
http://android.wooyd.org/JNIExample/files/JNIExample.pdf 
 
JNI pthread 多线程使用
http://www.cnblogs.com/lknlfy/archive/2012/03/16/2400786.html 
 
 

    推荐阅读