使用开源通信框架alljoyn来做设备,服务的搜索、发现,通信,详细原理参考
gstreamer作媒体播放。
有兴趣同学可以看下https://github.com/europelee/AjUtil,简单的多媒体文件流分享(上图即它的architecture)
(alljoyn设备、服务通告,发现示意图)
涉及面:
1. JNI中的多native线程与java通信处理:
JNIEnv, java_vm, thread: JNIEnv不能为多个native线程共同拥有, 即JNIEnv对于每个线程是唯一的,它是线程相关的,那么
对于一个native线程如果需要使用JNIEnv, 需要通过javavm的AttachCurrentThread方法来获取它自有的。
比如下面的 set_ui_message,当内部native线程运行时需要通知某些消息到android 的java层 , 通过get_jni_env来获取它自有JNIEnv.
2.Thread-Specific Data
大家注意到current_jni_env? 如果 set_ui_message在多个native线程里面被调用,那get_jni_env函数里面pthread_getspecific搞什么鬼,
current_jni_env就一个全局变量,能保证每个线程的env指针唯一?
正常情况下,一个全局变量是为进程内的多个线程共享,但如果线程想单独拥有它,那么可以使用POSIX提供的Thread-Specific Data, 即
线程私有数据,这样看起来这是一个全局变量,所有线程都可以使用它,但它的值在每一个线程中又是单独存储的,一个使用同名而不同变量地址的线程相关数据结构,通过pthread_key_create函数来创建
pthread_key_create(¤t_jni_env, detach_current_thread);
3. code:
/* Register this thread with the VM */
static JNIEnv *attach_current_thread(void) {
JNIEnv *env;
JavaVMAttachArgs args;
GST_DEBUG("Attaching thread %p", g_thread_self());
args.version = JNI_VERSION_1_4;
args.name = NULL;
args.group = NULL;
if ((*java_vm)->AttachCurrentThread(java_vm, &env, &args) < 0) {
GST_ERROR("Failed to attach current thread");
return NULL;
}
return env;
}
/* Retrieve the JNI environment for this thread */
static JNIEnv *get_jni_env(void) {
JNIEnv *env;
if ((env = pthread_getspecific(current_jni_env)) == NULL) {
env = attach_current_thread();
pthread_setspecific(current_jni_env, env);
}
return env;
}
/* Change the content of the UI's TextView */
static void set_ui_message(const gchar *message, CustomData *data) {
JNIEnv *env = get_jni_env();
GST_DEBUG("Setting message to: %s", message);
jstring jmessage = (*env)->NewStringUTF(env, message);
(*env)->CallVoidMethod(env, data->app, set_message_method_id, jmessage);
if ((*env)->ExceptionCheck(env)) {
GST_ERROR("Failed to call Java method");
(*env)->ExceptionClear(env);
}
(*env)->DeleteLocalRef(env, jmessage);
}