zoukankan      html  css  js  c++  java
  • Android之jni深入

    小技巧:自动生成 java本地方法对应的c代码的方法名 javah 指令 +全类名

    java1.6版本 class C:workspaceHelloWorldFromC2inclasses
    java1.7以上 src C:workspaceHelloWorldFromC2src

    获得方法的签名的方法

    javap -s 打印方法的签名 注意要cd到 C:workspaceHelloWorldFromC2inclasses 传全类名

    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);
    }

    完成

  • 相关阅读:
    JavaScript Patterns 5.7 Object Constants
    JavaScript Patterns 5.6 Static Members
    JavaScript Patterns 5.5 Sandbox Pattern
    JavaScript Patterns 5.4 Module Pattern
    JavaScript Patterns 5.3 Private Properties and Methods
    JavaScript Patterns 5.2 Declaring Dependencies
    JavaScript Patterns 5.1 Namespace Pattern
    JavaScript Patterns 4.10 Curry
    【Android】如何快速构建Android Demo
    【Android】如何实现ButterKnife
  • 原文地址:https://www.cnblogs.com/jjx2013/p/6223735.html
Copyright © 2011-2022 走看看