介绍了在Android Studio
中配置NDK的开发环境:Android Studio NDK开发-环境配置,NDK开发环境配置完成以后,就要写一下著名的Hello World
程序了。
在开始以前须要先介绍下Java和c/c++通讯:JNI,JNI(Java Native Inteface)是Java平台的一部分,它容许Java代码和其余语言写的代码进行交互。尤为是c/c++,可是并不妨碍你使用其余语言,只要调用约定支持就能够了。NDK上Java和c/c++有两种交互方式:javascript
这里使用的是第一种交互方式,即Java调用c/c++。java
##建立JNI目录
打开Android Studio
,新建一个项目,右键点击App
(对应的module)新建一个JNI目录:android
jni
目录:
##新建Java类
新建一个HelloJni.java的类,用来和NDK交互:c++
package com.example.jjz.jni;
public class HelloJni {
//定义一个jni的方法
public native String sayHello();
}复制代码
HelloJni中使用关键词native
定义了一个方法,native
:一个Natvie Method就是一个Java调用非Java代码的接口,该方法的实现由c/c++实现。
方法定义完以后能够看到一个提示,没有sayHello
的实现。git
这是由于并无实现对应的c/c++的方法,下面就须要使用c/c++使用sayHello
方法。github
##gradle中支持NDKapp
Android Studio
从1.3开始就支持了对于NDK的开发,能够在gradle配置NDK的开发选项,首先在bulid.gradle
中设置ndk的的moduleName:函数
defaultConfig {
applicationId "com.example.jjz.jni"
minSdkVersion 15
targetSdkVersion 23
versionCode 1
versionName "1.0"
//指定.so的目录
sourceSets.main{
jniLibs.srcDir 'src/main/libs'
}
ndk{
moduleName 'hello'
}
}复制代码
在进行同步gradle的时候出现了一个错误:post
NDK integration is deprecated in the current plugin
set "android.useDeprecatedNdk=true"in gradle.properties to continue using the current NDK integration复制代码
根据提示须要在gradle.properties中设置android.useDeprecatedNdk=true
。gradle
#生成.h文件
Java
中使用调用NDK的方法,要先生成.h头文件,JNI
的.h文件规则:
JNIEXPORT
.
变成_
。_
分割例如上面的sayHello
方法转换为JNI的方法为:
JNIEXPORT jint JNICALL
Java_com_example_jjz_jni_HelloJni_sayHello(JNIEnv *env, jobject instance, jint a) {
}复制代码
这种定义规则很复杂,不容易手写,还好能够经过javah
命令自动生成。
在app/目录下运行命令:
javah -d src/main/jni/ -classpath build/intermediates/classes/debug/ com.example.jjz.jni.HelloJni
其中-d
是生成.h文件的保存目录。-classpath
是指定.class所在的目录,项目build成功以后,会在build/intermediates/classes/debug/
目录里生成.class文件。com.example.jjz.jni.HelloJni
是包名加上类名。
就能够在jni目录下获得一个com_example_jjz_jni_HelloJni.h
的文件,文件内容以下:
/* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/
* Header for class com_example_jjz_jni_HelloJni */
#ifndef _Included_com_example_jjz_jni_HelloJni
#define _Included_com_example_jjz_jni_HelloJni
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_jjz_jni_HelloJni
* Method: sayHello
* Signature: ()Ljava/lang/String;
*/
JNIEXPORT jstring JNICALL Java_com_example_jjz_jni_HelloJni_sayHello
(JNIEnv *, jobject);
#ifdef __cplusplus
}
#endif
#endif复制代码
.h
文件只是一个声明文件,还须要实现.h文件中定义的方法
添加.c文件
新建文件com_example_jjz_jni_HelloJni.c
用来文件实现sayHello
方法。
#include "com_example_jjz_jni_HelloJni.h"
JNIEXPORT void JNICALL JNIEXPORT jstring JNICALL Java_com_example_jjz_jni_HelloJni_sayHello(JNIEnv *env, jobject object) {
return (*env)->NewStringUTF(env, "Hello Jni");
}复制代码
添加Application.mk文件
APP_MODULES := hello
APP_ABI :=all复制代码
添加Android.mk文件
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
LOCAL_MODULE :=hello
LOCAL_SRC_FILES =: com_example_jjz_jni_HelloJni.c
include $(BUILD_SHARED_LIBRARY)复制代码
##编译调用
文件添加完成以后就可使用NDK编译了,在../app/src/main/jni目录下,运行命令
ndk-build
运行以后能够看到生成的libhello.so文件:
注意这个时候.so
文件已经生成,可是在java中并无加载.so
类库,必须加载.so
类库才能被Java使用,加载的方式使用使用函数System.loadLiabrary("hello")
:
public class HelloJni {
static {
//加载.so类库,加载的名称去掉lib
System.loadLibrary("hello");
}
public native int sayHello(int a);
}复制代码