【问题标题】:Is it possible to create UI elements with the NDK ? - lack of specs in Android docs是否可以使用 NDK 创建 UI 元素? - Android 文档中缺乏规范
【发布时间】:2012-10-01 02:12:31
【问题描述】:

阅读相关文档后,我不知道是否可以仅使用使用 NDK 编译的 C++/C 代码来创建按钮或其他 UI 元素等用于获取用户输入的内容。

当我想处理需要保持焦点的“窗口”或活动时,没有问题,但我不知道如何构建带有回调和用户输入元素的 UI。

奇怪的是有一个窗口框架,但没有任何 UI 元素回调的痕迹。

我可以使用 NDK 构建触摸按钮或虚拟游戏手柄吗?


我很欣赏我们的努力和我们越来越接近我的观点的事实,但显然我解释得不够好。

我找到了这张图片here

现在我的问题和这个问题的重点是:

假设我可以放置和绘制这个虚拟操纵杆,我如何才能仅检测运动并在 Android 上仅使用 NDK 进行Joystick.onUpJoystick.onDown 之类的回调?

如果 NDK 没有此类回调,我应该每次都检测 [x,y] 位置,将其与我的操纵杆的位置进行比较,存储之前的位置,比较之前的位置和下一个能找到方向吗?

由于传感器以非常快的速度抛出事件,我认为仅考虑原始 X、Y 对我自己构建它最终会导致控制系统效率非常低,因为它不会在操作系统级别进行优化使用适当的传感器调用。

根据 NativeActivity 示例,也不清楚如何处理多个触摸点,例如我如何同时处理 2 个触摸事件?

只需考虑上面的图片,并考虑只有 1 个触摸点的 x,y 坐标,以及如何以 NDK 支持的有效方式解决这个问题。

谢谢。

