android JNI 资料大全

AndroidJNI 通过C++调用JAVA

1. 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

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  

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类型签名的描写叙述

用来表示要取得的属性/方法的类型

类型           对应的签名

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类型签名···)返回值类型签名

特别注意: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

图解签名:

使用javap命令来产生签名

javap -s -p [full class Name]

-s 表示输出签名信息

-p 同-private,输出包含private訪问权限的成员信息

样例:

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

}

TestNative完整代码:

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();

}

}

C/C++代码

#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

}

本文地址,转载请注明出处:

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

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

时间: 2024-10-06 21:47:43

android JNI 资料大全的相关文章

Android内存优化大全(中)

转载请注明本文出自大苞米的博客(http://blog.csdn.net/a396901990),谢谢支持! 写在最前: 本文的思路主要借鉴了2014年AnDevCon开发者大会的一个演讲PPT,加上把网上搜集的各种内存零散知识点进行汇总.挑选.简化后整理而成. 所以我将本文定义为一个工具类的文章,如果你在ANDROID开发中遇到关于内存问题,或者马上要参加面试,或者就是单纯的学习或复习一下内存相关知识,都欢迎阅读.(本文最后我会尽量列出所参考的文章). OOM: 内存泄露可以引发很多的问题:

【转】android JNI

原文网址:http://jinguo.iteye.com/blog/696185 Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C.C++ 和汇编语言)编写的应用程序和库进行交互操作. 1.从如何载入.so档案谈起 由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Byt

[转载]—— Android JNI知识点

Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C.C++ 和汇编语言)编写的应用程序和库进行交互操作. 1.从如何载入.so档案谈起 由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Bytecode之后,必须靠Dalvik虚拟机(VM: Virtual Machine)

【资源】Android学习资料 - 逆天整理 - 精华无密版

 入门看视频,提高看书籍,飘升做项目.老练研开源,高手读外文,大牛讲低调~  极客学院安卓Android全套最新视频教程[17G全套视频+独家源码] http://pan.baidu.com/s/1kT5nSkn 链接: http://pan.baidu.com/s/1jGsyJ0y 密码: btbg 传智播客Java安卓方向就业班全套视频下载 http://pan.baidu.com/s/1eQq4YXG 链接: http://pan.baidu.com/s/1qWA3yyS 密码: p7qj

Android jni 编程入门

本文将介绍如何使用eclipse和ndk-build来编写一个基于Android4.4版本的包含有.so动态库的安卓程序. 前提是已经安装和配置好了诸如SDK,NDK等编译环境.下面开始编程! 1 程序逻辑 我们要编写的程序包含两部分:java部分--负责界面和调用JNI native函数:JNI native 部分--负责native函数的具体实现(本文使用C语言). native 函数伪代码如下: ? 1 2 3 4 5 6 7 8 /* funtion: 传入两个整形变量,计算他们之和 r

android 布局属性大全---初学者必备

Android功能强大,界面华丽,但是众多的布局属性就害苦了开发者,下面这篇文章结合了网上不少资料,花费本人一个下午搞出来的,希望对其他人有用. 第一类:属性值为true或false android:layout_centerHrizontal 水平居中 android:layout_centerVertical 垂直居中 android:layout_centerInparent 相对于父元素完全居中 android:layout_alignParentBottom 贴紧父元素的下边缘 and

Android JNI知识简介

Java Native Interface (JNI)标准是java平台的一部分,它允许Java代码和其他语言写的代码进行交互.JNI 是本地编程接口,它使得在 Java 虚拟机 (VM) 内部运行的 Java 代码能够与用其它编程语言(如 C.C++ 和汇编语言)编写的应用程序和库进行交互操作. 1.从如何载入.so档案谈起 由于Android的应用层的类都是以Java写的,这些Java类编译为Dex型式的Bytecode之后,必须靠Dalvik虚拟机(VM: Virtual Machine)

超全Android JNI&NDK编程总结

由于网上关于JNI/NDK相关的知识点介绍的比较零散而且不具备参照性,所以写了这篇JNI/NDK学习笔记,便于作为随时查阅的工具类型的文章,本文主要的介绍了在平时项目中常用的命令.JNI数据类型.签名等,便于查阅相关资料.文末相关参考资料比较适合刚接触或者不熟悉Android NDK开发的朋友参阅. 常用命令 javac 编译java源文件生成.class文件 由于JNI对应的头文件由javah工具根据对应的.class文件生成,所以在进行JNI编程之前,写好Java代码后需要先编译,在使用ja

Android jni 二维数组 传递

学习Android Jni时,一个二维 整数 数组的传递花了我好长时间,在网上查的资料都不全,当然最后是成功了,写在这里是为了自己记住,当然有人搜索到并利用了我会很高兴. in Android Java file public native boolean  add(int[][] qizidata,.....) 用JDK工具生产jni 的*.h文件 your project path> ..Javajdk1.6.0_10binjavah -classpath ./bin JAVA Class