您的位置:首页 > 移动开发 > Android开发

Android Studio 3.0以上版本JNI编程

2019-08-06 11:30 405 查看
版权声明:本文为博主原创文章,遵循 CC 4.0 by-sa 版权协议,转载请附上原文出处链接和本声明。 本文链接:https://blog.csdn.net/ylq240911/article/details/98596020

平时使用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目录下,然后就可以调用相应的接口了

 

 

 

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: