android windows 上JNI编程

昨天学习windows上的JNI编程,JNI说白了就是java和c语言的一个互相沟通的桥梁,java可以调用JNI来完成调用C语言实现的方法。JNI的全称是(Java native interface),其实在编程重你只需要将与java交互的函数写出来,其他的C语言内部调用的就可以直接使用C语言相关语法了。闲话少说,开始正题吧。

要想在windroid或者是linux上使用JNI必须要下载NDK的并且指定路径,在windows我们还需要安装一个sygwin,这里我就不再说怎样安装cygwin了,在你安装好的cygwin文件夹中找到一个etc的文件夹,在这个文件中找到一个profile文件,修改其中的Path后加上:(ndk的路径),在我理解ndk就是构建出了一个重pc到android的一个交叉编译环境,当然它里面还有很多我不知道的,还有待探索。然后我们就可以开始使用了,当然你要是用eclipse写C/C++还需要安装cdt插件。安装过后就可以使用eclipse编写c/c++的代码了。

下面我们来看看代码怎样编写吧,首先我们在android工程中创建一个jni的文件夹,在jni的文件夹中创建c语言的源文件,在android中穿件一个类,类中可以使用native标识创建函数例如下面:

public class DataProvider {

//带参数的c语言调用java语言

public int add2( int x, int y){

return x + y;

}

//无参数的函数C语言调用java语言

public void show(){

System.out.println( "我被调用了啊" );

}

//无参数的静态函数C语言调用java语言

public static void show2(){

System.out.println( "我又被调用了啊" );

}

//将函数使用native标识,可以自动生成相应的函数

public native int add(int x, int y);

public native int sayHello( String hello );

public native int[] array(int[] arr);

public native int callbackadd2();

public native void callbackshow();

public native static void callbackshow2();

public native void callbackshow3();

}

将这个类写好了就可以使用javah (类的全类名), 全类名是指包名+类名,例如com.example.testjni.DataProvider,这样就可以生成一个c语言中使用的头文件例如:

/* DO NOT EDIT THIS FILE - it is machine generated */

#include <jni.h>

/* Header for class com_example_testjni_DataProvider */

#ifndef _Included_com_example_testjni_DataProvider

#define _Included_com_example_testjni_DataProvider

#ifdef __cplusplus

