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方法可能会出现的异常, ...
随机推荐
- CPU 内存 硬盘的区别
第一点:CPU 是处理器,内存和硬盘是存储器,受CPU 的控制. 第二点:由于内存的速度很快,在电脑运行的过程中,CPU通常只与内存交换数据,但内存断电数据就会全部丢失,因此电脑使用硬盘作为主要的存 ...
- ASP.NET Core 依赖注入(构造函数注入,属性注入等)
原文:ASP.NET Core 依赖注入(构造函数注入,属性注入等) 如果你不熟悉ASP.NET Core依赖注入,先阅读文章: 在ASP.NET Core中使用依赖注入 构造函数注入 构造函数注 ...
- flask生成环境不要使用其自身低性能的服务器
flask自带一个服务器,主要用在开发环境.默认情况下一次只能处理一个请求,当然你也可以设置为多进程或者多线程的情况. 但是其自带服务器的处理能力比较有限.生成环境下应该使用其他的服务器,参照:htt ...
- centos 7 卸載 mysql
跟網上文章,安裝了一個mysqlwget http://repo.mysql.com/mysql-community-release-el7-5.noarch.rpm 記下卸載過程: 首先执行查看命令 ...
- 《C++ Primer Plus》学习笔记9
<C++ Primer Plus>学习笔记9 第15章 友元.异常和其他 <<<<<<<<<<<<<<& ...
- docker on UP Board
前言 原创文章,转载引用务必注明链接.水平有限,如有疏漏,欢迎指正. 本文使用Markdown写成,为获得更好的阅读体验和正常的图片.链接,请访问我的博客: http://www.cnblogs.co ...
- iPhone 适配之路
(1)1x时代 2007年,初代iPhone公布,屏幕的宽高是320*480像素.这个分辨率一直到iPhone3GS也保持不变. 那时编写iOS的App应用程序.仅仅支持绝对定位. 比方一个butto ...
- 使用 C# 开发智能手机软件:推箱子(四)
这是"使用 C# 开发智能手机软件:推箱子"系列文章的第四篇. 在这篇文章中,介绍 Common/FindPath.cs 源程序文件. using System; using Sy ...
- Android Webview的测试
1.查看当前的所有窗口: Set contexts= driver.getContextHandles(); System.out.println(contexts); 打印出当前所有的窗口 Set& ...
- Django之cookie 和 session
一. 1.cookie的由来!!! 由于HTTP协议是无状态的,既每一次的请求都是独立的,他不会因为你之前来过,就记住你,所以每次浏览器去访问服务器的时候,都是一个全新的过程,之前的数据也不会保留,所 ...