积累系统性知识
积聚技术精华
  首页    个人中心    撰写积文    建立课题    订立目标    整理积文    管理课题    管理目标    技能Get    代码积累 
Android-JNI总结(1)
error997 (error997)    2015-05-10 19:11:13      目标    课题
   1>>JNI结构 (Java代码>JNI代码>C/C++代码)
   2>>一个MediaScanner调用例子
   1.java层:(加载函数库 库名由.mk文件配置)

切换到: 纯代码  
   
public class MediaScanner  
{  
    static {  
        System.loadLibrary("media_jni");//加载类库   
        native_init();//调用jni层代码   
    }  
     
    private static native final void native_init();  
  
}


   public class MediaScanner
{
    static {
        System.loadLibrary("media_jni");//加载类库
        native_init();//调用jni层代码
    }
   
    private static native final void native_init();

}

切换到: 纯代码  
   
static void  
android_media_MediaScanner_native_init(JNIEnv *env)//jni代码实现   
{  
     jclass clazz;  
  
    clazz = env->FindClass("android/media/MediaScanner");  
    if (clazz == NULL) {  
        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaScanner");  
        return;  
    }  
  
    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");  
    if (fields.context == NULL) {  
        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaScanner.mNativeContext");  
        return;  
    }  
}


   static void
android_media_MediaScanner_native_init(JNIEnv *env)//jni代码实现
{
     jclass clazz;

    clazz = env->FindClass("android/media/MediaScanner");
    if (clazz == NULL) {
        jniThrowException(env, "java/lang/RuntimeException", "Can't find android/media/MediaScanner");
        return;
    }

    fields.context = env->GetFieldID(clazz, "mNativeContext", "I");
    if (fields.context == NULL) {
        jniThrowException(env, "java/lang/RuntimeException", "Can't find MediaScanner.mNativeContext");
        return;
    }
}
   ***************************************静态注册***********************************
   java文件:

切换到: 纯代码  
   
/** 
 *  @author Lean  @date:2014-11-29   
 */  
public class GetStr {  
      
    static{  
        System.loadLibrary("JNISample");  
    }  
  
    public static native String testGet();  
      
}


   /**
 *    @author Lean  @date:2014-11-29  
 */
public class GetStr {
   
   static{
      System.loadLibrary("JNISample");
   }

   public static native String testGet();
   
}
   >>获取jni的.h代码文件
   生成.h文件,调用javah -jni packagename.classname

切换到: 纯代码  
   
/* DO NOT EDIT THIS FILE - it is machine generated */  
#include <jni.h>   
/* Header for class com_example_jnisample_GetStr */  
  
#ifndef _Included_com_example_jnisample_GetStr   
#define _Included_com_example_jnisample_GetStr   
#ifdef __cplusplus   
extern "C" {  
#endif   
/* 
 * Class:     com_example_jnisample_GetStr 
 * Method:    testGet 
 * Signature: ()Ljava/lang/String; 
 */  
JNIEXPORT jstring JNICALL Java_com_example_jnisample_GetStr_testGet  
  (JNIEnv *, jclass);  
  
#ifdef __cplusplus   
}  
#endif   
#endif


   /* DO NOT EDIT THIS FILE - it is machine generated */
#include <jni.h>
/* Header for class com_example_jnisample_GetStr */

#ifndef _Included_com_example_jnisample_GetStr
#define _Included_com_example_jnisample_GetStr
#ifdef __cplusplus
extern "C" {
#endif
/*
 * Class:     com_example_jnisample_GetStr
 * Method:    testGet
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnisample_GetStr_testGet
  (JNIEnv *, jclass);

#ifdef __cplusplus
}
#endif
#endif
   >>生成.so对应
   书写jni文件,复制com_example_jnisample_GetStr.h文件函数名到JNISample.cpp  如下:

切换到: 纯代码  
   
#include <jni.h>   
#include "com_example_jnisample_GetStr.h"   
  
extern "C" {  
#endif   
/* 
 * Class:     com_example_jnisample_GetStr 
 * Method:    testGet 
 * Signature: ()Ljava/lang/String; 
 */  
JNIEXPORT jstring JNICALL Java_com_example_jnisample_GetStr_testGet  
  (JNIEnv *env, jclass){  
    return env->NewStringUTF("hello");  
}  
  
#ifdef __cplusplus   
}


   #include <jni.h>
#include "com_example_jnisample_GetStr.h"

extern "C" {
#endif
/*
 * Class:     com_example_jnisample_GetStr
 * Method:    testGet
 * Signature: ()Ljava/lang/String;
 */
JNIEXPORT jstring JNICALL Java_com_example_jnisample_GetStr_testGet
  (JNIEnv *env, jclass){
   return env->NewStringUTF("hello");
}

#ifdef __cplusplus
}
   ***************************************动态注册***********************************
   1.MediaScanner的动态注册在执行System.loadLibrary("")后,系统统一调用android_media_MediaPlayer的JNI_OnLoad()方法;

切换到: 纯代码  
   
