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

    完成

  • 相关阅读:
    Delphi 10.3.3解决Android 11闪退
    QuickCore
    Delphi 10.4.1使用传统代码提示方案
    LINUX SHELL条件判断
    C#程序集使用强名字(Strong Name)签名/强名称签名
    ASP.NET Core环境变量和启动设置的配置教程
    ASP.NET Core MVC获取请求的参数方法示例
    Fluentvalidation的基本使用
    netstat & crontab
    Linux/Centos下多种方法查看系统block size大小
  • 原文地址:https://www.cnblogs.com/jjx2013/p/6223735.html
Copyright © 2011-2022 走看看