【问题讨论】:

    标签: android user-interface android-ndk native native-activity


    【解决方案1】:

    当然可以。阅读从 C(++) 调用 Java,并调用相应的 Java 函数 - 一个一个地构造 UI 元素(布局、按钮等),或者加载一个 XML 布局。没有 C 特定的接口,但可以调用 Java 接口。

    除非它是一款游戏并且您打算通过 OpenGL ES 进行自己的绘图。我不确定你是否可以混搭。

    NativeActivity 中,您仍然可以获得指向Java Activity 对象的指针并调用其方法——它是ANativeActivity 结构的clazz 成员,它作为参数传递给您的android_main,通过android_app 结构。获取该指针,从其中获取JNIEnv*,然后分配一个布局。

    这将如何与 OpenGL 绘图互操作,我不确定。

    编辑:关于整合您自己的输入处理。关键回调是android_app 结构中的onInputEvent(struct android_app* app, AInputEvent* event)。将您的回调放在那里,Android 会在适当的时候调用它。使用AInputEvent_getType(event) 检索事件类型;触摸事件的类型为 AINPUT_EVENT_TYPE_MOTION。

    EDIT2:这是一个抓取触摸事件的最小原生应用:

    #include <jni.h>
    #include <android_native_app_glue.h>
    #include <android/log.h>
    
    static int32_t OnInput(struct android_app* app, AInputEvent* event)
    {
        __android_log_write(ANDROID_LOG_ERROR, "MyNativeProject", "Hello input event!");
        return 0;
    }
    
    extern "C" void android_main(struct android_app* App)
    {
        app_dummy();
        App->onInputEvent = OnInput;
    
        for(;;)
        {
             struct android_poll_source* source;
             int ident;
             int events;
    
             while ((ident = ALooper_pollAll(-1, NULL, &events, (void**)&source)) >= 0)
             {
                 if(source != NULL)
                     source->process(App, source);
    
                 if (App->destroyRequested != 0)
                         return;
             }
        }
    
    }
    

    您自然需要围绕它添加一个项目,包括清单、Android.mk 和所有内容。 Android.mk 将需要以下内容作为最后一行:

    $(call import-module,android/native_app_glue)
    

    native_app_glue 是一个静态库,它为通常通过 Java 使用的 API 提供一些 C 桥接。

    您也可以在没有胶水库的情况下做到这一点。但是你需要提供你自己的函数ANativeActivity_onCreate,和一堆其他的回调。 android_main/android_app 组合是胶水库定义的接口。

    编辑:对于触摸坐标,使用AMotionEvent_getX/Y(),将事件对象作为第一个参数传递,指针的索引作为第二个参数传递。使用AMotionEvent_getPointerCount() 检索指针(触摸点)的数量。这是您对多点触控事件的本机处理。

    我应该每次都检测 [x,y] 位置,将其与 我的操纵杆的位置,存储以前的位置,比较 上一个位置和下一个位置来获取方向?

    简而言之,是的,你是。虚拟操纵杆没有内置平台支持;您处理触摸和坐标,并将其转化为应用程序的 UI 隐喻。这几乎就是编程的精髓。

    虽然不是“每次” - 只有当它发生变化时。 Android 是一个事件驱动的系统。

    现在,关于您的“我希望它在操作系统级别”的情绪。它在很多层面上都是错误的。首先,操作系统不欠你任何东西。操作系统就是它,接受它或离开它。其次,不愿意付出努力(也就是懒惰)在软件社区中通常是不受欢迎的。第三,操作系统代码仍然是代码。将某些东西移入操作系统可能会提高您的效率,但您为什么认为它会让用户察觉到差异?我们正在谈论的是触摸处理 - 不是特别占用 CPU 的任务。您是否真的构建了一个应用程序、配置文件并发现它的性能不足?在你这样做之前,永远不要猜测瓶颈在哪里。那个词是“过早优化”,这是每个人和他们叔叔的猫都会警告你的东西。

    【讨论】:

    • 这是通常的方法,我问的是 100% 原生活动;所以我需要使用 JNI 而我无法避免这种情况?假设我有 C/C++ 引擎的代码库,你的提示是关于使用 JNI 调用 java 函数?在这种情况下,我的应用程序的入口点是什么? Java 还是 C/C++?我想在这种情况下,我必须使用 Java 构建整个 UI,包括窗口,所以我的入口点是 Java 代码,但是如何将 EGL 本机缓冲区与 Java 连接起来呢?我得到了你的提示,但我不清楚实现,尤其是对于 EGL 缓冲区部分。
    • 仍然是 Java 类(其所有方法都是原生的)的 100% 原生活动与 NativeActivity 之间存在差异。前者可以而且应该使用 Android 布局,后者不能。决定你想要哪一个。是游戏吗?如果不是,那么可能是前者。是的,要回调 Java,您需要 JNI。此外,SO 不是一个讨论论坛 - 如果您还有其他问题,请作为新问题提出。
    • ii 一直在谈论 NativeActivity,我只想用 C/C++ 处理我的代码库,只用 NDK,你能确认或调整你的答案吗? NDK 语言和 NDK 示例都使用术语 NativeActivity,所以对于本地,我的意思是 100% C/C++。现在你能澄清一下吗?我会在其他问题中询问 EGL 吗?同样,有机会仅使用 NDK 构建 UI 回调吗?是的,它是关于游戏或与 OpenGL 相关技术类似的东西。
    • 郑重声明,NativeActivity 与纯粹的 C++ 活动不同。 NativeActivity 是封装原生代码的一种模式,但不是唯一的。
    • &lt;ndk root&gt;/samples/native-activity:我可以用这样的代码构建一个 UI 吗?
    【解决方案2】:

    Rawdrawandroid 表明没有什么是不可能的。使用它,您可以完全在 C/C++ 中编写 UI 和处理 UI 事件。

    注意:不会使用 java、classes.dex、字节码。

    示例应用:https://play.google.com/store/apps/details?id=org.cnlohr.colorchord

    请阅读 rawdraw 开发者如何处理常见情况:

    使用此框架,您可以获得:

    • 制作一个支持 OpenGL ES 的窗口
    • 加速度计/陀螺仪输入,多点触控
    • 用于按键输入的安卓键盘
    • 能够将资产文件存储在您的 APK 中并使用 AAssetManager 读取它们
    • 权限支持使用声音之类的东西。 https://github.com/cnlohr/cnfa 中的示例
    • 直接访问 USB 设备。 https://github.com/cnlohr/androidusbtest 中的示例

    NDK UI 可以用 Java 以外的方式编写。

    这也必须做一点,以将其粘贴到互联网上所有那些在 Stack Overflow 问题上发布“那是不可能的”或“你做错了”的 Luddite ......在 JNI 中请求权限“哦,你必须在 Java 中做到这一点”或其他类似的愚蠢的东西。我对你对什么是可能的或不可能的意见完全不感兴趣。这是计算机科学。没有限制。我可以做任何我想做的事。这只是一点点。你不拥有我。

    您可以从 C 访问 android api,就像 java 一样:

    附:如果你想要一堆例子来说明如何在 Android 上用 C 语言做很多你“需要”java 的事情,滚动到这个文件的底部:https://github.com/cntools/rawdraw/blob/master/CNFGEGLDriver.c - 它展示了如何使用 JNI 来编组大量的东西无需跳回 Java/Kotlin 领域即可进出 Android API。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-18
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多