使用NDK将选择循环应用程序移植到Android。设计问题

时间:2011-01-10 01:11:05

标签: c++ c select java-native-interface android-ndk

我有一个使用这样的选择循环的网络应用程序:

bool shutdown=false;
while (!shutdown) {

     [do something]
     select(...,timeout);
}

由于应用程序需要接收Intent,需要处理GUI等,因此主循环在Android应用程序中不能像这样工作。

我认为我基本上有三种可能性:

  1. 将主循环移动到应用程序的java部分。
  2. 让循环在自己的线程中运行,并以某种方式从/与java进行通信。
  3. 使用Android< = 2.3并使用原生活动并使用AInputQueue / ALooper而不是选择。
  4. 第一种可能性并不容易,因为java没有选择适用于fds。简单地使用select和return之后每个循环到java都不是一个优雅的可能性,因为这需要将超时设置为20ms,以便在程序的java部分有一个很好的响应时间。

    第二个概率听起来更好但我在java和程序的c ++ / c部分之间做了一些沟通。冷酷的事情:

    1. 使用插座,有点难看。
    2. 在“java gui线程”中使用本机调用,在“c线程”中使用本机回调。两个线程都需要具有线程安全实现,但这是可管理的。
    3. 我没有探究第三种可能性,但我认为这不是可行的方法。

      我想我可以一起破解一些可行的东西,但我会问最佳选择路径是什么。

3 个答案:

答案 0 :(得分:1)

根据提供的有限信息,我可以考虑以下方法:

循环可以在一个单独的线程中运行,有两个选项:
a)寻找gui led变更(基于全局本地状态变量的值,例如,en_type的native_app_state)
b)发生触发回调Java的事情

您可以使用单独的本机函数或一个集成的本机函数来响应来自Java的GUI事件 - 您可以在其中使用该全局本机状态变量的状态。

您可以根据每个州的情况以及应用程序的性能限制来优化实施。

答案 1 :(得分:1)

也许您可以将Java NIO用于本机应用程序的网络层。 java.nio.channels.Selector为您提供了与C的select()相当的Java。而java.nio.channels.Channel类似于C中的fd。

此示例代码不是Android特定的,但应该可以使用(或至少让您了解使用情况):http://www.exampledepot.com/egs/java.nio/NbClient.html

答案 2 :(得分:1)

关于IPC:Looper - 或至少NDK实现ALooper - 使用POSIX pipe()作为IPC的手段;你可以在android_app_glue.c中看到一些这种情况,它是NDK的标准配置。作为该文件的参考,有问题的行是:

 int msgpipe[2];
    if (pipe(msgpipe)) {
        LOGE("could not create pipe: %s", strerror(errno));
        return NULL;
    }
    android_app->msgread = msgpipe[0];
    android_app->msgwrite = msgpipe[1];

,关键行是

ALooper_addFd(looper, android_app->msgread, LOOPER_ID_MAIN, ALOOPER_EVENT_INPUT, NULL, &android_app->cmdPollSource);

其中第二个参数(fd)是文件描述符:

int ALooper_addFd   (   ALooper *   looper,
        int     fd,
        int     ident,
        int     events,
        ALooper_callbackFunc    callback,
        void *      data 
    )   

...如果他们将它用于native_app_glue.c,用于游戏等等,我认为它效率很高。