JNI开发基础篇:Java类调用C库或者方法
来源:互联网 发布:access2007数据库教程 编辑:程序博客网 时间:2024/05/18 06:43
Maybe i walk slowly,but i will never give up
创建新的工程
在JNI开发中与C语言的结合,所以我们在创建新的项目的时候,建议添加C库的支持。(因为会有代码自动提示)如下:
勾选 Include C++ Support
然后一路next。在于平常创建项目中不同的是最后会有一个这样的选择:
下面的两个框可选可不选。
Exceptions Support(异常报错)
Runtime Type Information Support(运行支持)
创建完的工程如下:
附:在这里说一下不同的开发环境所遇到不同的问题。AS:2.2.2 或者更高ndk:version 16.0sdk:该版本下创建的工程,项目中会自动帮我们生成cpp文件夹,并且在项目中的`build.gradle`中默认配置Cmark。
like this:android { ··· defaultConfig { ··· externalNativeBuild { cmake { cppFlags "" } } } externalNativeBuild { cmake { path "CMakeLists.txt" } }}
并且生成一个默认的文件`CMakeLists.txt`
like this:文件中前面有 `#`的均是说明信息,我直接在这里删掉了cmake_minimum_required(VERSION 3.4.1)add_library( native-lib #指定生成os文件的名称,但是注意,在androidstudio中生 #成的os文件会在指定名前面添加 lib 关键词,所以我们平常 #看到的os文件都是类似`libxxxxxx.os` src/main/cpp/native-lib.cpp #项目中C/C++的源代码位置,如果有多个,可以接着写下去 #eg:src/main/jni/test.c #eg: src/main/jni/JNI.c )find_library( log-lib log )target_link_libraries( # Specifies the target library. # 指定目标library # 解释说明我们可以自定多个library。 native-lib # Links the target library to the log library # included in the NDK. ${log-lib} )
这就是我目前相应版本下创建项目中的内容。之前的1.xx版本是没有这些自动生成文件,是需要自己在`build.gradle`中自己配置脚本like this:
//配置ndk ndk{ moduleName "native-lib"//os文件名称 abiFilters "arm64-v8a","x86","x86_64" //支持CPU,默认会生成目前android手机所有可能的CPU ldLibs "log" //支持log输出 }
正题:
Java 类 调用 C 方法、函数
1:创建一个java类:
package com.wedfrend.jni;public class JNI { /** * 调用C语言中的加法运算 * @return */ public native int add(); /** * 检查密码是否正确 * @param pwd * @return 正确,返回200 错误返回500 */ public native int CheckPassWord(String pwd);}
这里所有的java方法,必须使用nativie关键字。
2:创建c中的方法。
2.1:直接在java的方法中,选中方法,按住alt+enter按钮。根据提示生成
这样生成的方法在另外一个文件中会生成如下的方法:
/**1:这个方法便是JIN调用的时候,在C语言中应该声明的方法2:JNIEXPORT ---> 自动生成,可删除3:jint ----> 经过JNI协议规定,返回值。等值于 java中的int4:JNICALL ----> 可删除5:Java_ ----> JNI协议,必须添加6:com_wedfrend_jni_ ---> 所在类的包名,java中的 . 变化为 _7: INI_ --->类名8:add ---> 方法名9: (JNIEnv *env, jobject instance) 两个固定参数,*env JNI中与c之间调用的主要二级指针。 instance 上下文参数*/JNIEXPORT jint JNICALLJava_com_wedfrend_jni_JNI_add(JNIEnv *env, jobject instance) { // TODO}
2.2:自己知道上面的书写方式,自己写。2.3:使用如下方法。
2.3.1cmd --》进入到项目中的java文件夹下,调用javah com.wedfrend.jni.JNIF:\ASTestApplication\JNIApplications\app\src\main\java>javah com.wedfrend.jni.JNI错错误误: 编编码码GBK的的不不可可映映射射字字符符错错误误: 编编码码GBK的的不不可可映映射射字字符符错错误误: 编编码码GBK的的不不可可映映射射字字符符编码错误是因为我们使用了中文,不过没什么影响。如果使用英文写注释,则不会出现这种错误了。这样会生成一个.h文件,如图:
打开如下:
/* DO NOT EDIT THIS FILE - it is machine generated */#include <jni.h>/* Header for class com_wedfrend_jni_JNI */#ifndef _Included_com_wedfrend_jni_JNI#define _Included_com_wedfrend_jni_JNI#ifdef __cplusplusextern "C" {#endif/* * Class: com_wedfrend_jni_JNI * Method: add * Signature: ()I */JNIEXPORT jint JNICALL Java_com_wedfrend_jni_JNI_add (JNIEnv *, jobject);/* * Class: com_wedfrend_jni_JNI * Method: CheckPassWord * Signature: (Ljava/lang/String;)I */JNIEXPORT jint JNICALL Java_com_wedfrend_jni_JNI_CheckPassWord (JNIEnv *, jobject, jstring);#ifdef __cplusplus}#endif#endif
说明:JNIEXPORT jint JNICALL Java_com_wedfrend_jni_JNI_CheckPassWord (JNIEnv *, jobject, jstring); 和上面的解释一样,之所以多了个参数,那是因为我们java方法中带参
不过这样的生成是没有参数值,只有参数类型,需要自己添加
2.3.2
debug处,使用cmd进入到该文件目录下,执行
javah com.wedfrend.jni.JNI
同样会生成一个头文件。
以上3中方法便是如何生成JNI下的.h方法
step3:在项目中创建一个jni文件夹,与java同等级的jni文件夹,并将.h文件拖入jni问价夹中
step4: 在jni中创建一个c源文件,然后引入头文件
此时你在打开 java类的时候,不会报错,反而会出现
按钮,点击之后便可以直接跳转到头文件中。
step5:在C中实现方法功能。
#include <string>#include "com_wedfrend_jni_JNI.h"/**下面的是引入打印模式,在c语言中可以执行输出内容*/#include "android/log.h"#define LOG_TAG "com.wedfrend.cNative"#define LOGD(...)__android_log_print(ANDROID_LOG_DEBUG,LOG_TAG,__VA_ARGS__)#define LOGI(...)__android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)#define LOGE(...)__android_log_print(ANDROID_LOG_ERROR,LOG_TAG,__VA_ARGS__)/** * 两个数相加 */JNIEXPORT jint JNICALL Java_com_wedfrend_jni_JNI_add (JNIEnv * env, jobject jobj){ int a = 10; int b = 5l; return a+b;};/** * 验证密码是否正确 */JNIEXPORT jint JNICALL Java_com_wedfrend_jni_JNI_CheckPassWord (JNIEnv * env, jobject instance, jstring jstr){ /*讲一个字符串转化为char指针*/ //const char *userPsw = env->GetStringUTFChars(jstr, 0); const char *userPsw = (*env)->GetStringUTFChars(env,jstr,0); char* basePsw = "123456"; LOGD("userPsw---------%d\n",*userPsw); /** *strcmp string库中提供比较两个字符串相等的方法。 *返回一个int类型值,这边很有意思的。 */ if(strcmp(userPsw,basePsw)==0){ return 200; }else{ return 500; }};
6:activity或者class中直接调用C语言中的方法:
6.1
TextView tv = (TextView) findViewById(R.id.sample_text);/*实例化你的native类,并且需要在该类中添加动态加载库的方法 { System.loadLibrary("native"); }*/ tv.setText(new JNI().CheckPassWord("123456")+"");
6.2在JNI类中动态加载库,如下:
package com.wedfrend.jni;public class JNI { { System.loadLibrary("native-lib"); } /** * 调用C语言中的加法运算 * @return */ public native int add(); /** * 检查密码是否正确 * @param pwd * @return 正确,返回200 错误返回500 */ public native int CheckPassWord(String pwd); public native String getName(String name);}
7:运行结果展示:
/*
打印输出功能查看:
12-18 15:34:42.229 7964-7964/com.wedfrend D/com.wedfrend.cNative: userPsw———123456
12-18 15:34:42.239 7964-7964/com.wedfrend D/SecWifiDisplayUtil: Metadata value : SecSettings2
*/
生成的os文件:
JNI开发基础篇:C语言调用Java中的方法
- JNI开发基础篇:Java类调用C库或者方法
- JNI开发基础篇:C语言调用Java中的方法
- Java 调用C 或者其他语言的方法-JNI
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- Android-NDK开发之基础--Android JNI实例代码(一)-- 在JNI中执行Java方法--C/C++调用Java
- JNI:JAVA调用C库方法
- jni 开发 c调用java
- jni - c 调用java方法
- Android JNI开发之c语言调用java方法
- 0072 JAVA JNI 如何调用C或者C++生成的dll【基础】
- Java 通过JNI调用C或者CPP代码
- Java 通过JNI调用C或者CPP代码
- JNI中C/C++调用JAVA类的方法
- java 调用本地C/C++方法:jni
- JNI中C调用Java方法
- JNI中C调用Java方法
- JNI中C调用Java方法
- Java API源码阅读邀请
- bzoj1270: [BeijingWc2008]雷涛的小猫
- kafka等,今天面试了
- (css3常用动画的实现
- 总结 2017-12-15
- JNI开发基础篇:Java类调用C库或者方法
- FFmpeg && nginx (centos 7)
- Android自动化测试【初级篇】-- Monkey测试
- Notepad++格式化代码插件
- angularjs自定义验证的实现
- hdu 4417
- Linux环境redis的下载安装部署过程
- vue+vuex+axios做登录、注册页权限等
- 软考常考知识点整理-项目生命周期、信息系统生命周期与产品生命周期