昨天要写个apk 练习用opengl es 画图, 不想在java里边直接调opengles, 想通过jni在cpp里边去调, 所以需要加上jni代码, 弄了3小时才搞出来,感觉坑还有点多, 遂记录一下步骤方便后面使用, 添加jni的方法有多种,这里只记录下本人搞出来的那种.
1. 编写声明native 接口的java文件声明3个native 接口
public native void initImpl();
public native void resizeImpl();
public native void doDrawImpl();
Draw.java
//Draw.java
package com.example.test1;
public class Draw {
public void init(){
initImpl();
}
public void resize() {
resizeImpl();
}
public void doDraw() {
doDrawImpl();
}
static {
System.loadLibrary("draw");
}
public native void initImpl();
public native void resizeImpl();
public native void doDrawImpl();
}
其中, 上边 System.loadLibrary(), 里边填的是后面咱们那些cpp代码要通过Android.mk编成的so库的名字,如我这由于命名为libdraw.so,所以填的draw .
2. 使用javac 生成 .class文件3. 使用javah 解析.class生成 .h文件
坑1: 这边需要注意执行javah的路径为 app/src/main/java, 后面跟的是包名+类名,
生成的.h长的样子如下:
com_example_test1_Draw.h
//com_example_test1_Draw.h #include4. 创建jni文件夹, 创建cpp文件#ifndef _Included_com_example_test1_Draw #define _Included_com_example_test1_Draw #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_com_example_test1_Draw_initImpl (JNIEnv *, jobject); JNIEXPORT void JNICALL Java_com_example_test1_Draw_resizeImpl (JNIEnv *, jobject); JNIEXPORT void JNICALL Java_com_example_test1_Draw_doDrawImpl (JNIEnv *, jobject); #ifdef __cplusplus } #endif #endif
鼠标选中app 文件夹, 然后 File ==> New ==> Folder ==> Jni Folder ,
然后路径选 src/main/jni, 如下:
创建完后如下, 是个空文件夹, 接着咱们再来创建.cpp文件, 添加编译脚本
里边添加个.cpp文件,根据自己需求含义命名,如我这边的Draw.cpp ,
然后把整个前面生成的.h内容拷贝过来, 往函数里边添加实现,写完该.h可以不要了, 如我这边添加的Draw.cpp
#include#include #define TAG "======>lkh" #define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型 #define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型 #define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型 #define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型 #define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型 #ifndef _Included_com_example_test1_Draw #define _Included_com_example_test1_Draw #ifdef __cplusplus extern "C" { #endif JNIEXPORT void JNICALL Java_com_example_test1_Draw_initImpl (JNIEnv *, jobject) { LOGI("Java_com_example_test1_Draw_initImpl"); } JNIEXPORT void JNICALL Java_com_example_test1_Draw_resizeImpl (JNIEnv *, jobject) { LOGI("Java_com_example_test1_Draw_resizeImpl"); } static bool printLogFirstTime = false; JNIEXPORT void JNICALL Java_com_example_test1_Draw_doDrawImpl (JNIEnv *, jobject) { if (printLogFirstTime == false) { LOGI("Java_com_example_test1_Draw_doDrawImpl"); printLogFirstTime = true; } } #ifdef __cplusplus } #endif #endif
5. 添加 Android.mk, Application.mk
jni目录下添加编cpp的mk文件,
Android.mk , 我这要生成叫libdraw.so的库所以LOCAL_MODULE 赋值 draw.
LOCAL_PATH := $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE := draw LOCAL_SRC_FILES := Draw.cpp LOCAL_LDLIBS += -llog LOCAL_LDLIBS += -lGLESv2 # use GL ext model LOCAL_CFLAGS += -DGL_GLEXT_PROTOTYPES include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_ABI := all APP_PLATFORM := android-17
其中, 17根据自己的实际情况需求版本调
6. 使用ndk-build 编译 生成.sojni目录下使用ndk-build编译生成.so文件, 如下:
如果报这个错
Android NDK: WARNING: APP_PLATFORM android-17 is higher than android:minSdkVersion 1 in
通过在AndroidManifest.xml 添加如下代码解决,
其中, 17, 23 根据自己的实际情况需求版本调
7. 添加 各种ndk配置build.gradle 添加 so打包路径, 不添加的话so没打包进去,apk一跑到jni代码就crash了,报找不到so库错误,
sourceSets {
main {
jni {
srcDirs 'src/main/jni'
}
jniLibs.srcDirs = ['src/main/libs']
}
}
gradle.properties 添加
android.useDeprecatedNdk=true
local.properties 添加 ndk路径
ndk.dir=/home/XXX/Android/Sdk/ndk-bundle



