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

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

Java -> Native

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

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 #include #include #include #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 JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaBooleanToNative(JNIEnv *env, jclass clazz, jboolean value) {    LOGD("Java Boolean: %d", value);}extern "C"JNIEXPORT void JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaByteToNative(JNIEnv *env, jclass clazz, jbyte value) {    LOGD("Java Byte: %d", value);}extern "C"JNIEXPORT void JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaCharToNative(JNIEnv *env, jclass clazz, jchar value) {    LOGD("Java Char: %d", value);}extern "C"JNIEXPORT void JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaShortToNative(JNIEnv *env, jclass clazz, jshort value) {    LOGD("Java Short: %d", value);}extern "C"JNIEXPORT void JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaIntToNative(JNIEnv *env, jclass clazz, jint value) {    LOGD("Java Int: %d", value);}extern "C"JNIEXPORT void JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaLongToNative(JNIEnv *env, jclass clazz, jlong value) {    LOGD("Java Long: %lld", value);}extern "C"JNIEXPORT void JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaFloatToNative(JNIEnv *env, jclass clazz, jfloat value) {    LOGD("Java Float: %f", value);}extern "C"JNIEXPORT void JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaDoubleToNative(JNIEnv *env, jclass clazz, jdouble value) {    LOGD("Java Double: %lf", value);}
点击每个按钮,在 Logcat 中查看输出日志
D/C_TAG: Java Boolean: 1D/C_TAG: Java Boolean: 0D/C_TAG: Java Byte: -128D/C_TAG: Java Byte: 127    Java Byte: 123D/C_TAG: Java Char: 0    Java Char: 65535    Java Char: 65    Java Char: 66    Java Char: 67D/C_TAG: Java Short: -32768D/C_TAG: Java Short: 32767    Java Short: 999D/C_TAG: Java Int: -2147483648    Java Int: 2147483647    Java Int: 999999D/C_TAG: Java Long: -9223372036854775808    Java Long: 9223372036854775807    Java Long: 999999999D/C_TAG: Java Float: 0.000000    Java Float: 340282346638528859811704183484516925440.000000    Java Float: 999999.812500D/C_TAG: Java Double: 0.000000    Java Double: 179769313486231570814527423731704356798070567525844996598917476803157260780028538760589558632766878171540458953514382464234321326889464182768467546703537516986049910576551282076245490090389328944075868508455133942304583236903222948165808559332123348274797826204144723168738177180919299881250404026184124858368.000000    Java Double: 999999999.800000

Java <- Navive

点击每个按钮,将从 Native 代码(C/C++)中获取 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 #include #include #include #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 JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaBooleanFromNative(JNIEnv *env, jclass clazz) {    return JNI_TRUE;}extern "C"JNIEXPORT jbyte JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaByteFromNative(JNIEnv *env, jclass clazz) {    return 123;}extern "C"JNIEXPORT jchar JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaCharFromNative(JNIEnv *env, jclass clazz) {    return 'A';}extern "C"JNIEXPORT jshort JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaShortFromNative(JNIEnv *env, jclass clazz) {    return 999;}extern "C"JNIEXPORT jint JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaIntFromNative(JNIEnv *env, jclass clazz) {    return 999999;}extern "C"JNIEXPORT jlong JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaLongFromNative(JNIEnv *env, jclass clazz) {    return 999999999;}extern "C"JNIEXPORT jfloat JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaFloatFromNative(JNIEnv *env, jclass clazz) {    return 999999.8;}extern "C"JNIEXPORT jdouble JNICALLJava_com_ihubin_ndkjni_NativeUtil_javaDoubleFromNative(JNIEnv *env, jclass clazz) {    return 999999999.8;}
点击每个按钮,进行测试

Java <-> Native

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

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 #include #include #include #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 JNICALLJava_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 JNICALLJava_com_ihubin_ndkjni_NativeUtil_sumText(JNIEnv *env, jclass clazz, jint i, jint j) {    return i + j;}extern "C"JNIEXPORT jint JNICALLJava_com_ihubin_ndkjni_NativeUtil_twoExpTest(JNIEnv *env, jclass clazz, jint exp) {    return pow(2, exp);}extern "C"JNIEXPORT jstring JNICALLJava_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);}
点击每个按钮,进行测试

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


代码:

NDKJNIday02

参考资料:

Oracle - JNI Types and Data Structures

JNI 打印 log 信息


更多相关文章

  1. Android(安卓)EditText 点击时不弹出键盘但显示光标
  2. SQLite操作
  3. android开始
  4. Android(安卓)Dialog,Toast封装
  5. Android(安卓)Studio上使用OpenCV-android-sdk
  6. PopupWindow setOutsideTouchable 问题
  7. Android(安卓)TextView实现点击展开动画效果
  8. android studio删除module
  9. Android(安卓)获取系统程序和应用程序

随机推荐

  1. android dom4j sax 兼容问题
  2. 最常用的GitHub—— Android(安卓)开源项
  3. Android跨进程通信
  4. Android关于常用正则号码类Util
  5. android带图片的AlertDialog和文件管理器
  6. Android利用tcpdump抓包
  7. android的文件操作
  8. Android入门:ImageView介绍
  9. 提升基于英特尔® 架构的 Android* 模拟
  10. Android的理解