extern "C" {

#endif

/*

* Class:     com_example_testjni_DataProvider

* Method:    add

* Signature: (II)I

*/

JNIEXPORT jint JNICALL Java_com_example_testjni_DataProvider_add

(JNIEnv *, jobject, jint, jint);

/*

* Class:     com_example_testjni_DataProvider

* Method:    sayHello

* Signature: (Ljava/lang/String;)I

*/

JNIEXPORT jint JNICALL Java_com_example_testjni_DataProvider_sayHello

(JNIEnv *, jobject, jstring);

/*

* Class:     com_example_testjni_DataProvider

* Method:    array

* Signature: ([I)[I

*/

JNIEXPORT jintArray JNICALL Java_com_example_testjni_DataProvider_array

(JNIEnv *, jobject, jintArray);

/*

* Class:     com_example_testjni_DataProvider

* Method:    callbackadd2

* Signature: ()I

*/

JNIEXPORT jint JNICALL Java_com_example_testjni_DataProvider_callbackadd2

(JNIEnv *, jobject);

/*

* Class:     com_example_testjni_DataProvider

* Method:    callbackshow

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_example_testjni_DataProvider_callbackshow

(JNIEnv *, jobject);

/*

* Class:     com_example_testjni_DataProvider

* Method:    callbackshow2

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_example_testjni_DataProvider_callbackshow2

(JNIEnv *env, jclass);

/*

* Class:     com_example_testjni_DataProvider

* Method:    callbackshow3

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_example_testjni_DataProvider_callbackshow3

(JNIEnv *, jobject);

#ifdef __cplusplus

}

#endif

#endif

这些都是使用javah后自动生成的。下一步我将该在c语言中是实现这些函数了,在此之前还需要创建一个mk文件,这个文件就是makefile,C语言在编译成库的情况下就可以读取makefile来编译。

mk文件:

LOCAL_PATH := $(call my-dir)

include $(CLEAR_VARS)

#对应的c语言的函数库

LOCAL_MODULE    := hello

#对应c代码的文件

LOCAL_SRC_FILES := hello.c functions.c

LOCAL_LDLIBS := -llog//使用本地库

include $(BUILD_SHARED_LIBRARY)

#include <stdio.h>

#include "com_example_testjni_DataProvider.h" //引用头文件

#include <android/log.h> //打印的日志

const char *TAG = "clog";

#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, TAG, __VA_ARGS__ );

#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, TAG, __VA_ARGS__ );

//使用log头文件中的函数打印日志到eclipse中的logcat,在这里需要在mk文件中添加库引用,LOCAL_LDLIBS += -llog

JNIEXPORT jint JNICALL Java_com_example_testjni_DataProvider_add

(JNIEnv *env, jobject o, jint x, jint y)

{

LOGI("%d\n", x );

LOGD("%d\n", y );

return x + y; //直接返回就可以

}

//int print(jintArray localarray, int i);

int print( int* localarray, int i )

{

LOGD( "array = %d\n", *(localarray+i));

return 0;

}//平常的c语言代码,可以直接调用

/*

* Class:     com_example_testjni_DataProvider

* Method:    sayHello

* Signature: (Ljava/lang/String;)I

*/

JNIEXPORT jint JNICALL Java_com_example_testjni_DataProvider_sayHello

(JNIEnv *env, jobject o, jstring hello)

{

}

/*

* Class:     com_example_testjni_DataProvider

* Method:    array

* Signature: ([I)[I

*/

JNIEXPORT jintArray JNICALL Java_com_example_testjni_DataProvider_array

(JNIEnv *env, jobject obj, jintArray array )//传的是一个java中int型数组,java调用c语言

{

//获得数组长度

int length = (*env)->GetArrayLength(env, array);

int i;

jint* localarray = (*env)->GetIntArrayElements(env, array, 0);

for( i = 0; i < length; i++ ){

*(localarray+i) += 5;

print( localarray, i );

}

return array;

}

/*

* Class:     com_example_testjni_DataProvider

* Method:    callbackadd2

* Signature: ()I

*/

JNIEXPORT jint JNICALL Java_com_example_testjni_DataProvider_callbackadd2

(JNIEnv *env, jobject obj)

{

jclass clazz = (*env)->FindClass(env, "com/example/testjni/DataProvider");

jmethodID mid = (*env)->GetMethodID(env, clazz, "add2", "(II)I");

return (*env)->CallIntMethod(env, obj, mid, 3, 5);

}

/*

* Class:     com_example_testjni_DataProvider

* Method:    callbackshow

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_example_testjni_DataProvider_callbackshow

(JNIEnv *env, jobject obj)

{

jclass clazz = (*env)->FindClass(env, "com/example/testjni/DataProvider");

jmethodID mid = (*env)->GetMethodID(env, clazz, "show", "()V");//

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

}

/*

* Class:     com_example_testjni_DataProvider

* Method:    callbackshow2

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_example_testjni_DataProvider_callbackshow2

(JNIEnv *env, jclass jc)

{

jmethodID mid = (*env)->GetStaticMethodID(env, jc, "show2", "()V");

jobject obj =  (*env)->CallStaticObjectMethod(env, jc, mid);

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

}

/*

* Class:     com_example_testjni_DataProvider

* Method:    callbackshow3

* Signature: ()V

*/

JNIEXPORT void JNICALL Java_com_example_testjni_DataProvider_callbackshow3

(JNIEnv *env, jobject obj)

{

jclass clazz = (*env)->FindClass(env, "com/example/testjni/DataProvider");

jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "show2", "()V");

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

}

java调用C语言将java传过来的值,使用jni的方法进行处理,然后使用,返回,c语言调用java需要在C语言代码中进行映射,例如:

JNIEXPORT void JNICALL Java_com_example_testjni_DataProvider_callbackshow3

(JNIEnv *env, jobject obj)

{

jclass clazz = (*env)->FindClass(env, "com/example/testjni/DataProvider");//得到类的字节码

jmethodID mid = (*env)->GetStaticMethodID(env, clazz, "show2", "()V");//得到函数的id

(*env)->CallVoidMethod(env, obj, mid);//执行函数

}

执行函数有不同的call函数,例如返回值是int是CallIntMethod(env, obj, mid, 3, 5);空类型是CallVoidMethod(env, obj, mid);后面的()V是函数签名,代表是返回值是void型,无参的函数。(II)I返回值是int型参数是两个int值得函数。c语言编写后要在工程的src目录下运行ndk-bulid命令就可以生成一个c语言库,在eclipse工程目录中也有显示。

在每次编译之前需要删除obj文件夹,以清除缓存。

jni对于一些可以很大的提高java代码的隐秘性,而且使用c语言开发jni程序可以提高效率。

