Android之jni深入
2016-03-22 19:59
483 查看
小技巧:自动生成 java本地方法对应的c代码的方法名 javah 指令 +全类名
java1.6版本 classC:\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蓝牙自动配对和Pin码设置
- Android Paint类的介绍
- Android中找不到png文件错误
- android开发实现七牛云传输文件
- 解决Android Studio的ADB not responding错误
- java.lang.ClassCastException: android.widget.LinearLayout$LayoutParams cannot be cast to android.wi
- android中的xml的tools
- Android输入法弹出时覆盖输入框问题
- Android开发的一些代码外的事情
- Android控件自适应屏幕大小
- Android中打招呼
- android 通过工具抓包
- android线程消息传递机制——Looper,Handler,Message
- Android中进程(Process)和线程(Thread)
- Android Studio 遇到 “method ID not in [0, 0xffff]: 65536” error
- java环境的搭建及Android SDK环境搭建的路径
- android实现从一个activity跳转到另一个activity中
- Android studio怎样隐藏标题栏
- Android studio 开发快捷键使用(新手)
- Android新手入门2016(12)--基于Layout文件的AlertDialog