重要提醒:
对于现阶段的AS NDK而言,读者往往因为各项参数配置的不合理而出错,这是读者最关心的。本文的各项参数对应关系如下:
(1)Android Studio 版本:2.0;
(2)compileSdkVersion = 23;
(3)buildToolsVersion = "23.0.3";
(4)gradle-experimental版本:com.android.tools.build:gradle-experimental:0.7.0-rc1;
(5)NDK版本:通过Android Studio下载最新的;
(6)JDK版本:1.7。
博文推荐:
AS NDK开发错误汇总:http://www.cnblogs.com/zhuyp1015/p/4976116.html
较好的介绍文章:http://yanbober.github.io/2015/02/14/android_studio_jni_1/
一、准备工作
(1)安装Android Studio2.0(低版本不支持NDK,因此建议安装较高版本);
(2)通过AS安装NDK,并指定NDK路径;
(3)通读Android Studio NDK开发官方文档(http://tools.android.com/tech-docs/new-build-system/gradle-experimental),通读后,可以避免很多坑。所以,通读后,再看下文。
(4)AS NDK开发比Eclipse NDK开发的好处:不再需要Android.mk文件和Application.mk文件。
二、目标
使用AS建立NDK工程:
(1)在与文件 MainActivity.java 相同的目录下,建立 jni 文件夹,在 jni 目录下,添加 HelloWorld.java 文件,在 HelloWorld.java 文件中,loadLibrary并声明native方法SayHelloWorld;
(2)在MainAcrivity.java中调用SayHelloWorld方法;
(3)通过javah命令,利用jni/HelloWorld.java创建头文件com_XX_XX_myapplication_jni_HelloWorld.h;
(4)实现源文件文件com_XX_XX_myapplication_jni_HelloWorld.cpp。
(5)目录结果见上图。
三、简要步骤及代码
由Android NDK官方文档可知,Android NDK工程与普通工程在如下3个配置文件(红色)处有不同,需要分别进行修改。
(1)修改Project目录下的build.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-experimental:0.7.0-rc1'
// NOTE: Do not place your application dependencies here; they belong
// in the individual module build.gradle files
}
}
allprojects {
repositories {
jcenter()
}
}
(2)修改app目录下的build.gradle文件:
apply plugin: 'com.android.model.application'
model {
android {
compileSdkVersion = 23
buildToolsVersion = "23.0.3"
defaultConfig {
applicationId = "com.tencent.xanderli.myapplication"
minSdkVersion.apiLevel = 17
targetSdkVersion.apiLevel = 23
}
ndk {
moduleName = "helloworld"
toolchain = 'clang'
CFlags.addAll(['-Wall'])
}
buildTypes {
release{
minifyEnabled = false
proguardFiles.add(file('proguard-rules.txt'))
}
}
tasks.withType(JavaCompile) {
sourceCompatibility = JavaVersion.VERSION_1_7
targetCompatibility = JavaVersion.VERSION_1_7
}
productFlavors {
// for detailed abiFilter descriptions, refer to "Supported ABIs" @
// https://developer.android.com/ndk/guides/abis.html#sa
create("arm") {
ndk.abiFilters.add("armeabi")
}
create("arm7") {
ndk.abiFilters.add("armeabi-v7a")
}
create("arm8") {
ndk.abiFilters.add("arm64-v8a")
}
create("x86") {
ndk.abiFilters.add("x86")
}
create("x86-64") {
ndk.abiFilters.add("x86_64")
}
create("mips") {
ndk.abiFilters.add("mips")
}
create("mips-64") {
ndk.abiFilters.add("mips64")
}
// To include all cpu architectures, leaves abiFilters empty
create("all")
}
}
}
dependencies {
compile fileTree(dir: 'libs', include: ['*.jar'])
compile 'com.android.support:appcompat-v7:23.3.0'
}
(3)修改gradle/wrapper/gradle-wrapper.properties文件:
#Mon Dec 28 10:00:20 PST 2015
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-2.10-bin.zip
(4)修改Local.propeties文件,指定SDK及NDK位置:
## 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.
#Mon May 02 21:20:00 CST 2016
ndk.dir=D\:\\develop\\AS\\SDK\\ndk-bundle
sdk.dir=D\:\\develop\\AS\\SDK
(5)修改gradle.properties文件(如果需要设置代理的话,修改该文件,否则跳过)
systemProp.http.proxyHost=xxx.xxx.com
systemProp.http.nonProxyHosts=xxx.xxx.com
systemProp.http.proxyPort=xxx
systemProp.https.proxyHost=xxx.xxx.com
systemProp.https.nonProxyHosts=xxx.xxx.com
systemProp.https.proxyPort=xxx
public class HelloWorld {
static {
System.loadLibrary("helloworld");
}
public static native String SayHelloWorld();
}
(7)利用javah命令生成native头文件,具体方法,自行Google。
在Eclipse创建的Android 工程目录下,javah执行方法如下:
需要注意的是,在笔者电脑上存在如下问题,供参考:
(1)在java 1.6下 ,Javah不能用,换成Java1.7,javah可以。
(2)javah执行的目录,需要是在src目录下,右键,在此打开命令窗口。因此,在Android Studio下面,就是在app/src/main/java窗口下执行。总体要求就是,后面的HelloWorld3,前面的必须是一个包名。
如果能正常执行javah,生成的头文件就不会出错,这里不贴出头文件的源代码。(8)src/main/jni/源文件的代码:
#include
#include
#include "com_xxx_xxx_myapplication_jni_HelloWorld.h"
JNIEXPORT jstring JNICALL Java_com_tencent_xanderli_myapplication_jni_HelloWorld_SayHelloWorld(JNIEnv *env,jclass){
return env->NewStringUTF("你比四环多一环");
}
(9)在MainActivity.java中,调用Native方法:
package com.tencent.xanderli.myapplication;
import android.app.Activity;
import android.app.AlertDialog;
import android.os.Bundle;
import static com.xxx.xxx.myapplication.jni.HelloWorld.SayHelloWorld;
public class MainActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new AlertDialog.Builder(this).setMessage(SayHelloWorld()).show();
}
}
注意:
在MainActivity.java中,需要静态导入native方法SayHelloWorld( ),否则,会报如下错误:
此时,在SayHelloWorld()函数上,Alt+Enter,会出现如下提示:
按照提示,点击,就可以自动添加如下代码到MainActivity.java文件中。
import static com.tencent.xanderli.myapplication.jni.HelloWorld.SayHelloWorld;
四、运行截图