JNI(Java Native Interface)
一、JNI(Java Native Interface)


- private native String getStringFromC();
3、在jni中创建一个C文件,定义一个函数实现本地方法,函数名必须用使用 本地方法的全类名,点改为下划线。

- 1 #include <stdio.h>
- 2 #include <stdlib.h>
- 3 #include <jni.h>
- 4 //方法名必须为本地方法的全类名点改为下划线,穿入的两个参数必须这样写,
- 5 //第一个参数为Java虚拟机的内存地址的二级指针,用于本地方法与java虚拟机在内存中交互
- 6 //第二个参数为一个java对象,即是哪个对象调用了这个 c方法
- 7 jstring Java_com_mwp_jnihelloworld_MainActivity_getStringFromC(JNIEnv* env,
- 8 jobject obj){
- 9 //定义一个C语言字符串
- 10 char* cstr = "hello form c";
- 11 //返回值是java字符串,所以要将C语言的字符串转换成java的字符串
- 12 //在jni.h 中定义了字符串转换函数的函数指针
- 13 //jstring (*NewStringUTF)(JNIEnv*, const char*);
- 14 //第一种方法:很少用
- 15 jstring jstr1 = (*(*env)).NewStringUTF(env, cstr);
- 16 //第二种方法,推荐
- 17 jstring jstr2 = (*env) -> NewStringUTF(env, cstr);
- 18 return jstr2;
- 19 }

4、在jni中创建 Android.mk文件,用于配置 本地方法

- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- #编译生成的文件的类库叫什么名字
- LOCAL_MODULE := hello
- #要编译的c文件
- LOCAL_SRC_FILES := Hello.c
- include $(BUILD_SHARED_LIBRARY)

5、在jni目录下执行 ndk-build.cmd指令,编译c文件
- static{
- //加载打包完毕的 so类库
- System.loadLibrary("hello");
- }
7、jni打包的C语言类库默认仅支持 arm架构,需要在jni目录下创建 Android.mk 文件添加如下代码可以支持x86架构
- APP_ABI := armeabi armeabi-v7a x86
四、JNI常见错误

