android studio 进行ndk/jni开发

一、前言:之前用eclipse开发ndk的时候大家是不是很痛苦,要做的事情很多:

    //NDK开发流程: 
    1、在java代码中 声明本地方法(native)
    2、通过javah工具完成jni样式的头文件(.h文件)的生成    

    3、在工程中 创建jni目录,在jni目录中编写 与java本地方法对应的C方法
        jstring Java_包名_类名_方法名(){...}

    4、编写Android.mk文件,来指定如何编译C代码
    5、通过ndk-build工具来完成交叉编译 ,生成Anroid 中可以调用的2进制文件(链接库文件)
    6、在Java代码中引用System.loadLibrary("hello-jni");
   这个过程是非常的繁琐,运行ndk-build命令还需要装cgwin

但是现在Android Studio集成了ndk开发环境(ndk如何配置就不说了),我们只需要走这么几步就可以了:

二、Android Studio进行ndk开发

1、创建工程的时候需要勾上支持ndk开发

2、默认选择支持标准c++就可以了

C++ Standard:使用下拉列表选择使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
Exceptions Support:如果希望启用对 C++ 异常处理的支持,请选中此复选框。如果启用此复选框,Android Studio 会将 -fexceptions 标                                     志添加到模块级 build.gradle文件的 cppFlags中,Gradle 会将其传递到 CMake。
Runtime Type Information Support:如果希望支持 RTTI,请选中此复选框。如果启用此复选框,Android Studio 会将 -frtti 标志添加到模                                    块级 build.gradle文件的 cppFlags中,Gradle 会将其传递到 CMake。

3、创建好的工程

创建好的工程多了cpp目录,这是写c++的包,还多了CMakeLists.txt,这是编译代码,makefile都帮我们写好了,我们用的时候只需要修改里面的代码即可:

看一下build.gradle:

android {
    compileSdkVersion 28
    defaultConfig {
        applicationId "com.jni.jnidemo"
        minSdkVersion 26
        targetSdkVersion 28
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
        externalNativeBuild {
            cmake {
                // 默认是 "cppFlags" "" ,如果要修改 Customize C++ Support 部分,可在这里加入cppFlags "-frtti -fexceptions"
                cppFlags ""
            }
        }
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
        }
    }
    // 指定c++编译代码的路径
    externalNativeBuild {
        cmake {
            path "CMakeLists.txt"
        }
    }
}

三、总结

进行ndk开发要掌握的步骤:

1、在cpp包下创建自己的.cpp或者.c文件,编写自己的c语言程序

2、在CMakeLists.txt中添加add_library,可以生成多个library,所以add_library可以自己在后面加

     在CMakeLists.txt中添加target_link_libraries,它也是一样,可以在后面自己加,不过这个不是必须的

3、在界面中引用一个库:

static {
    System.loadLibrary("native-lib");
}

4、把用c/c++写的方法用native来声明:

public native String stringFromJNI();

5、经过以上步骤就可以像普通的方法一样来调用了

四、注意

1、在Activity或者fragment里面新加的native方法如果.cpp文件里面没有就会报错,这时候只需要在native方法上Alt + Enter就会自动在cpp文件里面生成

2、不同厂商的 Android 手机支持的 CPU 架构不同,我们可以这样来限制我们支持的架构

defaultConfig {
    applicationId "com.jni.jnidemo"
    minSdkVersion 26
    targetSdkVersion 28
    versionCode 1
    versionName "1.0"
    externalNativeBuild {
        cmake {
            cppFlags ""
        }
    }

    ndk {
        abiFilters 'armeabi'//,'armeabi-v7a','arm64-v8a','x86','x86_64','mips','mips64'
    }
}

3、常用工具类:把Java字符串转化成c语言字符串

// 把Java字符串转化为C语言字符串
char* Jstring2CStr(JNIEnv*   env,   jstring   jstr)
{
    char*   rtn   =   NULL;
    jclass   clsstring   =   (*env)->FindClass(env,"java/lang/String");
    jstring   strencode   =   (*env)->NewStringUTF(env,"GB2312");
    jmethodID   mid   =   (*env)->GetMethodID(env,clsstring,   "getBytes",   "(Ljava/lang/String;)[B");
    jbyteArray   barr=   (jbyteArray)(*env)->CallObjectMethod(env,jstr,mid,strencode); // String .getByte("GB2312");
    jsize   alen   =   (*env)->GetArrayLength(env,barr);
    jbyte*   ba   =   (*env)->GetByteArrayElements(env,barr,JNI_FALSE);
    if(alen   >   0)
    {
     rtn   =   (char*)malloc(alen+1);         //"\0"
     memcpy(rtn,ba,alen);
     rtn[alen]=0;
    }
    (*env)->ReleaseByteArrayElements(env,barr,ba,0);  //
    return rtn;
} 

猜你喜欢

转载自blog.csdn.net/helloworld19870427/article/details/85679248