android jni 程序框架搭建


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 jnisurfaceview
LOCAL_PATH := $(call my-dir)
include $(CLEAR_VARS)

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


LOCAL_SRC_FILES := \
		OnLoad.cpp \
		SurfaceviewJni.cpp \
                logger.cpp

#LOCAL_SHARED_LIBRARIES := libsurfaceviewJni
LOCAL_SYSTEM_SHARED_LIBRARIES := libc libstdc++ libutils 

LOCAL_MODULE := libsurfaceviewJni

include $(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 := false
include $(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 lib

jint 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.cpp
static 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 原创,转载著名出处,谢谢。



  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值