Android Studio 3.0以上版本JNI编程
平时使用JNI比较少,以前有项目在eclipse中使用过,今天尝试在Android studio中使用JNI,记录如下流程,如有不妥,请指正
第一步:打开SDK manager,下载如下几个工具
第二步:创建一个Android项目,在项目中新建一个jni接口的class,如下:
[code]public class StringJni { //加接口 public static native int addParam(int a,int b); //减接口 public static native int pluParam(int a,int b); //乘接口 public static native int multiplicationParam(int a,int b); //字符串拼接接口 public static native String getStringParam(String request); static{ System.loadLibrary("MyStringJni"); } }
如上定义了加载的so文件名称为MyStringJni,并需要调用的native接口
第三步:再Extenal Tools添加javah
settings->Tools->Extenal Tools
name:javah
Program:$JDKPath$\bin\javah.exe
Arguments:-classpath . -jni -d $ModuleFileDir$/src/main/jni $FileClass$
Working directory:$ModuleFileDir$\src\main\Java
第四步:自动生成.h文件
右键刚才新建的jni接口类,选择ExternalTools ->javah,会生成如下.h文件
打开如下:
[code]/* DO NOT EDIT THIS FILE - it is machine generated */ #include <jni.h> /* Header for class com_huiyi_nypos_jniapp_jni_StringJni */ #ifndef _Included_com_huiyi_nypos_jniapp_jni_StringJni #define _Included_com_huiyi_nypos_jniapp_jni_StringJni #ifdef __cplusplus extern "C" { #endif /* * Class: com_huiyi_nypos_jniapp_jni_StringJni * Method: addParam * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_huiyi_nypos_jniapp_jni_StringJni_addParam (JNIEnv *, jclass, jint, jint); /* * Class: com_huiyi_nypos_jniapp_jni_StringJni * Method: pluParam * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_huiyi_nypos_jniapp_jni_StringJni_pluParam (JNIEnv *, jclass, jint, jint); /* * Class: com_huiyi_nypos_jniapp_jni_StringJni * Method: multiplicationParam * Signature: (II)I */ JNIEXPORT jint JNICALL Java_com_huiyi_nypos_jniapp_jni_StringJni_multiplicationParam (JNIEnv *, jclass, jint, jint); /* * Class: com_huiyi_nypos_jniapp_jni_StringJni * Method: getStringParam * Signature: (Ljava/lang/String;)Ljava/lang/String; */ JNIEXPORT jstring JNICALL Java_com_huiyi_nypos_jniapp_jni_StringJni_getStringParam (JNIEnv *, jclass, jstring); #ifdef __cplusplus } #endif #endif
第五步:新建c文件如下:
[code]#include "com_huiyi_nypos_jniapp_jni_StringJni.h" #include "StringUtils.c" #include <string.h> #include <jni.h> #include <malloc.h> JNIEXPORT jint JNICALL Java_com_huiyi_nypos_jniapp_jni_StringJni_addParam (JNIEnv *env, jobject obj, jint a, jint b) { jint c = 0; c = a + b; return c; } JNIEXPORT jint JNICALL Java_com_huiyi_nypos_jniapp_jni_StringJni_pluParam (JNIEnv *env, jobject obj, jint a, jint b) { jint c = 0; if (a > b) { c = a - b; } else { c = b - a; } return c; } JNIEXPORT jint JNICALL Java_com_huiyi_nypos_jniapp_jni_StringJni_multiplicationParam (JNIEnv *env, jobject obj, jint a, jint b) { jint c = 0; c = a * b; return c; } JNIEXPORT jstring JNICALL Java_com_huiyi_nypos_jniapp_jni_StringJni_getStringParam (JNIEnv *env, jobject obj, jstring request) { char *cstr = Jstring2CStr(env, request); char *hellostr = "World"; strcat(cstr, hellostr); //拼接两个字符串 return (*env)->NewStringUTF(env, cstr); }
如下为调用StringUtils.c的代码
[code] #include <jni.h> #include <malloc.h> #include <string.h> #pragma clang diagnostic push #pragma ide diagnostic ignored "err_incomplete_type" 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); 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; } #pragma clang diagnostic pop
第六步:在src目录下新建CMakeLists.txt文件如下:
如下为CMakeLists.txt具体内容:
[code]# For more information about using CMake with Android Studio, read the # documentation: https://d.android.com/studio/projects/add-native-code.html # Sets the minimum version of CMake required to build the native library. #CMakeLists.txt cmake_minimum_required(VERSION 3.4.1) # Creates and names a library, sets it as either STATIC # or SHARED, and provides the relative paths to its source code. # You can define multiple libraries, and CMake builds them for you. # Gradle automatically packages shared libraries with your APK. add_library( # Sets the name of the library. # 设置so文件名称. MyStringJni # Sets the library as a shared library. SHARED # 设置这个so文件为共享. # Provides a relative path to your source file(s). # 设置这个so文件为共享. src/main/jni/getStringJni.c) # Searches for a specified prebuilt library and stores the path as a # variable. Because CMake includes system libraries in the search path by # default, you only need to specify the name of the public NDK library # you want to add. CMake verifies that the library exists before # completing its build. find_library( # Sets the name of the path variable. log-lib # Specifies the name of the NDK library that # you want CMake to locate. log ) # Specifies libraries CMake should link to your target library. You # can link multiple libraries, such as libraries you define in this # build script, prebuilt third-party libraries, or system libraries. target_link_libraries( # Specifies the target library. # 制定目标库. MyStringJni # Links the target library to the log library # included in the NDK. ${log-lib} )
需要修改部分如下标记:
第七步:在app build.gradle的android——> defaultConfig下添加
[code]// 使用Cmake工具 externalNativeBuild { cmake { cppFlags "" //生成多个版本的so文件 abiFilters 'arm64-v8a','armeabi-v7a','x86','x86_64' } }
第八步:在app build.gradle的android下添加
[code] externalNativeBuild { cmake { path "CMakeLists.txt" // 设置所要编写的c源码位置,以及编译后so文件的名字 } }
第九步:Rebuild Project,会在如下图目录生成so文件:
第十步:在main目录下,新建Libs目录,将如上图的so文件全部拷贝到Libs目录下,然后就可以调用相应的接口了
- 使用JNI进行混合编程:在C/C++中调用Java代码--------------------cocos2d-x 3.0正式版本(7.5)
- Nexus-3.0以上版本创建本地中央仓库步骤
- [Delphi]Delphi中dbexpress连接3.0以上高版本mysql的问题
- 第三步 Cordova 3.0(及以上版本) 添加插件
- ExtJS 3.0以上版本在eclipse中使用spket插件设置自动提示的方法
- smarty3.0以上版本清除缓存与之前的区别
- 使用FastReport 3.0及以上版本创建动态报表的几个技巧(转)
- Android Studio 3.0预览版本 Error:Gradle: failed to create directory 解决方案
- Android Studio 3.0及先前版本支持java 8
- ExtJs学习篇---ExtJS 3.0以上版本在eclipse中使用spket插件设置自动提示的方法
- 使用 adt-eclipse 打包 Cordova (3.0及其以上版本) + sencha touch 项目
- Android studio 下JNI编程实例并生成so库
- java 对 mongo 接口实现 3.0版本以上
- 自己实现的一个python版本的多线程 ftp扫描器,python版本3.0以上
- cocos2d-x 3.0以上版本字体设置问题
- Android Studio 3.0 JNI的实现
- mongodb3.2以上版本的学习心得(附与3.0之前的区别)
- ubuntu环境下 python 3.0以上版本对sqlite3的支持问题
- Python3.0以上版本在对比图片相似中的应用
- OpenCV3.0以上版本的Mat和IplImage相互转换