Android Studio1.5中NDK开发

来源:互联网 发布:贵州大数据是什么 编辑:程序博客网 时间:2024/05/27 18:17

从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。

这里写图片描述

对NDK进行关联

这里写图片描述
这里写图片描述

这里也可以去修改工程下的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 2016ndk.dir=C\:\\software\\sdk\\ndk-bundlesdk.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 2015distributionBase=GRADLE_USER_HOMEdistributionPath=wrapper/distszipStoreBase=GRADLE_USER_HOMEzipStorePath=wrapper/distsdistributionUrl=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++方法的类中引用库,并且声明本地接口。

这里写图片描述

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

这里写图片描述

使用已经编译好的.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的官网已经提供了很完善的教程了.还有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 (需要翻墙)

2 0
原创粉丝点击