JNI开发第二篇通过反射实现C中调用java代码,并实现Log打印日志

来源:互联网 发布:复杂网络的实际应用 编辑:程序博客网 时间:2024/05/21 14:43

C中调用java代码,主要运用在C代码执行耗时操作时候来进行对UI的实时性的改变,比如做图像处理的时候,可能图像较大,处理时间较长,那么就可以通过这个技术来实时更新处理的进度,下面我们通过代码来看具体的实现。
1.MainActivity

public class MainActivity extends Activity {    JNI jni;    @Override    protected void onCreate(Bundle savedInstanceState) {        super.onCreate(savedInstanceState);        setContentView(R.layout.activity_main);        jni = new JNI(this);    }    public void callbackvoid(View v){        jni.callbackvoidmethod();    }    public void callbackint(View v){        jni.callbackintmethod();    }    public void callbackString(View v){        jni.callbackStringmethod();    }    public void callbackshowtoast(View v){        jni.callbackShowToast();    }}

2.JNI.java

public class JNI {    static{        System.loadLibrary("callback");    }    private Context mContext;    public JNI(Context context){        mContext = context;    }    public native void callbackvoidmethod();    public native void callbackintmethod();    public native void callbackStringmethod();    public native void callbackShowToast();    //C调用java空方法    public void helloFromJava(){        System.out.println("hello from java");    }    //C调用java中的带两个int参数的方法    public int add(int x,int y) {        return x+y;    }    //C调用java中参数为string的方法    public void printString(String s){        System.out.println(s);    }    public void showToast(String s){        Toast.makeText(mContext, s, Toast.LENGTH_LONG).show();    }}

3.activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"    xmlns:tools="http://schemas.android.com/tools"    android:layout_width="match_parent"    android:layout_height="match_parent"    android:paddingBottom="@dimen/activity_vertical_margin"    android:paddingLeft="@dimen/activity_horizontal_margin"    android:paddingRight="@dimen/activity_horizontal_margin"    android:paddingTop="@dimen/activity_vertical_margin"    android:orientation="vertical"    tools:context="com.mengxin.callbackjava.MainActivity" >    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="callbackvoid"        android:text="回调空方法" />    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="callbackint"        android:text="回调int参数方法" />    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="callbackString"        android:text="回调String参数方法" />    <Button        android:layout_width="wrap_content"        android:layout_height="wrap_content"        android:onClick="callbackshowtoast"        android:text="回调弹吐司" /></LinearLayout>

4.接下来是JNI的类文件命名为callback.c

#include <jni.h>#include <stdlib.h>#include "eben_hpc_log.h"/** * 把一个jstring转换成一个c语言的char* 类型. */char* _JString2CStr(JNIEnv* env, jstring jstr) {     char* rtn = NULL;     jclass clsstring = (*env)->FindClass(env, "java/lang/String");     jstring strencode = (*env)->NewStringUTF(env,"GB2312");     jmethodID mid = (*env)->GetMethodID(env, clsstring, "getBytes", "(Ljava/lang/String;)[B");     jbyteArray barr = (jbyteArray)(*env)->CallObjectMethod(env, jstr, mid, strencode); // String .getByte("GB2312");     jsize alen = (*env)->GetArrayLength(env, barr);     jbyte* ba = (*env)->GetByteArrayElements(env, barr, JNI_FALSE);     if(alen > 0) {        rtn = (char*)malloc(alen+1); //"\0"        memcpy(rtn, ba, alen);        rtn[alen]=0;     }     (*env)->ReleaseByteArrayElements(env, barr, ba,0);     return rtn;}JNIEXPORT void JNICALL Java_com_mengxin_callbackjava_JNI_callbackvoidmethod  (JNIEnv * env, jobject clazz){    //jclass      (*FindClass)(JNIEnv*, const char*);    //① 获取字节码对象    jclass claz = (*env)->FindClass(env,"com/mengxin/callbackjava/JNI");    //②获取Method对象    //jmethodID   (*GetMethodID)(JNIEnv*, jclass, const char*, const char*);    jmethodID methodID =(*env)->GetMethodID(env,claz,"helloFromJava","()V");    //③通过字节码对象创建一个Object    //④通过对象调用方法    //void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);    (*env)->CallVoidMethod(env,clazz,methodID);}JNIEXPORT void JNICALL Java_com_mengxin_callbackjava_JNI_callbackintmethod  (JNIEnv * env, jobject clazz){    //① 获取字节码对象    jclass claz =(*env)->FindClass(env,"com/mengxin/callbackjava/JNI");    //②获取Method对象    jmethodID methodID = (*env)->GetMethodID(env,claz,"add","(II)I");    //jint        (*CallIntMethod)(JNIEnv*, jobject, jmethodID, ...);    int result =(*env)->CallIntMethod(env,clazz,methodID,3,4);    LOGD("result = %d",result);}JNIEXPORT void JNICALL Java_com_mengxin_callbackjava_JNI_callbackStringmethod  (JNIEnv * env, jobject clazz){    //① 获取字节码对象        jclass claz =(*env)->FindClass(env,"com/mengxin/callbackjava/JNI");    //② 获取Method对象        jmethodID methodid =(*env)->GetMethodID(env,claz,"printString","(Ljava/lang/String;)V");    //        jstring result =(*env)->NewStringUTF(env,"hello from c");        (*env)->CallVoidMethod(env,clazz,methodid,result);}JNIEXPORT void JNICALL Java_com_mengxin_callbackjava_JNI_callbackShowToast  (JNIEnv * env, jobject clazz){    jclass claz =(*env)->FindClass(env,"com/mengxin/callbackjava/JNI");    jmethodID methodid =(*env)->GetMethodID(env,claz,"showToast","(Ljava/lang/String;)V");    //jobject     (*AllocObject)(JNIEnv*, jclass);    //通过字节码对象创建 java对象 在这儿就是创建了mainactivity的对象    //jobject obj =(*env)->AllocObject(env,claz);    jstring result =(*env)->NewStringUTF(env,"hello from c");    //void        (*CallVoidMethod)(JNIEnv*, jobject, jmethodID, ...);    (*env)->CallVoidMethod(env,clazz,methodid,result);}

5.如果是要打Log,还需要一个文件eben_hpc_log.h

#ifndef _Included_hpc_Log#define _Included_hpc_Log#ifdef __cplusplusextern "C" {#endif#include <android/log.h>// 宏定义类似java 层的定义,不同级别的Log LOGI, LOGD, LOGW, LOGE, LOGF。 对就Java中的 Log.i log.d#define LOG_TAG    "hpc -- JNILOG" // 这个是自定义的LOG的标识//#undef LOG // 取消默认的LOG#define LOGI(...)  __android_log_print(ANDROID_LOG_INFO,LOG_TAG, __VA_ARGS__)#define LOGD(...)  __android_log_print(ANDROID_LOG_DEBUG,LOG_TAG, __VA_ARGS__)#define LOGW(...)  __android_log_print(ANDROID_LOG_WARN,LOG_TAG, __VA_ARGS__)#define LOGE(...)  __android_log_print(ANDROID_LOG_ERROR,LOG_TAG, __VA_ARGS__)#define LOGF(...)  __android_log_print(ANDROID_LOG_FATAL,LOG_TAG, __VA_ARGS__)#ifdef __cplusplus}#endif#endif  

6.最后修改的是build.gradle

apply plugin: 'com.android.application'android {    compileSdkVersion 24    buildToolsVersion "24.0.1"    defaultConfig {        applicationId "com.mengxin.callbackjava"        minSdkVersion 15        targetSdkVersion 24        versionCode 1        versionName "1.0"        ndk {            ldLibs "log"            moduleName "callback"         //生成的so名字            //abiFilters "armeabi"  //输出指定三种abi体系结构下的so库。目前可有可无。            abiFilters "armeabi", "armeabi-v7a", "x86"  //输出指定三种abi体系结构下的so库。目前可有可无。        }    }    buildTypes {        release {            minifyEnabled false            proguardFiles getDefaultProguardFile('proguard-android.txt'), 'proguard-rules.pro'        }    }}dependencies {    compile fileTree(dir: 'libs', include: ['*.jar'])    testCompile 'junit:junit:4.12'    compile 'com.android.support:appcompat-v7:24.2.0'}

源码链接
参考文献
http://www.cnblogs.com/0616–ataozhijia/p/5628291.html

0 0