Android NDK JNI 入门笔记-day02-基本数据类型数据传递

Android NDK JNI 入门笔记目录

Java & JNI 基本数据类型

Java 中的基本数据类型包括 boolean,byte,char,short,int,long,float,double 这几种。

而用 C/C++ 编写 native 代码时,是不能直接使用 Java 的数据类型的。

所以 JNI 提供了 jboolean、jbyte、jchar、jshort、jint、jlong、jfloat、jdouble。

Java 基本数据类型与 JNI 数据类型的映射关系

Java Type Native Type Description
boolean jboolean unsigned 8 bits
byte jbyte signed 8 bits
char jchar unsigned 16 bits
short jshort signed 16 bits
int jint signed 32 bits
long jlong signed 64 bits
float jfloat 32 bits
double jdouble 64 bits
void void N/A

基本数据类型传递-练习工程

Day02 创建新项目

Java -> Native

点击每个按钮,将 Java 的基本数据类型传递到 Native,Native 代码(C/C++)中将数据打印到日志。

java-to-native

JavaToNativeActivity.java
public class JavaToNativeActivity extends AppCompatActivity {

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_java_to_native);
        setTitle("Java -> Native");
    }

    public void booleanTest(View view) {
        NativeUtil.javaBooleanToNative(true);
        NativeUtil.javaBooleanToNative(false);
    }

    public void byteTest(View view) {
        NativeUtil.javaByteToNative(Byte.MIN_VALUE);
        NativeUtil.javaByteToNative(Byte.MAX_VALUE);
        NativeUtil.javaByteToNative(Byte.parseByte("123"));
    }

    public void charTest(View view) {
        NativeUtil.javaCharToNative(Character.MIN_VALUE);
        NativeUtil.javaCharToNative(Character.MAX_VALUE);
        NativeUtil.javaCharToNative('A');
        NativeUtil.javaCharToNative('B');
        NativeUtil.javaCharToNative('C');
    }

    public void shortTest(View view) {
        NativeUtil.javaShortToNative(Short.MIN_VALUE);
        NativeUtil.javaShortToNative(Short.MAX_VALUE);
        NativeUtil.javaShortToNative(Short.parseShort("999"));
    }

    public void intTest(View view) {
        NativeUtil.javaIntToNative(Integer.MIN_VALUE);
        NativeUtil.javaIntToNative(Integer.MAX_VALUE);
        NativeUtil.javaIntToNative(Integer.parseInt("999999"));
    }

    public void longTest(View view) {
        NativeUtil.javaLongToNative(Long.MIN_VALUE);
        NativeUtil.javaLongToNative(Long.MAX_VALUE);
        NativeUtil.javaLongToNative(Long.parseLong("999999999"));
    }

    public void floatTest(View view) {
        NativeUtil.javaFloatToNative(Float.MIN_VALUE);
        NativeUtil.javaFloatToNative(Float.MAX_VALUE);
        NativeUtil.javaFloatToNative(999999.8F);
    }

    public void doubleTest(View view) {
        NativeUtil.javaDoubleToNative(Double.MIN_NORMAL);
        NativeUtil.javaDoubleToNative(Double.MAX_VALUE);
        NativeUtil.javaDoubleToNative(999999999.8);
    }

}
NativeUtil.java
public class NativeUtil {

    static {
        System.loadLibrary("native-lib");
    }

    public native static void javaBooleanToNative(boolean value);

    public native static void javaByteToNative(byte value);

    public native static void javaCharToNative(char value);

    public native static void javaShortToNative(short value);

    public native static void javaIntToNative(int value);

    public native static void javaLongToNative(long value);

    public native static void javaFloatToNative(float value);

    public native static void javaDoubleToNative(double value);

}
native-lib.cpp
#include <jni.h>
#include <string>
#include <android/log.h>
#include <math.h>