时间: 2024-07-29 23:37:27

android windows 上JNI编程的相关文章

android学习之jni编程初探

使"java+c"的开发方式成为了官方支持的开发方式,NDK的本质就是为了让Android应用程序能方便的使用JNI技术而提供的一套工具集合,使用NDK主要是4大好处,第一个,代码的保护,,由于apk的java层代码很容易被反编译,而c/c++反汇编难度较大:第二个,可以很方便的使用开源库,因为很多的现存的开源库都是c/c++代码编写的:第三个,提高程序的执行效率,第四个,便于移植,使用c/c++写的库可以方便在其它的嵌入式平台上使用.这里还有一个问题就是如果在模拟器上运行的话,我们只

Android 简单的JNI编程

1.先是编写包含 native 方法的类库 package com.miles.libs; public class Hello { // 加载本地库 static { System.loadLibrary("Hello"); } // 本地库中的方法 public native String hello(); } 2.用javah生成 c/c++ 头文件 javah -classpath 编译目录 类名 javah -classpath ./bin/classes com.miles

【转】Android JNI编程—JNI基础

原文网址:http://www.jianshu.com/p/aba734d5b5cd 最近看到了很多关于热补的开源项目——Depoxed(阿里).AnFix(阿里).DynamicAPK(携程)等,它们都用到了JNI编程,并且JNI编程也贯穿了Android系统,学会JNI编程对于我们学习研究Android源码.Android安全以及Android安全加固等都是有所帮助的.但是对于我们这些写Android应用的,大部分时间都是在使用Java编程,很少使用C/C++编程,对于JNI编程也了解的比较

Android JNI编程—JNI基础

什么是JNI,怎么使用 JNI--Java Native Interface,它是Java平台的一个特性(并不是Android系统特有的).其实主要是定义了一些JNI函数,让开发者可以通过调用这些函数实现Java代码调用C/C++的代码,C/C++的代码也可以调用Java的代码,这样就可以发挥各个语言的特点了.那么怎么使用JNI呢,一般情况下我们首先是将写好的C/C++代码编译成对应平台的动态库(windows一般是dll文件,linux一般是so文件等),这里我们是针对Android平台,所以

android开发教程(4)— jni编程之采用 javah 从java调用C++

用Java调用C/C++代码 当无法用 Java 语言编写整个应用程序时,JNI 允许您使用本机代码.在下列典型情况下,您可能决定使用本机代码: 希望用更低级.更快的编程语言去实现对时间有严格要求的代码. 希望从 Java 程序访问旧代码或代码库. 需要标准 Java 类库中不支持的依赖于平台的特性. 须知:SWIG和javah的区别(强烈推荐) 我看了网上的关于 jni编程 的教程很多,但不尽相同,刚开始会犯迷糊.我想笔者往往忽略了一个关键点,那就是采用了什么方式决定了步骤的流程.有两种生成

Android jni 编程3(对基本类型一维整型数组的操作)总结版

主要学习资料:黑马程序员的NDK方法使用(生产类库so)              jni编程指南中文版(已上传至博客园) 博主文章(它使用的是VS和eclipse联合开发):http://www.cnblogs.com/activity-life/p/3643047.html //0.传入一维整型数组,无返回值(但已对数组进行了修改) public native void arrayEncode(int[] arr); //1.传入一维整型数组,数组长度(因为c不容易获取而Java方便),返回

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

记一次在Windows上搭建React Native Android环境踩过的坑

要说最近技术圈什么比较活跃,我想除了动态加载框架和热修复技术之外,非Facebook的React Native莫属了吧,其实RN对IOS的支持比较早,但是Android似乎难产了,直到9月份才刚开源.距离RN开源也有一段时间了,一直没有去学习,今天兴趣来潮,索性学一把吧. 本文假设你的Windows上安装了Android SDK,并配置好了环境变量. 安装Node.js 从官网https://nodejs.org/en/下载Node.js的windows版,也不知道为什么版本迭代这么快,之前安装

【转】android JNI编程 一些技巧(整理)

原文网址:http://blog.csdn.net/linweig/article/details/5203716 本篇将介绍在JNI编程中如何传递参数和返回值. 首先要强调的是,native方法不但可以传递Java的基本类型做参数,还可以传递更复杂的类型,比如String,数组,甚至自定义的类.这一切都可以在jni.h中找到答案. 1. Java基本类型的传递 用过Java的人都知道,Java中的基本类型包括boolean,byte,char,short,int,long,float,doub