Android Studio1.5中NDK开发

从Android Studio1.3以后,在Android 环境开发JNI程序搭建开发环境变得相对简单。这里就来介绍一下基于Android Studio如何进行jni开发。在介绍之前,先跟大家说一下JNI和NDK都是什么,方便大家理解。

NDK和JNI的关系

JNI是java语言提供的Java和C/C++相互沟通的机制,Java可以通过JNI调用本地的C/C++代码,本地的C/C++的代码也可以 调用java代码。JNI 是本地编程接口,Java和C/C++互相通过的接口。Java通过C/C++使用本地的代码的一个关键性原因在于C/C++代码的高效性。
NDK是一系列工具的集合。它提供了一系列的工具,帮助开发者快速开发C(或C++)的动态库,并能自动将so和java应用一起打包成apk。这 些工具对开发者的帮助是巨大的。它集成了交叉编译器,并提供了相应的mk文件隔离CPU、平台、ABI等差异,开发人员只需要简单修改mk文件(指出“哪 些文件需要编译”、“编译特性要求”等),就可以创建出so。它可以自动地将so和Java应用一起打包,极大地减轻了开发人员的打包工作。

然后跟大家说一下环境的搭建

环境说明:

  • IDE:Android Studio 1.5
  • JDK: 1.7.0_67
  • Gradle:2.8
  • SDK with Build Tools at least version 23.0.2

使用Android Studio内置的SDK管理器下载NDK。

Android Studio1.5中NDK开发_第1张图片

对NDK进行关联

这里写图片描述
Android Studio1.5中NDK开发_第2张图片

这里也可以去修改工程下的local.properties

## This file is automatically generated by Android Studio.
# Do not modify this file -- YOUR CHANGES WILL BE ERASED!
#
# This file must *NOT* be checked into Version Control Systems,
# as it contains information specific to your local configuration.
#
# Location of the SDK. This is only used by Gradle.
# For customization when using a Version Control System, please read the
# header note.
#Thu Mar 03 11:29:37 CST 2016
ndk.dir=C\:\\software\\sdk\\ndk-bundle
sdk.dir=C\:\\software\\sdk

设置gradle

设置好NDK之后,开始设置gradle,设置gradle主要需要设置三个地方,设置好之后就可以直接编写和编译JNI代码了,不需要像以前一样编写Makefile,相当方便。但是设置gradle也是需要比较小心的,由于当前NDK还处于Experimental 阶段,更新不断,经常会爆出各种奇怪的错误,因此也要特别留心。好了废话不多说,下面来介绍设置gradle的三个主要步骤。

首先设置TopLevel gradle,也就是Project gradle,这里比较简单。

// Top-level build file where you can add configuration options common to all sub-projects/modules.

buildscript {
    repositories {
        jcenter()
    }
    dependencies {
//        classpath 'com.android.tools.build:gradle:1.5.0'
        classpath 'com.android.tools.build:gradle-experimental:0.4.0'

        // NOTE: Do not place your application dependencies here; they belong
        // in the individual module build.gradle files
    }
}

allprojects {
    repositories {
        jcenter()
    }
}

task clean(type: Delete) {
    delete rootProject.buildDir
}

还要多提一句的是,这里设置的是gradle-experimental:0.4.0,后面对应设置gradle wrapper的时候要对应gradle2.8-all 版本,这里先说到这里。

#Wed Oct 21 11:34:03 PDT 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.8-all.zip

接着设置 Module gradle,这一步是比较麻烦的。由于我们在创建工程的时候自动生成的这个gradle文件内容比较多,而且如果要使用NDK的话这个gradle变化比较大,这里直接贴出需要使用NDK的gradle,然后来进行说明。

apply plugin: 'com.android.model.application'

