Android之jni深入
16lz
2021-01-26
小技巧:自动生成 java本地方法对应的c代码的方法名 javah 指令 +全类名
java1.6版本 class C:\workspace\HelloWorldFromC2\bin\classes
java1.7以上 src C:\workspace\HelloWorldFromC2\src
获得方法的签名的方法
javap -s 打印方法的签名 注意要cd到 C:\workspace\HelloWorldFromC2\bin\classes 传全类名
Android.mk文件的书写
Anroid.mk 文件 LOCAL_PATH := $(call my-dir) // 返回当前c代码目录 include $(CLEAR_VARS) // 清楚了所有 已local 开头的配置文件 唯独不清楚LOCAL_PATH LOCAL_MODULE := hello // 库函数的名字 严格遵守makefile 格式 lib .so 如果前面加lib 不会自动生成了 LOCAL_SRC_FILES := Hello.c include $(BUILD_SHARED_LIBRARY) // 加入库函数
java调用C方法,并且传递参数
/** * 计算x和y的加法 apktools * 315 * @param x * @param y * @return */ public native int add(int x ,int y); // char String short kiss keep it simple and stupid String[] "123:234" /** * 给字符串后面拼装字符 加密运算 web url * @param s * @return */ public native String sayHelloInC(String s); // /** * 给c代码传递int数组 让c代码给这个数组进行操作 * 图形 声音的处理 * @param iNum * @return */ public native int[] intMethod(int[] iNum);
C代码输出到控制台上LOG
#define LOG_TAG "clog"#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG, LOG_TAG, __VA_ARGS__)#define LOGI(...) __android_log_print(ANDROID_LOG_INFO, LOG_TAG, __VA_ARGS__)
传递两个int实现
JNIEXPORT jint JNICALL Java_com_example_ndkpassdata_DataProvider_add (JNIEnv * env, jobject jobject, jint x, jint y){ // 想在logcat控制台上 打印日志 LOGD("x=%d",x); LOGI("y=%d",y); // log.i(TAG,"sss"); return x+y;}
字符串拼接实现
JNIEXPORT jstring JNICALL Java_com_example_ndkpassdata_DataProvider_sayHelloInC (JNIEnv * env, jobject jobject, jstring str){ char* c="hello"; // 在C语言中不能直接操作java中的字符串 // 把java中的字符串转换成c语言中 char数组 char* cstr=Jstring2CStr(env,str); strcat(cstr,c); LOGD("%s",cstr); return (*env)->NewStringUTF(env,cstr);}
传递数组实现
JNIEXPORT jintArray JNICALL Java_com_example_ndkpassdata_DataProvider_intMethod (JNIEnv * env, jobject jobject, jintArray jarray){ // jArray 遍历数组 jint* (*GetIntArrayElements)(JNIEnv*, jintArray, jboolean*); // 数组的长度 jsize (*GetArrayLength)(JNIEnv*, jarray); // 对数组中每个元素 +5 int length=(*env)->GetArrayLength(env,jarray); int* array=(*env)->GetIntArrayElements(env,jarray,0); int i=0; for(;i<length;i++){ *(array+i)+=5; } return jarray;}
C语言利用反射回调java方法
java的反射
Class<?> forName = Class.forName("com.example.ndkcallback.DataProvider"); Method declaredMethod = forName.getDeclaredMethod("helloFromJava", new Class[]{}); declaredMethod.invoke(forName.newInstance(), new Object[]{});
java中的方法的声明
public class DataProvider { //C调用java空方法 public void helloFromJava(){ System.out.println("哈哈哈 我被调用了"); } //C调用java中的带两个int参数的方法 public int Add(int x,int y){ int result=x+y; System.out.println("result:"+result); return result; } //C调用java中参数为string的方法 public void printString(String s){ System.out.println(s); } public static void demo(){ System.out.println("哈哈哈,我是静态方法"); } public native void callMethod1(); public native void callMethod2(); public native void callMethod3(); public native void callMethod4(); public native void callMethod5();}
实现
实现调用java空方法
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod1 (JNIEnv * env, jobject jobject){ /* * Class<?> forName = Class.forName("com.example.ndkcallback.DataProvider"); Method declaredMethod = forName.getDeclaredMethod("helloFromJava", new Class[]{}); declaredMethod.invoke(forName.newInstance(), new Object[]{}); * * */ ///jclass (*FindClass)(JNIEnv*, const char*); jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider"); // jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); // 方法签名 参数和返回值 jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V"); // void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); (*env)->CallVoidMethod(env,jobject,methodId);}
实现调用int参数的方法
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod2 (JNIEnv * env, jobject jobject){ jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider"); jmethodID methodId=(*env)->GetMethodID(env,clazz,"Add","(II)I"); // jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); (*env)->CallIntMethod(env,jobject,methodId,3,5);}
实现调用String参数的方法
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod3 (JNIEnv * env, jobject jobject){ // 参数 object 就是native方法所在的类 jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider"); jmethodID methodId=(*env)->GetMethodID(env,clazz,"printString","(Ljava/lang/String;)V"); // jint (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...); jstring str=(*env)->NewStringUTF(env,"hello"); (*env)->CallVoidMethod(env,jobject,methodId,str);}
实现调用其他类中的方法,注意此时的object为该类的对象
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod4 (JNIEnv * env, jobject j){ jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/MainActivity"); // jmethodID (*GetMethodID)(JNIEnv*, jclass, const char*, const char*); // 方法签名 参数和返回值 jmethodID methodId=(*env)->GetMethodID(env,clazz,"helloFromJava","()V"); // void (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...); // 需要创建DataProvider的 对象 // jobject (*AllocObject)(JNIEnv*, jclass); jobject obj=(*env)->AllocObject(env,clazz); // new MainActivity(); (*env)->CallVoidMethod(env,obj,methodId);}
实现调用静态方法
JNIEXPORT void JNICALL Java_com_example_ndkcallback_DataProvider_callMethod5 (JNIEnv * env, jobject j){ jclass clazz=(*env)->FindClass(env,"com/example/ndkcallback/DataProvider"); // jmethodID (*GetStaticMethodID)(JNIEnv*, jclass, const char*, const char*); jmethodID methodid=(*env)->GetStaticMethodID(env,clazz,"demo","()V"); //void (*CallStaticVoidMethod)(JNIEnv*, jclass, jmethodID, ...); (*env)->CallStaticVoidMethod(env,clazz,methodid);}
完成
更多相关文章
- Android(安卓)判断当前的界面是否是桌面的方法
- Android(安卓)Fragment学习之二、Fragement的使用方法
- android之mainfest 参数解说
- Android使用GPS获取用户地理位置并监听位置变化的方法
- Android(安卓)源码 图形系统之请求布局
- android 快捷键
- 使android dialog点击按钮dialog不消失的方法
- Android(安卓)NestedScrolling机制完全解析 带你玩转嵌套滑动
- Android(安卓)DownloadProvider分析