#define LOG_TAG  "C_TAG"
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
//LOGD("hello.length=%d",helloLen);

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaBooleanToNative(JNIEnv *env, jclass clazz, jboolean value) {
    LOGD("Java Boolean: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaByteToNative(JNIEnv *env, jclass clazz, jbyte value) {
    LOGD("Java Byte: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaCharToNative(JNIEnv *env, jclass clazz, jchar value) {
    LOGD("Java Char: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaShortToNative(JNIEnv *env, jclass clazz, jshort value) {
    LOGD("Java Short: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaIntToNative(JNIEnv *env, jclass clazz, jint value) {
    LOGD("Java Int: %d", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaLongToNative(JNIEnv *env, jclass clazz, jlong value) {
    LOGD("Java Long: %lld", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaFloatToNative(JNIEnv *env, jclass clazz, jfloat value) {
    LOGD("Java Float: %f", value);
}

extern "C"
JNIEXPORT void JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaDoubleToNative(JNIEnv *env, jclass clazz, jdouble value) {
    LOGD("Java Double: %lf", value);
}
点击每个按钮,在 Logcat 中查看输出日志
D/C_TAG: Java Boolean: 1
D/C_TAG: Java Boolean: 0
D/C_TAG: Java Byte: -128
D/C_TAG: Java Byte: 127
    Java Byte: 123
D/C_TAG: Java Char: 0
    Java Char: 65535
    Java Char: 65
    Java Char: 66
    Java Char: 67
D/C_TAG: Java Short: -32768
D/C_TAG: Java Short: 32767
    Java Short: 999
D/C_TAG: Java Int: -2147483648
    Java Int: 2147483647
    Java Int: 999999
D/C_TAG: Java Long: -9223372036854775808
    Java Long: 9223372036854775807
    Java Long: 999999999
D/C_TAG: Java Float: 0.000000
    Java Float: 340282346638528859811704183484516925440.000000
    Java Float: 999999.812500
D/C_TAG: Java Double: 0.000000
    Java Double: 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000
    Java Double: 999999999.800000

Java <- Navive

点击每个按钮,将从 Native 代码(C/C++)中获取 Java 的基本数据类型。

native-to-java

NativeToJavaActivity.java
public class NativeToJavaActivity extends AppCompatActivity {

    private TextView booleanText;
    private TextView byteText;
    private TextView charText;
    private TextView shortText;
    private TextView intText;
    private TextView longText;
    private TextView floatText;
    private TextView doubleText;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_native_to_java);
        setTitle("Native -> Java");

        booleanText = findViewById(R.id.boolean_text);
        byteText = findViewById(R.id.byte_text);
        charText = findViewById(R.id.char_text);
        shortText = findViewById(R.id.short_text);
        intText = findViewById(R.id.int_text);
        longText = findViewById(R.id.long_text);
        floatText = findViewById(R.id.float_text);
        doubleText = findViewById(R.id.double_text);
    }

    public void booleanTest(View view) {
        boolean value = NativeUtil.javaBooleanFromNative();
        booleanText.setText("value = " + value);
    }

    public void byteTest(View view) {
        byte value = NativeUtil.javaByteFromNative();
        byteText.setText("value = " + value);
    }

    public void charTest(View view) {
        char value = NativeUtil.javaCharFromNative();
        charText.setText("value = " + value);
    }

    public void shortTest(View view) {
        short value = NativeUtil.javaShortFromNative();
        shortText.setText("value = " + value);
    }

    public void intTest(View view) {
        int value = NativeUtil.javaIntFromNative();
        intText.setText("value = " + value);
    }

    public void longTest(View view) {
        long value = NativeUtil.javaLongFromNative();
        longText.setText("value = " + value);
    }

    public void floatTest(View view) {
        float value = NativeUtil.javaFloatFromNative();
        floatText.setText("value = " + value);
    }

    public void doubleTest(View view) {
        double value = NativeUtil.javaDoubleFromNative();
        doubleText.setText("value = " + value);
    }

}
NativeUtil.java
public class NativeUtil {

    static {
        System.loadLibrary("native-lib");
    }
    
    public native static boolean javaBooleanFromNative();

    public native static byte javaByteFromNative();

    public native static char javaCharFromNative();

    public native static short javaShortFromNative();

    public native static int javaIntFromNative();

    public native static long javaLongFromNative();

    public native static float javaFloatFromNative();

    public native static double javaDoubleFromNative();

}
native-lib.cpp
#include <jni.h>
#include <string>
#include <android/log.h>
#include <math.h>

#define LOG_TAG  "C_TAG"
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
//LOGD("hello.length=%d",helloLen);

extern "C"
JNIEXPORT jboolean JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaBooleanFromNative(JNIEnv *env, jclass clazz) {
    return JNI_TRUE;
}

extern "C"
JNIEXPORT jbyte JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaByteFromNative(JNIEnv *env, jclass clazz) {
    return 123;
}

extern "C"
JNIEXPORT jchar JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaCharFromNative(JNIEnv *env, jclass clazz) {
    return 'A';
}

extern "C"
JNIEXPORT jshort JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaShortFromNative(JNIEnv *env, jclass clazz) {
    return 999;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaIntFromNative(JNIEnv *env, jclass clazz) {
    return 999999;
}

extern "C"
JNIEXPORT jlong JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaLongFromNative(JNIEnv *env, jclass clazz) {
    return 999999999;
}

extern "C"
JNIEXPORT jfloat JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaFloatFromNative(JNIEnv *env, jclass clazz) {
    return 999999.8;
}

extern "C"
JNIEXPORT jdouble JNICALL
Java_com_ihubin_ndkjni_NativeUtil_javaDoubleFromNative(JNIEnv *env, jclass clazz) {
    return 999999999.8;
}
点击每个按钮,进行测试

native-to-java-result

Java <-> Native

点击每个按钮,将和 Native(C/C++) 传递、获取 Java 的基本数据类型。

java-and-native

JavaNativeActivity.java
public class JavaNativeActivity extends AppCompatActivity {

    private TextView charConcatText;
    private TextView sumText;
    private TextView twoExpText;
    private TextView calcMoneyText;

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_java_native);
        setTitle("Java <-> Native");

        charConcatText = findViewById(R.id.char_concat_text);
        sumText = findViewById(R.id.sum_text);
        twoExpText = findViewById(R.id.two_exp_text);
        calcMoneyText = findViewById(R.id.calc_money_text);
    }


    public void charConcatTest(View view) {
        String value = NativeUtil.charConcatTest('A', 'B', 'C');
        charConcatText.setText("A+B+C=" + value);
    }

    public void sumTest(View view) {
        int numOne = 123;
        int numTwo = 456;
        int value = NativeUtil.sumText(numOne, numTwo);
        sumText.setText(numOne + "+" + numTwo + "=" + value);
    }

    public void twoExpTest(View view) {
        int value = NativeUtil.twoExpTest(10);
        twoExpText.setText("2^10=" + value);
    }

    public void calcMoneyTest(View view) {
        double apple = 12.4;
        double banana = 99.8;
        double orange = 101.1;
        String value = NativeUtil.calcMoneyTest(apple, banana, orange);
        calcMoneyText.setText(value);
    }

}
NativeUtil.java
public class NativeUtil {

    static {
        System.loadLibrary("native-lib");
    }

    public native static String charConcatTest(char a, char b, char c);

    public native static int sumText(int i, int j);

    public native static int twoExpTest(int exp);

    public native static String calcMoneyTest(double v, double v1, double v2);
    
}
native-lib.cpp
#include <jni.h>
#include <string>
#include <android/log.h>
#include <math.h>

#define LOG_TAG  "C_TAG"
#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)
//LOGD("hello.length=%d",helloLen);


extern "C"
JNIEXPORT jstring JNICALL
Java_com_ihubin_ndkjni_NativeUtil_charConcatTest(JNIEnv *env, jclass clazz, jchar a, jchar b,
                                                 jchar c) {
    char charArray[4];
    charArray[0] = a;
    charArray[1] = b;
    charArray[2] = c;
    charArray[3] = '\0';
    return env->NewStringUTF(charArray);
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_ihubin_ndkjni_NativeUtil_sumText(JNIEnv *env, jclass clazz, jint i, jint j) {
    return i + j;
}

extern "C"
JNIEXPORT jint JNICALL
Java_com_ihubin_ndkjni_NativeUtil_twoExpTest(JNIEnv *env, jclass clazz, jint exp) {
    return pow(2, exp);
}

extern "C"
JNIEXPORT jstring JNICALL
Java_com_ihubin_ndkjni_NativeUtil_calcMoneyTest(JNIEnv *env, jclass clazz, jdouble v, jdouble v1,
                                                jdouble v2) {
    double totalMoney = v + v1 + v2;
    char *resultStr = new char();
    sprintf(resultStr, "总计:%f", totalMoney);
    return env->NewStringUTF(resultStr);
}
点击每个按钮,进行测试

java-and-native-result

至此,我们已经学会了在 Android 项目中与 Native(C/C++) 进行数据交换。


代码:

NDKJNIday02

参考资料:

Oracle - JNI Types and Data Structures

JNI 打印 log 信息


3 声望
4 粉丝
0 条评论
推荐阅读
音视频入门-20-BMP、PNG、JPG、GIF静态图生成GIF动态图
音视频入门文章目录 静态图 -&gt; 动态图前面 【18-手动生成一张GIF图片】 和 【19-使用giflib处理GIF图片】 生成的 GIF 每一帧都是一个颜色,平时用到的 GIF 每一帧都是图片,下面就做一张每一帧都是图片的 GIF...

binglingziyu阅读 1.2k

如何用3D流体实现逼真水流效果?
华为应用市场在2022年HDC大会期间发布了一款3D水流主题,基于华为HMS Core Scene Kit服务能力,展现立体灵动的水流岛屿,可跟随用户指尖实现实时流体波动效果,既趣味又解压。

HMSCore1阅读 2k

Android桌面图标快捷方式
长按桌面图标实现快捷方式最早是iOS提供的功能,而Android最早在Android 7.1版本也提供了对这方面的支持,于是在短时间内,像微信,支付宝,头条等流量级应用都提供了这方面的支持,如下图。 

xiangzhihong2阅读 590

2022 年终总结|致敬即将过去的,匆忙而又虐心的一年...
本文参与了 SegmentFault 思否年度征文「一名技术人的 2022」,欢迎正在阅读的你也加入。 时间,总是过的这么快,快得让人猝不及防,眨眼又是一年的末...似乎儿时的文章中,对于时间的流逝,描述的最多的便是:白...

贺biubiu1阅读 1.1k

封面图
安卓逆向之破解某成人APP播放次数限制
某成人水果APP非VIP用户存在播放次数限制,每天只能播放3次。超过3次需要购买VIP。 由于过于贫穷,于是抽空,对其安卓APP进行了逆向分析,最终成功破解了其播放次数限制。

悖论2阅读 224

封面图
读懂 gradle dependencies
不过在使用 dependencies 时有一些细节之前一直没有搞清楚,遂研究了一下部分细节。本文整体参考 gradle 官方文档,大家感兴趣也可以自己深入研究下。

云音乐技术团队1阅读 453

封面图
Android实现RecyclerView嵌套流式布局
新建Activity文件RecyclerViewActivity.class {代码...} Activity页面布局activity_recycler_view.xml {代码...}

似水流年1阅读 784

3 声望
4 粉丝
宣传栏