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
#include
#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 __cplusplus
extern "C" {
#endif
#include
// 宏定义类似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