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 #include #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 #include #include #include #include "logger.h"#include 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 *)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(安卓)ListView 去除边缘阴影、选中色、拖动背景色等
  2. android第二行代码总结:二、UI
  3. Android(安卓)5.0 Phone初始化分析
  4. Android(安卓)5.0 Telephony关键类初始化和相互关系
  5. 实现底部导航栏中间凸起
  6. Android(安卓)蓝牙4.0代码解析
  7. Android版本与Linux内核版本的关系
  8. 【Android】Android(安卓)代码判断当前设备是否为模拟器
  9. android 实现 搜索保存历史记录功能

随机推荐

  1. Android TextUtils类常用方法
  2. Android 9.0 System.loadLibrary 的源码
  3. Windows下编译使用Android(安卓)NDK,调用S
  4. Android 中屏蔽 Home 键
  5. 列出sdcard里所有.mp3文件,并且可以点击
  6. [Android][MediaRecorder] Android(安卓)
  7. 【技术直通车】ArcGIS Runtime SDK for A
  8. ButterKnife初级用法
  9. java和Android文件下载断点续传和图片下
  10. android获取网络数据