Android自助餐之Jni进阶

Posted -_-void

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Android自助餐之Jni进阶相关的知识,希望对你有一定的参考价值。

android自助餐之Jni(五)进阶

C2C++(待完善)

函数声明

  • Java类:package.name.ClassName.methodName();Java方法:public native String methodName(String value)
  • C:JNIEXPORT jstring JNICALL Java_package_name_ClassName_methodName(JNIEnv *env,jobject obj,jstring value)
  • C++

    //声明
    extern "C"{
    jstring Java_package_name_ClassName_methodName(JNIEnv *env,jobject obj,jstring value);
    }
    //定义:
    jstring Java_package_name_ClassName_methodName(JNIEnv *env,jobject obj,jstring value){...}

方法调用

  1. GetStringUTFChars
    • C:char * str = (*env)->GetStringUTFChars(env,value,NULL);
    • C++:const char * str = env->GetStringUTFChars(value,NULL);
  2. NewStringUTF
    • C:(*env)->NewStringUTF(env, str);
    • C++:env->NewStringUTF(str);
  3. sprintf
    • C:使用前只需定义第一个参数char * str;
    • C++:使用前需定义第一个参数并为其分配空间char * str = (char*)malloc(sizeof("size you need"))

使用androidLog

  1. 配置build.gradle

    android {
    //...
    defaultConfig {
    //...
    ndk{
    //...
    ldLibs "log", "z", "m"
    }
    }
    }
  2. include
    在用到log的C/C++中#include <android/log.h>
  3. 调用log
    __android_log_write(ANDROID_LOG_ERROR, "tag","message");

模块化

当jni文件夹下文件过多不好管理时,可以再jni下新建子文件夹来将文件分模块管理,引用时写上子文件名即可。例文件jni/file.h移到jni/file/file.h,对应的include "file.h"改为include "file/file.h"

类型转换

  1. java中的String
    在C/C++中用jstring接收,用char*操作,jstring与char*的转换见上述(C2C++)
  2. java中的int
    在C++中用int接收。

操作bitmap

  1. java代码

    public native void fun(Bitmap bmp);
  2. C++头文件
    #include <android/bitmap.h>
  3. C++代码

    void Java_package_name_ClassName_fun(JNIEnv *env,jobject obj,jobject bmp){
    AndroidBitmapInfo bmpInfo={0};
    if(AndroidBitmap_getInfo(env,bmp,&bmpInfo)<0){return;}
    unsigned char * dataFromBmp=NULL;//此指针即指向bitmap数据的指针
    if(AndroidBitmap_lockPixels(env,bmp,(void **)&dataFromBmp)){return;}//获取并锁定bitmap在内存的地址
    //do something with dataFromBmp
    AndroidBitmap_unlockPixels(env,bmp);//操作结束后需要解锁改地址
    }
  4. 配置build.gradle

    android {
    //...
    defaultConfig {
    //...
    ndk{
    //...
    ldLibs "jnigraphics"
    }
    }
    }
  5. 配置Android.mk
    LOCAL_LDLIBS := -ljnigraphics
  6. clean project

其他

  1. 使用标准库STL
    • 在jni下新建文件Application.mk并写入APP_STL := stlport_static
    • 在build.gradle中配置

      android {
      //...
      defaultConfig {
      //...
      ndk{
      //...
      stl "stlport_static"
      }
      }
      }
  2. 开启异常控制(可以在cpp中throw)

    android {
      //...
      defaultConfig {
          //...
          ndk{
             //...
             cFlags = "-fexceptions"
          }
      }
    }
  3. error: undefined reference to xxx
    一般该错误会在cpp中报出,找到对应的h文件,做如下修改

    
    #ifndef _A_H   
    
    
    #define _A_H  
    
    
    
    #ifdef __cplusplus
    
    extern "C"{
    
    #endif
    
    
    ...(文件原有代码)
    
    
    #ifdef __cplusplus
    
    }
    
    #endif
    
    
    
    #endif  // endof _A_H
    
  4. const char *unsignde char *

    //const cahr * str=...;
    unsigned char * data=(unsigned char *)(const_cast<char*>(str));

以上是关于Android自助餐之Jni进阶的主要内容,如果未能解决你的问题,请参考以下文章

Android自助餐之EventBus框架

Android自助餐之解析zip

我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印内容带有文件文件名方法名行号 等信息,方便定位日志输出的地方

我的Android进阶之旅NDK开发之在C++代码中使用Android Log打印日志,打印内容带有文件文件名方法名行号 等信息,方便定位日志输出的地方

我的C/C++语言学习进阶之旅JNI开发之转换C层返回的结构体为Java实体Bean

我的C/C++语言学习进阶之旅JNI开发之转换C层返回的结构体为Java实体Bean