Android studio NDK成长记录(一)CMake

Android studio NDK开发支持CMake和ndk-build两种编译方式:

第一种:CMake编译方式的开发步骤

  1. 下载安装studio     下载地址:“http://www.android-studio.org/
  2. 新建项目
  3. 下载安装ndk插件:File右键->setting->Android SDK->SDK Tool勾选CMake,LLDB,NDK,将这三个插件全都安装上。
  4. 查看是否关联上NDK,也可以手动添加(local.properties末尾加上如下代码)
    //这是自己的ndk地址,注意转义,下面的地址本来是"E:\Android\SDK\ndk-bundle"
    ndk.dir=E\:\\Android\\sdk\\ndk-bundle
    Android studio NDK成长记录(一)CMake_第1张图片
  5. gradle.properties文件末尾添加代码"android.useDeprecatedNdk=true"(为了适配低版本)
  6. 在module(如app:)目录下创建一个CMake的配置文件(CMakeLists.txt,必须是这个名字,这个文件是用于关联上gradle和CMake的),必须配置以下几个基本属性,如有需要并熟悉CMake语法,可自行酌情增加,可参考下面CMakeLists.txt的配置。(也可以在创建项目的时候勾选上support c++,studio就会自动创建该文件,并配置好gradle,并且会在MainActivity中生成一个native方法,创建一个cpp文件,和一个native-lib.cpp文件。这时候只需要去修改CMakeLists.txt中的参数,并且删除cpp中自动生成的cpp文件,改成自己想要的就行。
    #CMakeLists.txt配置内容如下
    #版本
    cmake_minimum_required(VERSION 3.4.1)
    
    add_library( 
                # 决定编译出来的so库的名称(这个配置文件得到的是libhello.so).
                 hello
                 # 动态 这样studio会将so库打包到你的apk中
                 SHARED  
                 #c文件的地址,若有多个文件,直接一一列出,以空格或者换行隔开       
                 src/main/cpp/hello.c src/main/cpp/test.c)
    
    find_library( # Sets the name of the path variable.
                  log-lib
    
                  # Specifies the name of the NDK library that
                  # you want CMake to locate.
                  log )
    
    target_link_libraries( # Specifies the target library.
                           hello
    
                           # Links the target library to the log library
                           # included in the NDK.
                           ${log-lib} )
  7. 关联CMake和gradle,配置这个的主要原因是为了让studio在编译的时候能找到你的资源文。
    有两种方式:有的同学不一定Link C++ Project with Gradle选项,就用第二种
    (1)自动关联,将工程改为Android视图,右键选中module(如app),选择Link C++ Project with Gradle,下拉选项中选择CMake,浏览找到你的项目中的CMakeLists.txt文件。(2.)手动关联,在module(如app)下的build.gradle中做如下配置externalNativeBuild属性
    Android studio NDK成长记录(一)CMake_第2张图片
    android {
        compileSdkVersion 25
        buildToolsVersion "25.0.0"
        defaultConfig {
            applicationId "com.picovr.ndksupporttest"
            minSdkVersion 15
            targetSdkVersion 25
            versionCode 1
            versionName "1.0"
            externalNativeBuild {
                cmake {
                    cppFlags "-frtti -fexceptions"  }
            }
        }
        buildTypes {
            release {
                minifyEnabled false
                proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'
            }
        }
        externalNativeBuild {
            cmake {
                path "CMakeLists.txt"  }
        }
    }
  8. 创建一个java类,在里面申明一个native方法
    package com.picovr.ndksupporttest.mynative;
    
    /**
     * Created by PICO-USER Dragon on 2017/1/17.
     */
    
    public class JNI {
        public static native String getString();
    }
  9. 创建.c或者cpp源文件,和头文件。(下面以c语言为例)
    第一种方式:
    在mian目录下新建cpp文件夹。
    选中Android Studio的左下角Terminal面板,输入命令“cd app/src/main/java”进入java目录,执行命令“javah 包名+类名“,这个命令是调用jdk中的javah.exe程序对native方法所在的Java类生成一个对应的.h头文件。这种方式生成的.h头文件中,自动将native方法在C语言中所对应的方法名全部生成出来了。然后将生成的.h文件剪切到cpp文件夹,并将.h文件中放方法名称copy到c文件中,将参数补全即可。
    生成.h文件的命令如:“javah com.picovr.ndksupporttest.mynative.JNI”
    第二种方式:
    在main目录新建文件夹cpp,右键新建C/C++ Source File 勾选上Create an asscoiated hearder,这样就会生成一个.c文件和.h的头文件,这个.h文件不会像第一种方式那样自动生成native方法在C语言中所对应的方法名,需要自己手动去写。在学习阶段建议手动去做,更好地了解并熟悉jni的一些规则。
    java中的native方法对应C语言中的方法的规则在下面的代码中已经详细解释:
    copy下面的代码的时候,导包hello.h和jni.h分别copy,因为每个人的头文件名字不一样。ndk安装路径也不一样,所以jni.h所在目录不一样。
    /* Created by PICO-USER Dragon on 2017/1/17.
      导包的时候要注意
      1.你自己创建的.h文件必须要
      2.jni.h必须要,这个导包的时候,studio应该会提示,其实就是你安装ndk所在目录下的platforms目录中的任意
      一个版本中,可以在电脑中按照下面jni.h的那个路径中找来看看
     */
    #include "hello.h" #include "../../../../../../Android/SDK/ndk-bundle/platforms/android-21/arch-x86_64/usr/include/jni.h"
    #include 
    #include 
    /**
     * 命名规则:返回值类型 + 方法名
     * 方法名:Java+包名+类名+方法名,并且把'.'改为'_'
     *
     * JNIEXPORT和JNICALL 可要可不要string Java_com_picovr_ndksupporttest_mynative_JNI_getString(JN *IEnv *env, jobject jobj)也行
     *
     * jstring 是返回值对应java中的String类
     * JNIEnv *env 必须参数,在C中必须要用到这个参数去调用方法
     * jobject jobj 必须参数 不一定用到
     */
    JNIEXPORT jstring JNICALL
    Java_com_picovr_ndksupporttest_mynative_JNI_getString(JNIEnv *env, jobject jobj) {
    
        //jstring     (*NewStringUTF)(JNIEnv*, const char*);其实是在调用ndk-build中的jni.h中的方法
        return (*env)->NewStringUTF(env, "The first jinDemo for Dragon !");
    
    }
  10. 加载动态链接库
    在native方法所在类中增加静态代码块,加载动态链接库
    package com.picovr.ndksupporttest.mynative;
    
    /**
     * Created by PICO-USER on 2017/1/17.
     */
    
    public class JNI {
    
        // Used to load the 'native-lib' library on application startup.
        static {
            //"hello"是so库的名字,也就是CMakeLists.txt文件中add_library()属性中的第一个参数
            System.loadLibrary("hello");
        }
    
        public static native String getString();
    
    }
  11. 调用native方法getstring()。看看是否能成功调用。



你可能感兴趣的:(Android,JNI)