Как отправить код, который будет запускаться в основном потоке Android из отдельного потока на C ++?

У меня есть отдельный поток, работающий на C ++ в фоновом режиме, и я хочу, чтобы он мог отправлять код для запуска в другом потоке, который уже запускает android.os.Looper (например, основной поток). Под «post» я имею в виду нечто похожее на View#post где Runnable помещается в очередь для запуска цикла событий. Код, который будет выполнен, также написан на C ++.

Я нашел API ALooper ( http://developer.android.com/ndk/reference/group___looper.html ), но документы невелики, и мне непонятно, получал ли ALooper, связанный с потоком назначения, добавляя еще один FD , И сигнализация, это заставит мой код поддерживать правильный порядок в очереди событий по отношению к другим включенным Runnables.

Я бы предпочел не проходить через Java и получить Handler и т. Д. – это просто кажется ненужным, поскольку и код, который я пытаюсь запустить, и код, который его отправляет, находятся на c ++.

В потоке может быть только один связанный с ним Looper, у Looper есть только одна очередь сообщений, поэтому смешивание Java и собственных обратных вызовов будет поддерживать порядок.

При этом я не думаю, что в 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 отображает второй . Определенно ничто не установлено в камне, когда два сообщения отправляются из разных потоков или задерживаются.

Вы можете найти платформу обмена сообщениями и параллелизма 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, отправки и обработки сообщений, выполняющих обратную связь между native и java с помощью jni-вызовов.

Если вы хотите сделать некоторые вещи в основном потоке из другого потока, я предлагаю вам использовать функцию runOnUiThread . Основной поток в Android – это поток пользовательского интерфейса. Я не уверен, что вы можете использовать эту функцию в коде ndk.

Пример кода может быть следующим:

Private void runOnMainThread () {

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

В любом случае, я предлагаю вам прочитать следующие ссылки: link1 , link2 , link3 .

Я надеюсь, что это помогает.

Вам нужно будет пройти через Java, так как android.os.Looper не реализован в собственном коде (по крайней мере, в последнем недавнем фиксации ).

У меня недостаточно опыта работы с NDK, чтобы быстро ввести требуемый шаблон, но очевидным вариантом является создание java Runnable на основе собственного кода и отправка его в петлеукладчик.

Не столь очевидное решение непосредственно работает в MessageQueue потока. Если у вас есть ссылка на это, вы можете зарегистрировать один конец родного канала и записать сообщения на другой конец; Труба в основном выполняет функцию Handler , но на собственном коде. Технически ваш код по-прежнему вызывается из Java, но вам не нужны накладные расходы. На самом деле я не нашел много документации, но эта тема могла бы стать хорошей отправной точкой.

Однако вполне возможно, что ваш код на самом деле не должен вызываться из основного потока, или что есть другой вариант для решения вашей проблемы без прохождения через Java. Это, однако, будет зависеть от проблемы, которую вы пытаетесь решить.


Примечание. Я предполагаю сценарий основного потока. Если в потоке, который вы хотите развернуть, вы можете использовать петлитель с нативным кодом, у вас есть больше возможностей.

¹ Возможно, что ALooper можно использовать в каком-то режиме клиента, чтобы это сделать. Очень не уверен в этом.

Intereting Posts
Активация Bluetooth Активация диалогового окна предупреждения после поворота экрана Распознавание голоса в качестве справочной службы Как пройти Drawable с помощью Parcelable Разработчик контракта Android оставил, нужно обновить приложение без оригинального хранилища ключей – возможно ли это? Система координат экрана Android: как установить (0,0) в нижней левой части экрана Android как первый квадрат плоскости xy Почему Android WebView не загружает видео youtube HTML5 iframe? Действительно ли невозможно защитить приложения Android от обратной инженерии? Сохранение TextView с onSaveInstanceState Android. Избегайте масштабирования фона Проблемы с сохранением коллекции с использованием ORMLite на Android Производительность чтения файлов на смартфонах: внутреннее хранилище против SD-карты и жесткий диск ПК Должен ли onHandleIntent вызываться, когда IntentService запущен с bindService? Декодировать часть Bitmap из файла на Android Как предотвратить редактирование EditText строки после пунктуации Oauth on Appengine с сервисами Google Play