NDK 5 使用POSIX线程

Java中使用线程特别简单,实现Runnable接口 或者 继承Thread.

NDK中使用线程可以在Activity中直接调用java线程,也可以通过JNI启动线程,这个线程源于POSIX中的线程库。


需要使用POSIX中pthread

头文件


如果启动了Posix线程,是无法与Android Java层交互的,主要是因为POSIX线程中无法直接调用JNIEnv  。
因此我们需要先把native thread与JVM关联上,这样既可获得JNIEnv。没有JNIEnv是无法回调JAVA层的方法。


编写一个Activity 只是打印一个语句Toast


public class MainActivity extends Activity {
	
	static {
		System.loadLibrary("ndk-thread");
	}

	public static MainActivity instance;

	@Override
	protected void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.activity_main);
		findViewById(R.id.start).setOnClickListener(new OnClickListener() {
			public void onClick(View arg0) {
				JNI.startThreadJNI(); //JNI Native 方法,启动线程
			}
		});

		instance = this;
	}

	public void showMsg(final String msg) {
		Log.d("showMsg","msg:" + msg);
		MainActivity.instance.runOnUiThread(new Runnable(){
			@Override
			public void run() {
				Toast.makeText(instance, msg, Toast.LENGTH_SHORT).show(); //回调弹出消息
			}
		});
	}

}


JNI.java

public class JNI {

 public JNI() {
 }

 public native static void startThreadJNI();

}

创建一个Callback.java 用来回调Activity的showMsg方法

public class Callback {

	public void setMsg(String msg) {
		MainActivity.instance.showMsg(msg);
	}

	public Callback() {
	}
}


在JNI_OnLoad方法中 我们能获取到JVM对象,这个方法是有框架自动执行的。在JNI.h头文件中有原型。

JavaVM* jvm1 = NULL;
jobject obj1 = NULL;
jmethodID mid1 = NULL;

jint JNI_OnLoad (JavaVM* vm, void* reserved)
{
	jvm1 = vm;
	return JNI_VERSION_1_4;
}


void *run_task(void *args) { //线程需要执行的东西
	JNIEnv* env = NULL;
	
    int n = (*jvm1)->AttachCurrentThread(jvm1,&env, NULL); //从jvm中获取到JNIEnv
    if (n == 0) {
    	
    	jstring msg = (*env)->NewStringUTF(env,"Yes Thread Running.");
        (*env)->CallVoidMethod(env, obj1, mid1, msg); //回调JAVA层Callback类中的方法
        (*env)->DeleteGlobalRef(env,obj1); //删除引用
    	(*jvm1)->DetachCurrentThread(jvm1); //这个一定要调用,否则报错,意在取消线程与jvm关联
    }
    LOGI("44");
}

void init_instance(JNIEnv *env) {
	 LOGI("instance.");
	 jclass jz1 = (*env)->FindClass(env,"com/birds/android/ndk/thread1/Callback");
	 jmethodID mid = (*env)->GetMethodID(env,jz1,"","()V");
	 jobject myobj = (*env)->NewObject(env,jz1,mid);
	          obj1 = (*env)->NewGlobalRef(env,myobj);
	 LOGI("OK Instance Done.");
	 mid1 = (*env)->GetMethodID(env, jz1, "setMsg", "(Ljava/lang/String;)V");
}






编写JNI层代码。直接写C代码

JNIEXPORT void JNICALL Java_com_birds_android_ndk_thread1_JNI_startThreadJNI
  (JNIEnv *env, jclass jclas) {
    init_instance(env);//主要是准备一些对象实例化,Callback实例化
    pthread_t thread1;
    
    int n = pthread_create(&thread1,NULL,run_task,NULL);//启动线程,调用run_task方法
    
    if (n != 0) {
    	
       //线程创建失败
    	jclass exceptionClazz = (*env)->FindClass(env,
    						"java/lang/RuntimeException");
        (*env)->ThrowNew(env,exceptionClazz, "create thread error.");

    }


}













你可能感兴趣的:(Android,技术研究,手机移动开发)