- #include <jni.h>
- #include <string.h>
- //将java字符串转换为c语言字符串(工具方法)
- char* Jstring2CStr(JNIEnv* env, jstring jstr)
- {
- char* rtn = NULL;
- jclass clsstring = (*env)->FindClass(env,"java/lang/String");
- jstring strencode = (*env)->NewStringUTF(env,"GB2312");
- jmethodID mid = (*env)->GetMethodID(env,clsstring, "getBytes", "(Ljava/lang/String;)[B");
- jbyteArray barr= (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");
- jsize alen = (*env)->GetArrayLength(env,barr);
- jbyte* ba = (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
- if(alen > 0)
- {
- rtn = (char*)malloc(alen+1); //"\0"
- memcpy(rtn,ba,alen);
- rtn[alen]=0;
- }
- (*env)->ReleaseByteArrayElements(env,barr,ba,0); //
- return rtn;
- }
- JNIEXPORT jstring JNICALL Java_com_mwp_encodeanddecode_MainActivity_encode
- (JNIEnv * env, jobject obj, jstring text, jint length){
- char* cstr = Jstring2CStr(env, text);
- int i;
- for(i = 0;i<length;i++){
- *(cstr+i) += 1; //加密算法,将字符串每个字符加1
- }
- return (*env)->NewStringUTF(env,cstr);
- }
- JNIEXPORT jstring JNICALL Java_com_mwp_encodeanddecode_MainActivity_decode
- (JNIEnv * env, jobject obj, jstring text, jint length){
- char* cstr = Jstring2CStr(env, text);
- int i;
- for(i = 0;i<length;i++){
- *(cstr+i) -= 1;
- }
- return (*env)->NewStringUTF(env, cstr);
- }


- 1 public class MainActivity extends Activity {
- 2
- 3 static{
- 4 System.loadLibrary("encode");
- 5 }
- 6 int[] array = {1,2,3,4,5};
- 7 @Override
- 8 protected void onCreate(Bundle savedInstanceState) {
- 9 super.onCreate(savedInstanceState);
- 10 setContentView(R.layout.activity_main);
- 11 }
- 12
- 13 public void click(View v){
- 14 encodeArray(array);
- 15 //不需要返回值,实际操作的是同一块内存,内容已经发生了改变
- 16 for (int i : array) {
- 17 System.out.println(i);
- 18 }
- 19 }
- 20
- 21 //传递数组其实是传递一个堆内存的数组首地址的引用过去,所以实际操作的是同一块内存,
- 22 //当调用完方法,不需要返回值,实际上参数内容已经改变,
- 23 //Android中很多操作硬件的方法都是这种C语言的传引用的思路,要非常熟练
- 24 private native void encodeArray(int[] arr);
- 25 }


- 1 #include <jni.h>
- 2 /*
- 3 * Class: com_mwp_jniarray_MainActivity
- 4 * Method: encodeArray
- 5 * Signature: ([I)V
- 6 */
- 7 JNIEXPORT void JNICALL Java_com_mwp_jniarray_MainActivity_encodeArray
- 8 (JNIEnv * env, jobject obj, jintArray arr){
- 9 //拿到整型数组的长度以及第0个元素的地址
- 10 //jsize (*GetArrayLength)(JNIEnv*, jarray);
- 11 int length = (*env)->GetArrayLength(env, arr);
- 12 // jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*);
- 13 int* arrp = (*env)->GetIntArrayElements(env, arr, 0);
- 14 int i;
- 15 for(i = 0;i<length;i++){
- 16 *(arrp + i) += 10; //将数组中的每个元素加10
- 17 }
- 18 }


- 1 public class MainActivity extends Activity {
- 2
- 3 static{
- 4 //加载美图秀秀的类库
- 5 System.loadLibrary("mtimage-jni");
- 6 }
- 7 private ImageView iv;
- 8 private Bitmap bitmap;
- 9 @Override
- 10 protected void onCreate(Bundle savedInstanceState) {
- 11 super.onCreate(savedInstanceState);
- 12 setContentView(R.layout.activity_main);
- 13
- 14 iv = (ImageView) findViewById(R.id.iv);
- 15
- 16 bitmap = BitmapFactory.decodeFile("sdcard/aneiyi.jpg");
- 17 iv.setImageBitmap(bitmap);
- 18 }
- 19
- 20 public void click(View v){
- 21
- 22 int width = bitmap.getWidth();
- 23 int height = bitmap.getHeight();
- 24
- 25 //用于保存所有像素信息的数组
- 26 int[] pixels = new int[width*height];
- 27 //获取图片的像素颜色信息,保存至pixels
- 28 bitmap.getPixels(pixels, 0, width, 0, 0, width, height);
- 29
- 30 JNI jni = new JNI();
- 31 //调用美图秀秀本地库中的美图方法,靠猜
- 32 //arg0:保存了所有像素颜色信息的数组
- 33 //arg1:图片的宽
- 34 //arg2:图片的高
- 35 //此方法是通过改变pixels的像素颜色值来实现美化效果,传递一个数组参数是不需要返回值的
- 36 jni.StyleLomoB(pixels, width, height);
- 37
- 38 Bitmap bmNew = Bitmap.createBitmap(pixels, width, height, bitmap.getConfig());
- 39 iv.setImageBitmap(bmNew);
- 40 }
- 41 }


- 1 public class MainActivity extends Activity {
- 2 static{
- 3 System.loadLibrary("hello");
- 4 }
- 5
- 6 @Override
- 7 protected void onCreate(Bundle savedInstanceState) {
- 8 super.onCreate(savedInstanceState);
- 9 setContentView(R.layout.activity_main);
- 10 }
- 11
- 12 public void click(View v){
- 13 cLog();
- 14 }
- 15
- 16 public native void cLog();
- 17
- 18 public void show(String message){
- 19 Builder builder = new Builder(this);
- 20 builder.setTitle("标题");
- 21 builder.setMessage(message);
- 22 builder.show();
- 23 }
- 24
- 25 }


- #include <jni.h>
- #include <android/log.h>
- #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_mwp_ccalljava2_MainActivity_cLog
- (JNIEnv * env, jobject obj){
- //打印log输出
- LOGD("我是C语言打印的debug日志");
- LOGI("我是C语言打印的info日志");
- //通过反射来调用java的方法,需要知道方法签名,使用javap得到方法签名
- //在bin/classes目录下执行 javap -s 全类名
- //1、得到类的字节码对象
- //jclass (*FindClass)(JNIEnv*, const char*);
- jclass clazz = (*env)->FindClass(env, "com/mwp/ccalljava2/MainActivity");
- //jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
- jmethodID methodID = (*env)->GetMethodID(env, clazz, "show", "(Ljava/lang/String;)V");
- //void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
- (*env)->CallVoidMethod(env,obj,methodID, (*env)->NewStringUTF(env, "这是弹窗的内容"));
- }

- LOCAL_PATH := $(call my-dir)
- include $(CLEAR_VARS)
- LOCAL_LDLIBS += -llog
- LOCAL_MODULE := hello
- LOCAL_SRC_FILES := log.c
- include $(BUILD_SHARED_LIBRARY)
十、模拟监测压力传感器

- 1 public class MainActivity extends Activity {
- 2 static{
- 3 System.loadLibrary("monitor");
- 4 }
- 5 private MyProgressBar mpb;
- 6 @Override
- 7 protected void onCreate(Bundle savedInstanceState) {
- 8 super.onCreate(savedInstanceState);
- 9 setContentView(R.layout.activity_main);
- 10
- 11 mpb = (MyProgressBar) findViewById(R.id.mpb);
- 12 mpb.setMax(100);
- 13 }
- 14
- 15 public void start(View v){
- 16 new Thread(){
- 17 public void run() {
- 18 startMonitor();
- 19 };
- 20 }.start();
- 21 }
- 22
- 23 public void stop(View v){
- 24 stopMonitor();
- 25 }
- 26
- 27 public native void startMonitor();
- 28 public native void stopMonitor();
- 29
- 30 //供本地方法调用刷新UI
- 31 public void show(int pressure){
- 32 mpb.setPressure(pressure);
- 33 }
- 34 }


- #include <jni.h>
- #include <stdio.h>
- #include <stdlib.h>
- //模拟压力传感其传递数据
- int getPressure(){
- return rand()%101;
- }
- //用于控制循环的开关
- int monitor;
- JNIEXPORT void JNICALL Java_com_mwp_monitor_MainActivity_startMonitor
- (JNIEnv * env, jobject obj){
- monitor = 1;
- int pressure;
- jclass clazz;
- jmethodID methodid;
- while(monitor){
- //本地方法获取传感器数据
- pressure= getPressure();
- //使用反射调用java方法刷新界面显示
- //jclass (*FindClass)(JNIEnv*, const char*);
- clazz= (*env)->FindClass(env, "com/mwp/monitor/MainActivity");
- //jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);
- methodid= (*env)->GetMethodID(env, clazz, "show","(I)V");
- // void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
- (*env)->CallVoidMethod(env, obj, methodid, pressure);
- sleep(1);
- }
- }
- JNIEXPORT void JNICALL Java_com_mwp_monitor_MainActivity_stopMonitor
- (JNIEnv * env, jobject obj){
- //结束循环
- monitor = 0;
- }


- #include <jni.h>
- #include "com_mwp_cplusplus_MainActivity.h"
- JNIEXPORT jstring JNICALL Java_com_mwp_cplusplus_MainActivity_helloC
- (JNIEnv * env, jobject obj){
- char* cstr = "hello from c";
- //return (*env)->NewStringUTF(env, cstr);
- return env->NewStringUTF(cstr);
- }

JNI(Java Native Interface)的更多相关文章
- 【详解】JNI(Java Native Interface)(一)
前言: 一提到JNI,多数编程者会下意识地感受到一种无法言喻的恐惧.它给人的第一感觉就是"难",因为它不是单纯地在JVM环境内操作Java代码,而是跳出虚拟机与其他编程语言进行交互 ...
- +Java中的native关键字浅析(Java+Native+Interface)++
JNI是Java Native Interface的 缩写.从Java 1.1开始,Java Native Interface (JNI)标准成为java平台的一部分,它允许Java代码和其他语言写的 ...
- 杂项-Maven-jna:JNA(Java Native Access)
ylbtech-杂项-Maven-jna:JNA(Java Native Access) JNA(Java Native Access )提供一组Java工具类用于在运行期间动态访问系统本地库(nat ...
- android 学习随笔二十七(JNI:Java Native Interface,JAVA原生接口 )
JNI(Java Native Interface,JAVA原生接口) 使用JNI可以使Java代码和其他语言写的代码(如C/C++代码)进行交互. 问:为什么要进行交互? 首先,Java语言提供的类 ...
- 【详解】JNI (Java Native Interface) (四)
案例四:回调实例方法与静态方法 描述:此案例将通过Java调用的C语言代码回调Java方法. 要想调用实例对象的方法,需要进行以下步骤: 1. 通过对象实例,获取到对象类的引用 => GetO ...
- 【详解】JNI (Java Native Interface) (三)
案例三:C代码访问Java对象的实例变量 获取对象的实例变量的步骤: 1. 通过GetObjectClass()方法获得此对象的类引用 2. 通过类引用的GetFieldID()方法获得实例变量的 ...
- 【详解】JNI (Java Native Interface) (二)
案例二:传递参数给C代码,并从其获取结果 注:这里传递的参数是基本类型的参数,在C代码中有直接的映射类型. 此案例所有生成的所有文件如下: (1)编写案例二的Java代码,如下: 这里我们定义了一个n ...
- Java Native Interface 基于JNI的嵌入式手机软件开发实例
1.通过JNI和c/c++的库组件.其他代码交互 2.java和c不能互通的原因时数据类型问题 Introduction https://docs.oracle.com/javase/8/docs/t ...
- Java Native Interface 六JNI中的异常
本文是<The Java Native Interface Programmer's Guide and Specification>读书笔记 在这里只讨论调用JNI方法可能会出现的异常, ...
随机推荐
- Go视频教程整理转
Go视频教程整理 [Go Web基础]01博客项目设计 |Go视频教程|Go语言基础 http://www.tudou.com/programs/view/gXZb9tGNsGU/ [Go Web基础 ...
- Ubuntu 16.04安装Jetty Web服务器
一.下载 http://www.eclipse.org/jetty/download.html 二.安装 tar -zxvf jetty-distribution-9.4.7.v20170914.ta ...
- [Testing] Config jest to test Javascript Application -- Part 1
Transpile Modules with Babel in Jest Tests Jest automatically loads and applies our babel configurat ...
- java utf8字符 导出csv 文件的乱码问题。
在输出的格式为UTF-8的格式,但是打开CSV文件一直为乱码,后来参考了这里的代码,搞定了乱码问题,原文请参考:http://hbase.iteye.com/blog/1172200 private ...
- 【转载】分布式系统理论基础 - 一致性、2PC和3PC
引言 狭义的分布式系统指由网络连接的计算机系统,每个节点独立地承担计算或存储任务,节点间通过网络协同工作.广义的分布式系统是一个相对的概念,正如Leslie Lamport所说[1]: What is ...
- 史上最全的CSS hack方式一览 jQuery 图片轮播的代码分离 JQuery中的动画 C#中Trim()、TrimStart()、TrimEnd()的用法 marquee 标签的使用详情 js鼠标事件 js添加遮罩层 页面上通过地址栏传值时出现乱码的两种解决方法 ref和out的区别在c#中 总结
史上最全的CSS hack方式一览 2013年09月28日 15:57:08 阅读数:175473 做前端多年,虽然不是经常需要hack,但是我们经常会遇到各浏览器表现不一致的情况.基于此,某些情况我 ...
- System V IPC相关函数
System V IPC 将一个已保存的路径名和一个整数标识符转换成一个key_t值,称为IPC键key_t:System V IPC(System V消息队列.System V信号量.System ...
- OpenStack源码系列---nova-conductor
nova-conductor启动的也是一个rpc server,代码框架和nova-compute类似,所以我也懒得再详细分析一遍服务启动的过程.nova-api那篇文章的最后我说"cctx ...
- Deep Learning for Robotics 资源汇总
1 前言 在最新Nature的Machine Intelligence 中Lecun.Hinton和Bengio三位大牛的Review文章Deep Learning中.最后谈The Future Of ...
- 命令行添加PATH
如何设置PATH 命令:echo "export PATH=xxxxxx:$PATH" >> ~/.bash_profile 解释:把"export PATH ...