JNI入门课程-第三章:JNI多类型字符串拼接

 序章:

1.本篇是JNI入门教程的第三篇,完整教程连接如下:

https://blog.csdn.net/rzleilei/article/details/122084609https://blog.csdn.net/rzleilei/article/details/122084609

2.本篇主要考察的是各种数据类型的转换,要完成的需求如下:

在java层中分别传入int,string,double,char,byte类型,然后在JNI中进行字符串拼接,最终返回给安卓层进行展示。

一。流程步骤

安卓中调用jni主要包含以下几个步骤:

1.在java中声明引用。

2.在jni中创建对应的h文件和cpp文件。

3.在CMakeLists中进行声明,声明之后jni中的方法才能被java外部调用。

4.java层中构造各种数据类型,然后传给JNI进行调用。

二。在java中创建声明类

和上一篇流程一样,所以只贴代码就不详细介绍了:

package com.xt.client.jni;

import com.xt.client.model.JavaModel;

public class CalculationJNITest {

    static {
        System.loadLibrary("Calculation");
    }

    /**
     * @param value1
     * @param value2
     * @param str1
     * @param double1
     * @param chars
     * @param bytes
     * @return
     */
    public native String calculationSum(int value1, int value2, String str1, double double1, char[] chars, byte[] bytes);

}

三。在jni中创建h和cpp文件

1,2流程和上一篇文章中流程是一样的,就不详细介绍了。

1.创建com_xt_client_jni_CalculationJNITest.h文件

2.创建CalculationNative.cpp文件

3.创建JNI中被调用拼接方法Java_com_xt_client_jni_CalculationJNITest_calculationSum

方法如下:

jstring JNICALL
Java_com_xt_client_jni_CalculationJNITest_calculationSum(JNIEnv *env, jobject instance, jint value1,
                                                         jint value2, jstring str1, jdouble double1,
                                                         jcharArray chars, jbyteArray bytes) {
    //因为jni中的字符串是char类型,所以先把第三个参数jstring转换为char类型
    const char *thirdStr = env->GetStringUTFChars(str1, 0);
    LOGI("%s", "ConvertJcharArray2Chars");
    //java中的char类型在JNI中为jcharArray,同样转换为jni中的char类型
    char *charsChar = ConvertJcharArray2Chars(env, chars);
    LOGI("ConvertJByteaArrayToChars2:%s", charsChar);
    //java中的byte类型在JNI中为jbyteArray,同样转换为jni中的char类型
    char *bytesChar = ConvertJByteaArrayToChars(env, bytes, charsChar);
    LOGI("ConvertJByteaArrayToChars4:%s", charsChar);
    LOGI("bytesChar:%s", bytesChar);
    //字符串拼接
    char *buf = getChar(value1, value2, thirdStr, double1, charsChar, bytesChar);
    LOGI("%s %s", "buf is:", buf);
    //转换完成中生成jstring类型
    jstring computerName = env->NewStringUTF(buf);
    //buf已经使用完没用了,进行内存地址的删除
    delete[] buf;
    return computerName;
}

这里我们发现了好多LOGI,这个是我们自己声明的log方法,主要用于在JNI中调试输出logcat日志,方便排查问题。

我们只需要做如下两部就可以使用了:

1.在CPP文件头部添加声明:

#define LOG_TAG "lxltestjni"
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,LOG_TAG,__VA_ARGS__)

2.在CMakeLists中创建连接,这个具体第四章会介绍。

4.jint转换为jni中的char类型

使用sprintf()方法进行拼接,

char *getChar(jint value1,
              jint value2, const char *str1, jdouble double1,
              char *chars, char *bytes) {

    char *buf = new char[10];
    sprintf(buf, "%i", value1);
    LOGI("buff:%s", buf);//1

5.jstring转换为jni中的char类型

可以直接调用JNI提供的方法把jstring转换为char类型

const char *thirdStr = env->GetStringUTFChars(str1, 0);

6.jdouble转换为jni中的char类型

也可以通过sprintf方法进行拼接:

char *getChar(jint value1,
              jint value2, const char *str1, jdouble double1,
              char *chars, char *bytes) {
char *buf = new char[10];
sprintf(local, "%.0lf", double1);
}

7.jcharArray转换为jni中的char类型:ConvertJcharArray2Chars方法

char *ConvertJcharArray2Chars(JNIEnv *env, jcharArray chars) {
    jchar *array = (env)->GetCharArrayElements(chars, NULL);
    jsize arraysize = (env)->GetArrayLength(chars);

    char *buf = new char[arraysize + 1];
//    char buf[arraysize + 1];
    LOGI("arraysize:%i", arraysize);
    int i = 0;
    for (i = 0; i < arraysize; i++) {
        buf[i] = static_cast<char>(array[i]);
    }
    buf[arraysize] = '\0';
    return buf;
}

8.jcharByte转换为jni中的char类型

char *ConvertJByteaArrayToChars(JNIEnv *env, jbyteArray bytearray, char *charsChar) {
    char *chars = NULL;
    jbyte *bytes;
    bytes = env->GetByteArrayElements(bytearray, 0);
    __android_log_print(0, "111%s", "111");
    LOGI("ConvertJByteaArrayToChars3:%s", charsChar);
    int chars_len = env->GetArrayLength(bytearray);
    LOGI("chars_len:%d", chars_len);
    LOGI("ConvertJByteaArrayToChars3.1:%s", charsChar);
    chars = new char[chars_len + 1];
    LOGI("ConvertJByteaArrayToChars3.2:%s,%s", charsChar, chars);
    memset(chars, 0, chars_len + 1);
    LOGI("ConvertJByteaArrayToChars3.3:%s,%s", charsChar, chars);
    memcpy(chars, bytes, chars_len);
    LOGI("ConvertJByteaArrayToChars3.4:%s", charsChar);
    chars[chars_len] = 0;
    env->ReleaseByteArrayElements(bytearray, bytes, 0);
    LOGI("ConvertJByteaArrayToChars3.5:%s", charsChar);
    return chars;
}

9.对所有的char字符串进行拼接:getChar方法

四。CMakeLists中做好声明

1.创建文件Cmake文件:

src同级目录下,创建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(
        Calculation
        SHARED
        src/main/jni/CalculationNative.cpp)

2.CMakeLists中创建log的连接

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. 指定连接的目标库
        Calculation
        # Links the target library to the log library
        # included in the NDK.
        ${log-lib})

3.gradle中做好声明

app的build.gradle文件中,在android{}模块下,添加如下声明:

externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
//            version "3.10.2"
        }
    }

五。验证效果

1.java中写好调用方法

 if (position == 1) {
            var calculationJNITest = CalculationJNITest()
            val inputStreamFromUrl = IOHelper.fromStringToIputStream("6")
            val input2byte = IOHelper.input2byte(inputStreamFromUrl)
            try {
                val calculationSum =
                    calculationJNITest.calculationSum(1, 2, "3", 4.0, "5".toCharArray(), input2byte)
                mResult.text = calculationSum
            } catch (e: Exception) {
                e.printStackTrace()
            }
            return
        }

2.点击JNI多类型输入加法(其实应该是多类型输入拼接才对),查看效果,这时候我们发现result中显示了拼接值。

 

六。项目源码链接:

https://github.com/aa5279aa/android_all_demohttps://github.com/aa5279aa/android_all_demo/blob/master/DemoClient

调用入口类:

https://github.com/aa5279aa/android_all_demo/blob/master/DemoClient/app/src/main/java/com/xt/client/activitys/JNIActivity.kt

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

失落夏天

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值