NDK开发一些棘手的问题

javah

每当我们去创建一个本地方法,那么对应的C层方法名则应该是Java_包名类名方法名。每次都要自己去写很容易出错。这里我们可以使用javah这个命令来帮我们实现。

1.打开dos命令行,也可以是as自带的Terminal模块
2.跳转到包名的最顶层,一般我们是到 项目/app/src/main/java文件夹
3.调用javah -jni 包名.类名

javap

该命令可以帮助我们获取方法的签名,一般情况下,根据方法名和方法签名可以标识到唯一的某个方法。

1 找到需要获取签名方法的类的class文件,as目录下所有的class文件存储在app/build/intermediates/classes/debug文件夹下。找到对应的class文件。

cd app/build/intermediates/classes/debug/…

2.调用命令
javap -s com.xxx.MainActivity

Android.mk

总体来说 编译c文件,我们可以使用gcc工具,但是如果要让所有的c文件批量编译,就需要通过配置文件makefile脚本来实现。而jni中c文件的makefile脚本配置说明书可以通过docs文件夹的ANDROID-MK.html来查阅,但是AS下载好的文件夹却不包括docs文件夹.这里贴出主要的配置内容。

   ---------- cut here ------------------
   LOCAL_PATH := $(call my-dir)

   include $(CLEAR_VARS)

   LOCAL_MODULE    := hello-jni
   LOCAL_SRC_FILES := hello-jni.c

   include $(BUILD_SHARED_LIBRARY)
   ---------- cut here ------------------

Application.mk

该文件同样存在于JNI文件夹下,其可以配置产生的对应cpu的so库,默认生成所有类型的so库。配置如下:

APP_ABI
    By default, the NDK build system will generate machine code for the
    'armeabi' ABI. This corresponds to an ARMv5TE based CPU with software
    floating point operations. You can use APP_ABI to select a different
    ABI.

    For example, to support hardware FPU instructions on ARMv7 based devices,
    use:

        APP_ABI := armeabi-v7a

    Or to support both ARMv5TE and ARMv7 based devices, use:

        APP_ABI := armeabi armeabi-v7a

类型一般有armeabi armeabi-v7a x86

C代码的一些配置

sleep

win下面开发的c代码有sleep(int)函数,帮助代码实现睡眠。但是unix系统该函数无法使用,需要实现导包:

#include <unistd.h>

strcmp

该函数实现2个c字符串相比较,在某些系统中无法直接使用,可以使用导包实现:

#include <string.h>

如果2个字符串相等 则返回0。

java字符串转c字符串

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); // String .getByte("GB2312");
    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;
}

c字符串转java字符串

(*env)->NewStringUTF(env,text)

c代码调用java方法

其操作的方式有点类似于反射,代码如下:

//jclass      (*FindClass)(JNIEnv*, const char*);
    jclass clazz=(*env)->FindClass(env,"com/a520it/alipayndksample/MainActivity");
    //jmethodID GetMethodID(jclass clazz, const char* name, const char* sig)
    jmethodID methodId=(*env)->GetMethodID(env,clazz,"dismissDialog","()V");
    //void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);
    (*env)->CallVoidMethod(env,obj,methodId);

猜你喜欢

转载自blog.csdn.net/qq285016127/article/details/78408995