周末帮小弟弟看一个NDK的问题,回首又温习了一下NDK的部分知识,留个笔头。
1.新版AS中NDK 简单使用
- 新建一个Android项目勾上Include C++ Support ,会自动生成cpp目录
- C++ Standard:使用哪种 C++ 标准。选择 Toolchain Default 会使用默认的 CMake 设置。
- Exceptions Support:是否启用对 C++ 异常处理的支持
-
Runtime Type Information Support:是否启用运行时类型信息
这里简单写一个小Demo 更多信息
native-lib.cpp
#include <jni.h>
#include <string>
extern "C"
jstring
Java_cn_kerison_demo_ndk_MainActivity_stringFromJNI( JNIEnv *env, jobject /* this */) {
std::string hello = "Hello from C++";
return env->NewStringUTF(hello.c_str());
}
extern "C"
jstring
Java_cn_kerison_demo_ndk_MainActivity_getPackageName( JNIEnv *env, jobject _this, jobject context) {
jclass contextClass = env->FindClass("android/content/Context");
jmethodID methodID = env->GetMethodID(contextClass,"getPackageName","()Ljava/lang/String;");
jstring result = (jstring) env->CallObjectMethod(context, methodID);
const char *chars = env->GetStringUTFChars(result, false);
if (chars != NULL) {
env->ReleaseStringUTFChars(result, chars);
return env->NewStringUTF(chars);
}
return NULL;
}
MainActivity.java
public class MainActivity extends AppCompatActivity {
static {
//加载库文件
System.loadLibrary("native-lib");
}
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
TextView tv = (TextView) findViewById(R.id.sample_text);
//调用native方法
tv.setText(String.format("%s [%s]",stringFromJNI(),getString(this)));
}
//声明native方法
public native String stringFromJNI();
public native String getString(Context context);
}
2.NDK 编译方式
- NDK-Build
以前的NDK开发都是用NDK-Build编译的,依赖文件Android.mk。 详情
#调用宏my-dir切换到当前工程目录
LOCAL_PATH := $(call my-dir)
# 清除除了LOCAL_PATH以外的LOCAL_XXX临时变量
include $(CLEAR_VARS)
#编译生成的文件的类库叫什么名字
LOCAL_MODULE := hello
#要编译的c文件
LOCAL_SRC_FILES := Hello.c
#编译的架构类型
TARGET_ARCH_ABI := All
#编译库的类型脚本
include $(BUILD_SHARED_LIBRARY)
- CMake
新版的AS已经推荐直接使用CMake,CMake 构建脚本是一个纯文本文件,依赖文件CMakeLists.txt。
#设置CMake 的版本要求
cmake_minimum_required(VERSION 3.4.1)
#设置编译的库
add_library(
#设置库名
native-lib
#设置库的类型
SHARED
#设置库需要编译的文件
src/main/cpp/native-lib.cpp )
# 指定库的头文件目录
include_directories(src/main/cpp/include/)
#检查依赖的库
find_library(
#库的路径
log-lib
#库的名字
log )
#链接第三方库到目标库中
target_link_libraries(
#要链接库的名字
# native-lib
#链接的库
${log-lib} )
3.编译脚本指定
android {
...
defaultConfig {
...
externalNativeBuild {
//指定编译类型
cmake {...}
// or ndkBuild {...}
}
ndk {
//指明apk需要打包的架构类型
abiFilters 'x86', 'x86_64', 'armeabi', 'armeabi-v7a','arm64-v8a'
}
}
buildTypes {...}
externalNativeBuild {
cmake {
path "CMakeLists.txt"
}
// or ndkBuild {...}
}
}
4.NDK注意事项
- 一般NDK导出的包为[lib+库名称.so]使用时,系统会自动忽略识别lib字段和so扩展名
static {
System.loadLibrary(“native-lib”);
}
- 出现故障问题不编译或非代码问题,build下clean或refresh linked C++
- C/C++中的字符串和java的字符串需要进行转换
- C++ 使用时要兼容C模式: extern "C"
- 方法签名一定更要写对,可用javap命令查看签名或者javah生成头文件。
Java 类型 | 类型签名 |
---|---|
boolean | Z |
byte | B |
char | C |
short | S |
int | I |
long | L |
float | F |
double | D |
Class | (L+类的全路径+;),L是前缀,;是结束符,.用/代替,比如String, 其签名为Ljava/lang/util/String; |
Array | [类型签名, 比如 [B |
- 类型对照
java | jni |
---|---|
char | jchar |
byte | jbyte |
short | jshort |
int | jint |
long | jlong |
float | jfloat |
double | jdouble |
boolean | jboolean |
- 其他查看官网api
网友评论