The construction process of JNI development applications on Android is basically the same. The following describes the construction process of jni apk Based on the surfaceview function of JNI layer painting on Android.
APK directory structure:
├── 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. Static block loading dynamic library in Java class and local method declaration at Java layer:
Static {
System. loadlibrary ("surfaceviewjni ");
}
Private native void nativesetsurface (surface );
Private native void nativedraw (string path, int width, int height );
2. Compile 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. Compile 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. Bind the Java layer and Local interface to the C/C ++ code
The key point here is the jni_onload function. When the Java layer loads the dynamic library, the virtual opportunity first calls jni_onload in the dynamic library. Therefore, the Java layer interface and Local interface are bound to the jni_onload function for initialization, this is also the practice of the android framework.
Put it in a file:
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. Implementation interface code:
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. Compile the JNI directory in ndk_build and generate the dynamic library to the libs directory,
Run mm in the root directory of the APK to generate the APK.
Note:
Here, the local code uses the log interface Android/log. h provided by ndk, so you need to connect to the log dynamic library parameters in makefile.
LOCAL_LDLIBS := \ -lm -lstdc++ -lgcc -llog
The above C ++ code includes Java-> C ++ calls and C ++-> JAVA anti-calls.
OK.
Csdn lidp original, reposted the famous source, thank you.