Android Studio 3.0以上版本JNI编程

平时使用JNI比较少,以前有项目在eclipse中使用过,今天尝试在Android studio中使用JNI,记录如下流程,如有不妥,请指正

 

第一步:打开SDK manager,下载如下几个工具

 

第二步:创建一个Android项目,在项目中新建一个jni接口的class,如下:

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文件

打开如下:

/* 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文件如下:

#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的代码


#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具体内容:

# 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下添加

// 使用Cmake工具
        externalNativeBuild {
            cmake {
                cppFlags ""
                //生成多个版本的so文件
                abiFilters 'arm64-v8a','armeabi-v7a','x86','x86_64'
            }
        }

第八步:在app build.gradle的android下添加

 externalNativeBuild {
        cmake {
            path "CMakeLists.txt"   // 设置所要编写的c源码位置,以及编译后so文件的名字
        }
    }

第九步:Rebuild Project,会在如下图目录生成so文件:

第十步:在main目录下,新建Libs目录,将如上图的so文件全部拷贝到Libs目录下,然后就可以调用相应的接口了

 

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值