model {
    android {
        compileSdkVersion = 23
        buildToolsVersion = "23.0.2"

        defaultConfig.with {
            applicationId = "com.oracleen.rl.easyar"
            minSdkVersion.apiLevel = 15
            targetSdkVersion.apiLevel = 23
            versionCode = 1
            versionName = "1.0"
        }
    }
    android.ndk {
        moduleName = "HelloARVideoNative"
        cppFlags.add("-I${file("../../package/include")}".toString())
        cppFlags.add("-DANDROID")
        cppFlags.add("-fexceptions")
        cppFlags.add("-frtti")
        stl = "gnustl_static"
        ldLibs.add("log")
        ldLibs.add("GLESv2")
    }
    android.buildTypes {
        release {
            minifyEnabled = false
            proguardFiles.add(file("proguard-rules.pro"))
        }
    }

    android.productFlavors {
        create("arm") {
            ndk.with {
                abiFilters.add("armeabi-v7a")
            }
        }
    }
    android.sources {
        main {
            jni {
                dependencies {
                    library file("../../package/Android/libs/armeabi-v7a/libEasyAR.so") abi "armeabi-v7a"
                }
            }
        }
    }
}

dependencies {
    //    compile fileTree(dir: 'libs', include: ['*.jar'])
    testCompile 'junit:junit:4.12'
    compile 'com.android.support:appcompat-v7:23.0.1'
    compile fileTree(dir: '../../package/Android/libs', include: ['*.jar'])
}

和自动生成的gradle相比,首先是 apply plugin: ‘com.android.application’ 变成了 apply plugin: ‘com.android.model.application’。下面的配置也需要包装在model{}中。

这个gradle的配置有几点需要注意的:

  1. 所有值的设置都要写成 xxx = yyyy的形式,比如: applicationId = “com.oracleen.rl.easyar” ,否则会报这种错误:Error:Cause: org.gradle.api.internal.ExtensibleDynamicObject, 当出现此类错误,检查是否都用了 “=”的方式。
  2. buildTypes 需要从android{} 中取出来,写成android.buildTypes{}的形式,否则会出现这种错误:Error:Unable to load class ‘org.gradle.nativeplatform.internal.DefaultBuildType_Decorated’. 内容也需要改为上边文件中的格式,否则会报这种错误:Error:No signature of method: org.gradle.model.ModelMap.minifyEnabled() is applicable for argument types: (java.lang.Boolean) values: [false]
  3. defaultConfig{} 需要写成defaultConfig.with{} 的形式,否则会报这种错误:Error:Cause: com.android.build.gradle.managed.AndroidConfig_Impl
  4. 在defaultConfig.with{} 中 需要写成上边格式,也就是比自动生成的多 .apiLevel ,否则会报这种错误:Unable to load class com.android.build.gradle.managed.ProductFlavor_Impl 
  5. 最后一点,在gradleWrapper中使用的是2.5,则android.ndk {} 中类似cppFlags 的添加使用 += 的方式,否则需要使用 .add的方式
  6. 引用的其他model构建方式也要包装在model{}当中。

NDK开发主要有两中情况:一种是使用已经编译好的.so动态库;一种是使用c/c++源代码开发。我会分别介绍。

编译c/c++源代码开发

这里我们起一个名字是“HelloARVideoNative”的JNI库,androidstudio会把我们编写的c/c++代码编译成这个名字的.so文件。

android.ndk {
        moduleName = "HelloARVideoNative"
        stl = "gnustl_static"
        ldLibs.add("log")
        ldLibs.add("GLESv2")
    }

然后我们在我们需要使用c/c++方法的类中引用库,并且声明本地接口。

Android Studio1.5中NDK开发_第3张图片

然后就可以去c/c++文件中去实现我们的方法了。

Android Studio1.5中NDK开发_第4张图片

使用已经编译好的.so动态库

在app下的gradle中做如下配置

 android.sources {
        main {
            jni {
                dependencies {
                    library file("../../package/Android/libs/armeabi-v7a/libEasyAR.so") abi "armeabi-v7a"
                }
            }
        }
    }

指向我们的so库文件位置,然后在需要引用的地方

static {
        System.loadLibrary("EasyAR")
    }

然后我们就可以使用so库中的方法了。

Android Studio1.5中NDK开发_第5张图片

最后,附上相关的资源.其实在android的官网已经提供了很完善的教程了.还有github上也托管了sample代码.

Experimental Plugin User Guide: http://tools.android.com/tech-docs/new-build-system/gradle-experimental
github sample: https://github.com/googlesamples/android-ndk
官方ndk视频教程: https://youtu.be/okLKfxfbz40 (需要)

你可能感兴趣的:(NDK)