概述
- Android Studio2.2开始支持使用ndk-build来构建NDK项目。
目录结构
- tree 项目根目录/app/src/main,得到以下文件树:
├── AndroidManifest.xml
├── java
│ └── com
│ └── daking
│ └── app
│ └── ndkdemo
│ ├── MainActivity.java
│ ├── NDKUtil.java // NDK的Java调用工具类
│ └── bean // 各实体类
│ └── User.java
├── jni
│ ├── Android.mk
│ ├── Application.mk
│ ├── api.c // 对外接口实现
│ ├── api.h // 对外接口定义
│ └── entrance.c // jni入口
└── res
build.gradle配置
- 指定Application.mk、输出abi等项目信息。
android {
defaultConfig {
externalNativeBuild {
ndkBuild {
// 指定Application.mk
arguments "NDK_APPLICATION_MK:=src/main/jni/Application.mk"
// 输出ABI
abiFilters "armeabi", "armeabi-v7a", "x86"
// c编译选项,可自定义,如ENABLE_DEBUG_LOG为控制是否输出debug日志
cFlags "-DENABLE_DEBUG_LOG"
}
}
}
}
- 指定Android.mk。
android {
externalNativeBuild {
ndkBuild {
path "src/main/jni/Android.mk"
}
}
}
文件详解
Application.mk
- 模板内容:
# 输出ABI
APP_ABI := armeabi
Android.mk
- 模板内容:
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)
# 模块名,此处为最终生成的共享库库名
LOCAL_MODULE := nativecode
# 包含的头文件
LOCAL_C_INCLUDES := \
$(NDK_PROJECT_PATH)
# 编译的源文件
LOCAL_SRC_FILES := \
entrance.c \
api.c
# 生成共享库
include $(BUILD_SHARED_LIBRARY)
api
-
api为对Java等上层公开的接口。其中api.h为函数定义,api.c为实现。
-
api.h模板内容:
#ifndef NDKDEMO_API_H
#define NDKDEMO_API_H
#include <jni.h>
#include <string.h>
#include <stdio.h>
jstring getLibName(JNIEnv* env, jobject obj);
#endif //NDKDEMO_API_H
- api.c模板内容:
#include <jni.h>
#include <string.h>
#include <stdio.h>
#include "api.h"
jstring getLibName(JNIEnv *env, jobject obj) {
return (*env)->NewStringUTF(env, "nativecode lib!");
}
entrance.c
-
App加载so库时,虚拟机首先会去执行
JNI_OnLoad()
。于是可在JNI_OnLoad方法中注册jni函数。 -
模板内容:
#include <jni.h>
#include <stdio.h>
#include "api.h"
// 各jni函数
static JNINativeMethod jniMethods[] = {
{"getLibName", "()Ljava/lang/String;", (void*)getLibName}
// 若有新jni方法,则用逗号分隔,添加新的元素。
};
int JNI_OnLoad(JavaVM *vm, void *reserved)
{
JNIEnv *env;
if ((*vm)->GetEnv(vm, (void **)&env, JNI_VERSION_1_4) != JNI_OK) {
return JNI_ERR;
}
jclass cls = (*env)->FindClass(env, "com/daking/app/ndkdemo/NDKUtil");
if (cls == NULL)
return JNI_ERR;
int len = sizeof(jniMethods) / sizeof(jniMethods[0]);
(*env)->RegisterNatives(env, cls, jniMethods, len);
return JNI_VERSION_1_4;
}
NDKUtil.java
- 模板内容:
package com.daking.app.ndkdemo;
public class NDKUtil {
static {
System.loadLibrary("nativecode");
}
public static native String getLibName();
}