我如何发布代码以在C ++中的单独线程在Android主线程上运行?

我有一个单独的线程在后台运行在C + +中,我希望它能够发布代码运行在另一个线程已经运行一个android.os.loopper(例如主线程)。 通过“发布”,我的意思是类似于View#post ,其中一个Runnable排队在事件循环中运行。 将被执行的代码也用C ++编写。

我发现了ALooper API( http://developer.android.com/ndk/reference/group___looper.html ),但是文档不是很好,我不清楚是否获得与目标线程关联的ALooper,添加另一个FD ,并发信号通知它将使我的代码在事件队列中保持与其他入队的Runnable相对的正确sorting。

我宁愿不必去通过Java,并得到一个处理程序等 – 这似乎是没有必要的,因为我试图运行的代码和发布它的代码是在c + +。

Solutions Collecting From Web of "我如何发布代码以在C ++中的单独线程在Android主线程上运行?"

一个线程只能有一个Looper关联,一个Looper只有一个消息队列,所以混合Java和本地callback将维持sorting。

有了这个,我不认为今天在Android有任何合同的义务,保证post()以特定的顺序执行,即

 getHandler().post(new Runnable() { @Override public void run() { mTextView.setText("first"); } }); getHandler().post(new Runnable() { @Override public void run() { mTextView.setText("second"); } }); 

没有正式保证mTextView 第二次显示。 当两个post是从不同的线程发出或延迟的时候,绝对没有什么是固定的。

你可以在一篇很棒的博客文章中find一个用于本地代码开发的Android消息传递和并发框架 。

更新

这是必要的证据。 在处理一个不相关的问题时收到了下面的堆栈跟踪:

 A/art: art/runtime/check_jni.cc:65] native: #00 pc 0000484c /system/lib/libbacktrace_libc++.so (UnwindCurrent::Unwind(unsigned int, ucontext*)+23) A/art: art/runtime/check_jni.cc:65] native: #01 pc 00003031 /system/lib/libbacktrace_libc++.so (Backtrace::Unwind(unsigned int, ucontext*)+8) A/art: art/runtime/check_jni.cc:65] native: #02 pc 002441f9 /system/lib/libart.so (art::DumpNativeStack(std::__1::basic_ostream<char, std::__1::char_traits<char> >&, int, char const*, art::mirror::ArtMethod*)+68) A/art: art/runtime/check_jni.cc:65] native: #03 pc 002285a1 /system/lib/libart.so (art::Thread::Dump(std::__1::basic_ostream<char, std::__1::char_traits<char> >&) const+144) A/art: art/runtime/check_jni.cc:65] native: #04 pc 000afe9b /system/lib/libart.so (art::JniAbort(char const*, char const*)+582) A/art: art/runtime/check_jni.cc:65] native: #05 pc 000b05d1 /system/lib/libart.so (art::JniAbortF(char const*, char const*, ...)+60) A/art: art/runtime/check_jni.cc:65] native: #06 pc 000b299d /system/lib/libart.so (art::ScopedCheck::Check(bool, char const*, ...) (.constprop.129)+672) A/art: art/runtime/check_jni.cc:65] native: #07 pc 000bab87 /system/lib/libart.so (art::CheckJNI::CallVoidMethodV(_JNIEnv*, _jobject*, _jmethodID*, std::__va_list)+50) A/art: art/runtime/check_jni.cc:65] native: #08 pc 00060817 /system/lib/libandroid_runtime.so (???) A/art: art/runtime/check_jni.cc:65] native: #09 pc 000a5b29 /system/lib/libandroid_runtime.so (???) A/art: art/runtime/check_jni.cc:65] native: #10 pc 00010fd7 /system/lib/libutils.so (android::Looper::pollInner(int)+482) A/art: art/runtime/check_jni.cc:65] native: #11 pc 00011081 /system/lib/libutils.so (android::Looper::pollOnce(int, int*, int*, void**)+92) A/art: art/runtime/check_jni.cc:65] native: #12 pc 0007fbe5 /system/lib/libandroid_runtime.so (android::NativeMessageQueue::pollOnce(_JNIEnv*, int)+22) A/art: art/runtime/check_jni.cc:65] native: #13 pc 00051b8b /system/framework/arm/boot.oat (Java_android_os_MessageQueue_nativePollOnce__JI+102) A/art: art/runtime/check_jni.cc:65] at android.os.MessageQueue.nativePollOnce(Native method) A/art: art/runtime/check_jni.cc:65] at android.os.MessageQueue.next(MessageQueue.java:143) A/art: art/runtime/check_jni.cc:65] at android.os.Looper.loop(Looper.java:122) A/art: art/runtime/check_jni.cc:65] at android.app.ActivityThread.main(ActivityThread.java:5411) A/art: art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke!(Native method) A/art: art/runtime/check_jni.cc:65] at java.lang.reflect.Method.invoke(Method.java:372) A/art: art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:916) A/art: art/runtime/check_jni.cc:65] at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:709) 

你需要一个已经在主线程中执行的函数。 如果你在那里调用ALooper_forThread()ALooper_prepare() ,你会得到一个指向与主线程关联的活套的指针。 请记住调用ALooper_acquire()以便它可以在不同的线程之间共享。

这可以帮助您https://groups.google.com/forum/#!topic/android-ndk/v2OITtaZTes

但通过java端的处理程序很容易实现,通过jni调用在native和java之间来回发送和处理消息。

如果你想在另一个线程的主线程中做一些东西,我build议你使用runOnUiThread函数。 Android中的主线程是用户界面线程。 我不确定你是否可以在ndk代码中使用这个函数。

代码的例子可以是这样的:

private void runOnMainThread(){

 runOnUiThread(new Runnable(){ public void run() { try { // do some stuffs } catch (final Exception ex) { // handle the possible exception } } }); } 

无论如何,我build议你阅读以下链接: link1 , link2 , link3 。

我希望它有帮助。

你将不得不通过Java,因为android.os.Looper没有在本地代码中实现 (至less在当前最新的提交中 )。

我没有足够的经验与NDK快速键入所需的样板,但显而易见的select似乎是创build一个基于本机代码的Java Runnable并将其发送到循环。

不太明显的解决scheme直接在线程的MessageQueue上运行。 一旦你有了一个参考,你可以注册一个本地pipe道的一端,并写信息到另一端; 该pipe道基本上采用Handler的function,但在本地代码。 从技术上讲,你的代码仍然是从Java调用的,但是你不需要开销。 整个事情我还没有find太多的文件,但是这个线索可能是一个很好的起点

但是,您的代码实际上不必从主线程中调用,或者有另一个选项可以在不通过Java的情况下解决您的问题。 然而,这将取决于你正在试图解决的问题。


注意:我假设主线程场景。 如果您可以在要部署的线程中使用基于本机代码的活套,则可以使用更多选项。

¹有可能ALooper可以在某种客户端模式下使用。 非常不确定。