昨天学习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++的代码了。
以下我们来看看代码如何编写吧,首先我们在androidproject中创建一个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语言编写后要在project的src文件夹下执行ndk-bulid命令就能够生成一个c语言库,在eclipseproject文件夹中也有显示。

在每次编译之前须要删除obj目录,以清除缓存。

jni对于一些能够非常大的提高java代码的隐秘性,并且使用c语言开发jni程序能够提高效率。

android windows 上JNI编程的更多相关文章

  1. Android studio 下JNI编程实例并生成so库

    Android studio 下JNI编程实例并生成so库 因为公司需要为Android相机做美颜等图像后期处理,需要使用JNI编程,最近学了下JNI,并且在Android Studio下实现了一个小 ...

  2. Android中JNI编程的那些事儿(1)

    转:Android中JNI编程的那些事儿(1)http://mobile.51cto.com/android-267538.htm Android系统不允许一个纯粹使用C/C++的程序出现,它要求必须 ...

  3. 【转】Android JNI编程—JNI基础

    原文网址:http://www.jianshu.com/p/aba734d5b5cd 最近看到了很多关于热补的开源项目——Depoxed(阿里).AnFix(阿里).DynamicAPK(携程)等,它 ...

  4. Android Studio上NDK/JNI开发环境问题

    基础环境: 操作系统 —— Windows 7 Android Studio —— 1.5.1(android-studio-bundle-141.2456560-windows.exe) NDK — ...

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

    主要学习资料:黑马程序员的NDK方法使用(生产类库so)              jni编程指南中文版(已上传至博客园) 博主文章(它使用的是VS和eclipse联合开发):http://www.c ...

  6. JNI编程实现(Windows)

    上一篇介绍了Linux平台的JNI编程方法,Windows平台的JNI本地调用基本类似,区别就是制作的动态库不同,Linux平台是*.so,Windows平台是*.dll.其中,Windows平台的函 ...

  7. Android jni 编程(参数的传递,成员,方法的)相互访问

    package com.test.androidjni; import android.app.Activity; import android.os.Bundle; import android.u ...

  8. 开始在Windows上开发Android

    介绍 鉴于您正在阅读这篇文章,您很可能已经知道android是什么了.可能.在科幻小说和电影中,机器人本质上是具有拟人化特征的机器人.还记得<星球大战>里的C-3PO吗?那<星际迷航 ...

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

    原文网址:http://blog.csdn.net/linweig/article/details/5203716 本篇将介绍在JNI编程中如何传递参数和返回值. 首先要强调的是,native方法不但 ...

随机推荐

  1. Flexigrid去掉列选择

    Flexigrid中会出现列选择的小黑箭头,有时挺讨厌,想去掉.发现没有控制的地方,于是自己加. 在flexigrid.js中增加 在定义中增加 p = $.extend({ //apply defa ...

  2. TTL 超时问题

    在TCP/IP网络中,网络层并不对数据包进行可靠性传输保证,只通过ICMP报文提供反馈机制(例如:差错控制).PING命令就是ICMP的请求/响应报文,也是网络最常用的测试手段.通常使用PING命令测 ...

  3. hdu 4090 GemAnd Prince

    题目大意: 别人说是消消看,至于你玩没玩过.反正我是没玩过的. 就是选择一个钻石,可以消除与它相连的所有钻石.并获得 消除数量*消除数量  的分 思路: 直接暴搜,然后用一个cnt数组表示每一种钻石剩 ...

  4. Swift - 高级运算符介绍

    除了基本运算符之外,Swift还支持位运算和位移运算,包括:   1,按位取反运算:操作符是 ~ 2,按位与运算:操作符是 & 3,按位或运算:操作符是 | 4,按位异或运算:操作符是 ^ 5 ...

  5. 在Delphi中使用C++对象(两种方法,但都要改造C++提供的DLL)

    Delphi是市场上最好的RAD工具,但是现在C++占据着主导地位,有时针对一个问题很难找到Delphi或Pascal的解决方案.可是却可能找到了一个相关的C++类.本文描述几种在Delphi代码中使 ...

  6. Jquery事件的连接

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  7. 二、Cocos2dx概念介绍(游戏开发中不同的坐标系,cocos2dx锚点)

    注:ccp是cocos2dx中的一个宏定义,#define ccp(__X__,__Y__)CCPointMake((float)__X__, (float)__Y__),在此文章中表示坐标信息 1. ...

  8. 北京哪儿有卖tods豆豆鞋的?在线等答案、、、、(类似动物园、西单等地)_百度知道

    北京哪儿有卖tods豆豆鞋的?在线等答案....(类似动物园.西单等地)_百度知道 北京哪儿有卖tods豆豆鞋的?在线等答案....(类似动物园.西单等地)

  9. Eclipse下Android编程代码自动提示

    在用Eclipse进行Android编程,为了代码自动提示,需要进行如下操作: 1.设置 java 文件的代码提示功能 打 开 Eclipse 依次选择 Window > Preferences ...

  10. Nginx 负载均衡-加权轮询策略剖析

    本文介绍的是客户端请求在多个后端服务器之间的均衡,注意与客户端请求在多个nginx进程之间的均衡相区别(Nginx根据每个工作进程的当前压力调整它们获取监听套接口的几率,那些当前比较空闲的工作进程有更 ...