android上 jni开发 应用构建过程基本一致,下面 结合最近 在android 上实现 jni层 绘制 surfaceview 功能 阐述 带jni的apk构建过程。


apk 目录结构:


├── AndroidManifest.xml├── Android.mk├── jni│ ├── Android.mk│ ├── logger.cpp│ ├── logger.h│ ├── OnLoad.cpp│ └── SurfaceviewJni.cpp├── libs│ └── armeabi│     └── libsurfaceviewJni.so├── res│ ├── layout│ │ └── hello_activity.xml│ └── values│     └── strings.xml└── src    └── com        └── example            └── android                └── jnisurfaceview                    ├── JavasurfaceView.java                    └── JniSurfaceViewActivity.java



1. java类中 static 块 加载动态库及java层本地方法声明 :

static {

System.loadLibrary("surfaceviewJni");
}

private native void nativeSetSurface(Surface surface);
private native void nativeDraw(String path ,int width, int height);

2 . 编写 jni makefile

jni/Android.mk

#lib for jnisurfaceviewLOCAL_PATH := $(call my-dir)include $(CLEAR_VARS)LOCAL_LDLIBS := \        -lm -lstdc++ -lgcc -llogLOCAL_SRC_FILES := \OnLoad.cpp \SurfaceviewJni.cpp \                logger.cpp#LOCAL_SHARED_LIBRARIES := libsurfaceviewJniLOCAL_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libutils LOCAL_MODULE := libsurfaceviewJniinclude $(BUILD_SHARED_LIBRARY)

3. 编写 apk makefile


LOCAL_PATH:= $(call my-dir)include $(CLEAR_VARS)# Only compile source java files in this apk.LOCAL_SRC_FILES := $(call all-java-files-under, src)LOCAL_PACKAGE_NAME := JniSurfaceView#LOCAL_JNI_SHARED_LIBRARIES := libsurfaceviewJni#LOCAL_PRELINK_MODULE := falseinclude $(BUILD_PACKAGE)


4. C/C++代码中绑定java层和本地接口


这里的关键点在JNI_OnLoad 函数,java层在 load 动态库时虚拟机会首先调用动态库中的JNI_OnLoad,所以 java层接口和本地接口的绑定在JNI_OnLoad 函数中初始化即可,这也是android framework 的做法。


放在一个文件中:

OnLoad.cpp


/* * Desc: jni code for surfaceview * Author :lidp */ #include <android/log.h>#include <jni.h>#include "logger.h"#define TAG_JNISURFACEVIEW "jni surfaceview test"static JavaVM *jvm = NULL;int register_jnisurfaceview(JNIEnv* env);JNJEnv* getEnv(){JNIEnv* env = NULL;if(jvm->GetEnv(void**)&env, JNI_VERSION_1_4) != JNI_OK) {return NULL;droid_log(LOG_ERROR,"failed in get jvm\n");}return env;}//this function will be called by jvm on load shared libjint JNI_OnLoad(JavaVM *vm,void* reserved){JNIEnv* env = NULL;jint ret = JNI_ERR;droid_log(LOG_DEBUG,"Jni Onload be called\n");jvm = vm;if(jvm->GetEnv((void**)&env, JNI_VERSION_1_4) != JNI_OK) {droid_log(LOG_ERROR,"failed get jvm\n");return ret;}if(register_jnisurfaceview(env) != JNI_OK)return ret;;return JNI_VERSION_1_4;}

5. 实现接口代码:


SurfaceviewJni.cpp


#include <unistd.h>#include <stdio.h>#include <stdlib.h>#include <android/log.h>#include "logger.h"#include <jni.h>struct JavaGule {jobject jsurface;};static struct JavaGule gule;//code pase from framework jnihelp.cppstatic int jniRegisterNativeMethods(JNIEnv* env, const char* className, const JNINativeMethod* gMethods, int numMethods){    jclass clazz;droid_log(LOG_DEBUG, "register native method for class %s\n", className);    clazz = env->FindClass(className);    if (clazz == NULL)        return -1;    if (env->RegisterNatives(clazz, gMethods, numMethods) < 0)        return -1;    return 0;}static void jnisurfaceview_draw(JNIEnv *env, jobject obj, jstring photopath, jint w, jint h){droid_log(LOG_DEBUG, "native draw be called \n");jclass sufaceClass = env->FindClass("android/view/Surface");if(sufaceClass == NULL) {droid_log(LOG_ERROR,"Cant not find android/view/Surface class\n");return;}jfieldID surfaceID = env->GetFieldID(sufaceClass, "mSurface", "I");    if (surfaceID == NULL) {        droid_log(LOG_ERROR,"Can't find Surface.mSurface");        return;    }//sp<Surface> surface = (Surface *)env->GetIntField(gule.jsurface, surfaceID);/*if(surface.isValid()) {} else {droid_log(LOG_ERROR, "cant get surface\n");}*/}static void jnisurfaceview_setSurface(JNIEnv *env, jobject obj, jobject javasurface){droid_log(LOG_DEBUG, "native setSurface be called \n");gule.jsurface = javasurface;}static JNINativeMethod gmethods[] = {{"nativeDraw", "(Ljava/lang/String;II)V", (void *)jnisurfaceview_draw},{"nativeSetSurface", "(Landroid/view/Surface;)V", (void*)jnisurfaceview_setSurface},};int register_jnisurfaceview(JNIEnv* env){return jniRegisterNativeMethods(env,"com/example/android/jnisurfaceview/JavasurfaceView", gmethods, sizeof(gmethods)/sizeof(gmethods[0]));}


6. ndk_build 编译 jni目录,生成动态库到 libs目录,

apk 根目录 执行 mm 生成apk.


注意:

这里本地代码用到了 ndk提供的log 接口 android/log.h 所以在makefile中要连接log动态库 用参数

LOCAL_LDLIBS := \        -lm -lstdc++ -lgcc -llog

上面的 c++代码即包含 java->c++的调用也包含 C++ -> java的反调用。


ok.


csdn lidp 原创,转载著名出处,谢谢。



更多相关文章

  1. Android(安卓)浏览器的开发实例分享
  2. Android(安卓)Camera使用小结
  3. android全屏,去掉title栏的办法
  4. Android(安卓)对话框【Dialog】去除白色边框代码
  5. Android(安卓)Camera使用小结
  6. Android(安卓)应用指定浏览器开发实例
  7. Android(安卓)UI LinearLayout权限级别与TableLayout混合使用,
  8. Android(安卓)TextView Marquee的应用实例详解
  9. Android(安卓)设置默认锁屏壁纸接口

随机推荐

  1. Android语言切换原理
  2. Android OpenGL 显示基本图形及相关概念
  3. Android 5.x--使用Material Theme加Palet
  4. 关于Edittext点击弹出软键盘,布局上移标题
  5. Android(安卓)程序员学习 iOS ——UIView
  6. android 实例覆盖各个方面
  7. 瘸腿蛤蟆笔记cocos2d-x-3.2移植到到andro
  8. Android 快速开发框架,thinkandroid改变和
  9. 还在用枚举?我早就抛弃了!(Android(安卓)注
  10. Android之常见安全问题