jint JNI_OnLoad(JavaVM* vm, void* reserved)  
{  
JNIEnv* env = NULL;  
    jint result = -1;  
  
  
    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {  
        LOGE("ERROR: GetEnv failed\n");  
        goto bail;  
    }  
    assert(env != NULL);  
    if (register_android_media_MediaScanner(env) < 0) {  
        LOGE("ERROR: MediaScanner native registration failed\n");  
        goto bail;  
    }  
    /* success -- return valid version number */  
    result = JNI_VERSION_1_4;  
  
bail:  
    return result;  
}


   jint JNI_OnLoad(JavaVM* vm, void* reserved)
{
JNIEnv* env = NULL;
    jint result = -1;


    if (vm->GetEnv((void**) &env, JNI_VERSION_1_4) != JNI_OK) {
        LOGE("ERROR: GetEnv failed\n");
        goto bail;
    }
    assert(env != NULL);
    if (register_android_media_MediaScanner(env) < 0) {
        LOGE("ERROR: MediaScanner native registration failed\n");
        goto bail;
    }
    /* success -- return valid version number */
    result = JNI_VERSION_1_4;

bail:
    return result;
}

切换到: 纯代码  
   
int register_android_media_MediaScanner(JNIEnv *env)  
{  
    return AndroidRuntime::registerNativeMethods(env,  
                "android/media/MediaScanner", gMethods, NELEM(gMethods));  
}


   int register_android_media_MediaScanner(JNIEnv *env)
{
    return AndroidRuntime::registerNativeMethods(env,
                "android/media/MediaScanner", gMethods, NELEM(gMethods));
}
   3.声明
   gMethods代码如下(JNINativeMethod是一个java 函数与jni函数一一对应的结构体)

切换到: 纯代码  
   
static JNINativeMethod gMethods[] = {  
    {"processDirectory",  "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V",      
                                                        (void *)android_media_MediaScanner_processDirectory},  
    {"processFile",       "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V",      
                                                        (void *)android_media_MediaScanner_processFile},  
    {"setLocale",         "(Ljava/lang/String;)V",      (void *)android_media_MediaScanner_setLocale},  
    {"extractAlbumArt",   "(Ljava/io/FileDescriptor;)[B",     (void *)android_media_MediaScanner_extractAlbumArt},  
    {"native_init",        "()V",                      (void *)android_media_MediaScanner_native_init},  
    {"native_setup",        "()V",                      (void *)android_media_MediaScanner_native_setup},  
    {"native_finalize",     "()V",                      (void *)android_media_MediaScanner_native_finalize},  
};


   static JNINativeMethod gMethods[] = {
    {"processDirectory",  "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V",    
                                                        (void *)android_media_MediaScanner_processDirectory},
    {"processFile",       "(Ljava/lang/String;Ljava/lang/String;Landroid/media/MediaScannerClient;)V",    
                                                        (void *)android_media_MediaScanner_processFile},
    {"setLocale",         "(Ljava/lang/String;)V",      (void *)android_media_MediaScanner_setLocale},
    {"extractAlbumArt",   "(Ljava/io/FileDescriptor;)[B",     (void *)android_media_MediaScanner_extractAlbumArt},
    {"native_init",        "()V",                      (void *)android_media_MediaScanner_native_init},
    {"native_setup",        "()V",                      (void *)android_media_MediaScanner_native_setup},
    {"native_finalize",     "()V",                      (void *)android_media_MediaScanner_native_finalize},
};
   *.gMethods中签名中方法类型签名的简化
   *.java代码对应的jni对象类型
   *.JNIEnv*表示jni环境与线程绑定的变量.
   如果从方法里面获取JNIEnv* 则表示的是当前的变量,如果从后台服务获取,则需要从JNI_OnLoad()中的参数
   JavaVm* vm获取 并调用AttachCurrentThread()。在后台线程退出前,必须调用DetachCurrenThread()。
   *.JNIEnv操作jobject相当于操作jfieldID和jmethodID
   1.获取methodID,后调用mEnv操作(Call<Type>Method) methodID
   2.获取fieldID 后 ,调用set<type>Field() 或者set<type>Field()
   *.垃圾回收机制  变量生命周期  (全局引用 局部引用弱全局引用)
   全局引用:NewGlobalRef声明mClient(env->NewGlobalRef(client))
   DeleteGlobalRef 销毁mEnv->DeleteGlobalRef(mClient);
   弱全局引用:特殊的全局引用使用前调用JNIEnv->IsSameOject判断是否被回收
   *.jstring  java中String 对象在jni 中的影射
   本地字符串转JAVA 的String
   Unicode:JNIEnv->NewString();
   UTF-8:JNIEnv->NewStringUTF();
   JAVA 的String转本地字符串
   Unicode:JNIEnv->GetStringCharas();
   UTF-8:JNIEnv->GetStringUTFCharas();
   释放资源:
   Unicode:JNIEnv->ReleaseStringCharas();
   UTF-8:JNIEnv->ReleaseStringUTFCharas();

转自 http://blog.csdn.net/qq285016127/article/details/41595755
(+0)技能Get

建议楼主:搜索关键字 |参考其他资源 |回复 |追问
  error997(error997):   个人中心    课题    目标    代码积累