写那么多不如来点代码实在!!!
Java代码:
public class MainActivity extends AppCompatActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
}
public void callNative(View view){
Toast.makeText(getApplicationContext(),helloMethod("hello native"),Toast.LENGTH_SHORT).show();
}
public void callJava(View view){
nativeCallJava();
}
public void CallJavaInThread(View view){
nativeCallJavaInThread();
}
static {
System.loadLibrary("hello");
}
public native String helloMethod(String input);
public native void nativeCallJava();
public native void nativeCallJavaInThread();
public static void nativeCall(String message){
Log.e("MainActivity","nativeCall : "+message);
}
public void nativeCall_nonStatic(String message){
Log.e("MainActivity","nativeCall_nonStatic : "+message);
}
}
onload.h
#ifndef JNIC2JAVA_ONLOAD_H
#define JNIC2JAVA_ONLOAD_H
#endif //JNIC2JAVA_ONLOAD_H
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <assert.h>
#include <android/log.h>
#include "test.h"
//extern供其他文件使用,作为一个全局变量,这时候的值会同步
JavaVM *savedVm;
jclass clazz_global;//用于在多线程中回调java中的方法。
jobject object_global;
//注意static定义的全局变量的不同
//static JavaVM *savedVm;
//static jclass clazz_global;//static定义的变量,不能在其他文件中访问。可以再同一文件中多线程访问
//static jobject object_global;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm,void *reserved);
jint register_method(JNIEnv *env);
jint registerNativeMethods(JNIEnv* env, const char *class_name, JNINativeMethod *methods, int num_methods);
JNIEXPORT jstring JNICALL helloMethod(JNIEnv *env, jobject thiz,jstring input);
JNIEXPORT void JNICALL nativeCallJava(JNIEnv *env, jobject thiz);
JNIEnv *getEnv();
JNIEXPORT void JNICALL nativeCallJavaInThread(JNIEnv *env, jobject thiz);
void* callJava_thread_func(void* p);
onload.cpp
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <assert.h>
#include <android/log.h>
#include "onload.h"
#include<pthread.h>
#define TAG "myDemo-jni" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型
JavaVM *savedVm;
jclass clazz_global;//用于在多线程中回调java中的方法。
jobject object_global;
JNIEXPORT jint JNICALL JNI_OnLoad(JavaVM *vm,void *reserved){
LOGE("JNI_Onload in 1");
JNIEnv *env = NULL;
int result = -1;
if (vm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
LOGE("JNI_Onload in 2");
return JNI_ERR;
}
result = register_method(env);
savedVm = vm;
LOGE("JNI_Onload in 3 , result is %d", result);
return JNI_VERSION_1_6;
}
JNINativeMethod methods[] = {
{"helloMethod","(Ljava/lang/String;)Ljava/lang/String;",(void*)helloMethod},
{"nativeCallJava","()V",(void*)nativeCallJava},
{"nativeCallJavaInThread","()V",(void*)nativeCallJavaInThread}
};
jint register_method(JNIEnv *env){
LOGE("register_method in 1");
int result = registerNativeMethods(env,"com/xxxx/jni/MainActivity",methods, sizeof(methods) / sizeof(methods[0]));
LOGE("register_method in 2,result is %d ",result);
return result;
}
jint registerNativeMethods(JNIEnv* env, const char *class_name, JNINativeMethod *methods, int num_methods) {
int result = 0;
LOGE("registerNativeMethods in 1");
jclass clazz = env->FindClass(class_name);
clazz_global = (jclass)env->NewGlobalRef(clazz);
LOGE("registerNativeMethods in 2");
if(clazz == NULL){
LOGE("registerNativeMethods in 3");
return JNI_FALSE;
}
LOGE("registerNativeMethods in 4");
result = env->RegisterNatives(clazz, methods, num_methods);
LOGE("registerNativeMethods in 5");
if(result < 0){
LOGE("registerNativeMethods in 6");
return JNI_FALSE;
}
LOGE("registerNativeMethods in 7 ,result is %d",result);
return result;
}
//Java调用native方法
JNIEXPORT jstring JNICALL helloMethod(JNIEnv *env, jobject thiz,jstring input){
LOGE("helloMethod in 1");
const char *result_char = env->GetStringUTFChars(input,JNI_FALSE);
jstring result = env->NewStringUTF(result_char);
return result;
}
//native方法将调用Java方法
JNIEXPORT void JNICALL nativeCallJava(JNIEnv *env, jobject thiz){
object_global = (jobject)env->NewGlobalRef(thiz);
LOGE("nativeCallJava in 1");
env = getEnv();
LOGE("nativeCallJava in 2");
jclass clazz = env->FindClass("com/xxxx/jni/MainActivity");
LOGE("nativeCallJava in 3");
jmethodID method1 = env->GetStaticMethodID(clazz,"nativeCall","(Ljava/lang/String;)V");
LOGE("nativeCallJava in 4");
jstring result = env->NewStringUTF("aaaaaaaaa");
env->CallStaticVoidMethod (clazz, method1,result);
LOGE("nativeCallJava in 5");
jmethodID method2 = env->GetMethodID(clazz,"nativeCall_nonStatic","(Ljava/lang/String;)V");
LOGE("nativeCallJava in 6");
env->CallVoidMethod (thiz, method2,result);
}
JNIEXPORT void JNICALL nativeCallJavaInThread(JNIEnv *env, jobject thiz){
pthread_t native_thread;
pthread_create(&native_thread, NULL, callJava_thread_func,NULL);
//在另一个文件中的线程
pthread_create(&native_thread, NULL, testcallJava_thread_func,NULL);
// testCallJavaInThread();
}
//在多线程中调用java的方法
void* callJava_thread_func(void* p){
LOGE("callJava_thread_func in 1");
JNIEnv *env ;
if (savedVm->AttachCurrentThread(&env, 0) != 0)
{
LOGE("Failed to attach current thread");
return 0;
}
LOGE("callJava_thread_func in 2");
// jclass clazz = env->FindClass("com/xxxx/jni/MainActivity");
LOGE("callJava_thread_func in 3");
jmethodID method1 = env->GetStaticMethodID(clazz_global,"nativeCall","(Ljava/lang/String;)V");
LOGE("callJava_thread_func in 4");
jstring result = env->NewStringUTF("BBBBBBBBB");
env->CallStaticVoidMethod (clazz_global, method1,result);
LOGE("callJava_thread_func in 5");
jmethodID method2 = env->GetMethodID(clazz_global,"nativeCall_nonStatic","(Ljava/lang/String;)V");
LOGE("callJava_thread_func in 6");
env->CallVoidMethod (object_global, method2,result);
LOGE("callJava_thread_func in 7");
savedVm->DetachCurrentThread();
}
JNIEnv *getEnv() {
JNIEnv *env = NULL;
if (savedVm->GetEnv(reinterpret_cast<void **>(&env), JNI_VERSION_1_6) != JNI_OK) {
env = NULL;
}
return env;
}
test.h
#ifndef JNIC2JAVA_TEST_H
#define JNIC2JAVA_TEST_H
#endif //JNIC2JAVA_TEST_H
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <jni.h>
#include <assert.h>
#include <android/log.h>
extern JavaVM *savedVm;
extern jclass clazz_global;//用于在多线程中回调java中的方法。
extern jobject object_global;
void testCallJavaInThread();
extern void* testcallJava_thread_func(void* p);
test.cpp
#include "test.h"
#include "onload.h"
#include<pthread.h>
#include <assert.h>
#include <android/log.h>
#define TAG "myDemo-jni" // 这个是自定义的LOG的标识
#define LOGD(...) __android_log_print(ANDROID_LOG_DEBUG,TAG ,__VA_ARGS__) // 定义LOGD类型
#define LOGI(...) __android_log_print(ANDROID_LOG_INFO,TAG ,__VA_ARGS__) // 定义LOGI类型
#define LOGW(...) __android_log_print(ANDROID_LOG_WARN,TAG ,__VA_ARGS__) // 定义LOGW类型
#define LOGE(...) __android_log_print(ANDROID_LOG_ERROR,TAG ,__VA_ARGS__) // 定义LOGE类型
#define LOGF(...) __android_log_print(ANDROID_LOG_FATAL,TAG ,__VA_ARGS__) // 定义LOGF类型
void testCallJavaInThread(){
// pthread_t testnative_thread;
// pthread_create(&testnative_thread, NULL, testcallJava_thread_func,NULL);
testcallJava_thread_func(NULL);
}
void* testcallJava_thread_func(void* p){
LOGE("testcallJava_thread_func in 1");
JNIEnv *env ;
if(savedVm == NULL){
LOGE("savedVm == NULL");
}
if (savedVm->AttachCurrentThread(&env, 0) != 0)
{
LOGE("Failed to attach current thread");
return 0;
}
LOGE("testcallJava_thread_func in 2");
// jclass clazz = env->FindClass("com/goertek/jni/MainActivity");//在多线程中FindClass会报错
LOGE("testcallJava_thread_func in 3");
jmethodID method1 = env->GetStaticMethodID(clazz_global,"nativeCall","(Ljava/lang/String;)V");
LOGE("testcallJava_thread_func in 4");
jstring result = env->NewStringUTF("BBBBBBBBB");
env->CallStaticVoidMethod (clazz_global, method1,result);
LOGE("testcallJava_thread_func in 5");
jmethodID method2 = env->GetMethodID(clazz_global,"nativeCall_nonStatic","(Ljava/lang/String;)V");
LOGE("testcallJava_thread_func in 6");
env->CallVoidMethod (object_global, method2,result);
LOGE("testcallJava_thread_func in 7");
savedVm->DetachCurrentThread();//不调用这一句,会报错
}
Android.mk
LOCAL_PATH:=$(call my-dir)
include $(CLEAR_VARS)
LOCAL_SRC_FILES:= \
onload.cpp\
test.cpp\
LOCAL_MODULE:=hello
LOCAL_LDLIBS :=-llog
include $(BUILD_SHARED_LIBRARY)
Application.mk
APP_PLATFORM := android-21
APP_ABI := armeabi-v7a
#APP_OPTIM := debug
APP_OPTIM := release