昨天要写个apk 练习用opengl es 画图, 不想在java里边直接调opengles, 想通过jni在cpp里边去调, 所以需要加上jni代码, 弄了3小时才搞出来,感觉坑还有点多, 遂记录一下步骤方便后面使用, 添加jni的方法有多种,这里只记录下本人搞出来的那种.
声明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 .
坑1: 这边需要注意执行javah的路径为 app/src/main/java, 后面跟的是包名+类名,
生成的.h长的样子如下:
com_example_test1_Draw.h
//com_example_test1_Draw.h
/* DO NOT EDIT THIS FILE - it is machine generated */
#include
/* Header for class com_example_test1_Draw */
#ifndef _Included_com_example_test1_Draw
#define _Included_com_example_test1_Draw
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_test1_Draw
* Method: initImpl
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_test1_Draw_initImpl
(JNIEnv *, jobject);
/*
* Class: com_example_test1_Draw
* Method: resizeImpl
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_test1_Draw_resizeImpl
(JNIEnv *, jobject);
/*
* Class: com_example_test1_Draw
* Method: doDrawImpl
* Signature: ()V
*/
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
/* DO NOT EDIT THIS FILE - it is machine generated */
#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类型
/* Header for class com_example_test1_Draw */
#ifndef _Included_com_example_test1_Draw
#define _Included_com_example_test1_Draw
#ifdef __cplusplus
extern "C" {
#endif
/*
* Class: com_example_test1_Draw
* Method: initImpl
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_test1_Draw_initImpl
(JNIEnv *, jobject) {
LOGI("Java_com_example_test1_Draw_initImpl");
}
/*
* Class: com_example_test1_Draw
* Method: resizeImpl
* Signature: ()V
*/
JNIEXPORT void JNICALL Java_com_example_test1_Draw_resizeImpl
(JNIEnv *, jobject) {
LOGI("Java_com_example_test1_Draw_resizeImpl");
}
/*
* Class: com_example_test1_Draw
* Method: doDrawImpl
* Signature: ()V
*/
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
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根据自己的实际情况需求版本调
jni目录下使用ndk-build编译生成.so文件, 如下:
如果报这个错
Android NDK: WARNING: APP_PLATFORM android-17 is higher than android:minSdkVersion 1 in
通过在AndroidManifest.xml 添加如下代码解决,
其中, 17, 23 根据自己的实际情况需求版本调
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