Можно ли создавать элементы интерфейса с помощью NDK? - отсутствие спецификаций в Android документах

После прочтения соответствующих документов я не понимаю, смогу ли я создать такие вещи, как кнопки или другие элементы пользовательского интерфейса, используемые для получения пользовательского ввода, используя только код C++/C, скомпилированный с помощью NDK.

Нет проблем, когда я хочу обработать "окно" или действие, которое должно оставаться в фокусе, но я не понимаю, как создать пользовательский интерфейс с элементами для обратных вызовов и пользовательского ввода.

Странно, что существует оконная инфраструктура, но без каких-либо следов обратных вызовов для элементов пользовательского интерфейса.

Могу ли я создать сенсорные кнопки или виртуальный геймпад с помощью NDK?


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

Я нашел это изображение здесь

Теперь моя проблема и фокус этого вопроса:

Предположим, что я могу разместить и нарисовать этот виртуальный джойстик, как я могу обнаружить только движения и иметь обратный вызов, как Joystick.onUp или же Joystick.onDown с Android и используя только NDK?

Если в NDK нет таких обратных вызовов, я должен каждый раз обнаруживать позицию [x,y], сравнивать ее с положением моего джойстика, сохранять предыдущую позицию, сравнивать предыдущую и следующую позиции. получить направление?

Поскольку датчик генерирует события с очень высокой скоростью, я думаю, что построение этого самостоятельно, учитывая только необработанную пару X,Y, в конечном итоге приведет к созданию действительно неэффективной системы управления, поскольку она не будет оптимизирована на уровне ОС при соответствующей датчик звонков.

В соответствии с примером NativeActivity также неясно, как обрабатывать несколько точек касания, например, как я могу обрабатывать 2 события касания одновременно?

Просто рассмотрите изображение выше и подумайте о наличии только координаты x, y для 1 точки касания и о том, как я могу решить это эффективным способом, который поддерживается NDK.

Благодарю.

2 ответа

Решение

Что вы можете. Читайте о вызове Java из C(++) и вызывайте соответствующие функции Java - либо создавайте элементы пользовательского интерфейса (макеты, кнопки и т. Д.) По одному, либо загружайте макет XML. Для этого нет специального C-интерфейса, но есть Java, который можно вызвать.

Если это не игра, и вы не собираетесь делать свой собственный рисунок через OpenGL ES. Я не уверен, что вы можете смешивать и сочетать.

В NativeActivityвы все еще можете получить указатель на объект Java Activity и вызвать его методы - это clazz член ANativeActivity структура, которая передается вашему android_main в качестве параметра, через android_app состав. Возьми этот указатель, возьми JNIEnv* от того же, и назначить макет.

Как это будет взаимодействовать с рисунком OpenGL, я не уверен.

РЕДАКТИРОВАТЬ: о создании собственной обработки ввода. Ключевой обратный вызов onInputEvent(struct android_app* app, AInputEvent* event) в android_app состав. Поместите ваш обратный вызов там, 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 является статической библиотекой, которая обеспечивает некоторые C-мосты для API, которые обычно используются через Java.

Вы можете сделать это и без библиотеки клея. Но тогда вам нужно будет предоставить свою собственную функцию ANativeActivity_onCreateи множество других обратных вызовов. android_main/android_app combo - это интерфейс, определенный библиотекой glue.

РЕДАКТИРОВАТЬ: для сенсорных координат, используйте AMotionEvent_getX/Y(), передавая объект события в качестве первого параметра и индекс указателя в качестве второго. использование AMotionEvent_getPointerCount() чтобы получить количество указателей (точек соприкосновения). Это ваша нативная обработка событий мультитач.

Я должен каждый раз определять положение [x,y], сравнивать его с положением моего джойстика, сохранять предыдущую позицию, сравнивать предыдущую и следующую позиции, чтобы получить направление?

Короче говоря, да. Нет встроенной поддержки платформ для виртуальных джойстиков; вы имеете дело с касаниями и координатами и переводите их в метафору пользовательского интерфейса вашего приложения. Это в значительной степени суть программирования.

Не "каждый раз", хотя - только когда это меняется. Android - это система, управляемая событиями.

Теперь о вашем настроении "Я хочу это на уровне ОС". Это НЕПРАВИЛЬНО на многих уровнях. Во-первых, ОС вам ничего не должна. ОС - это то, что есть, возьми или оставь. Во-вторых, нежелание расширять свои усилия (AKA ленив) обычно вызывает недовольство в сообществе разработчиков программного обеспечения. В-третьих, код ОС все еще код. Перемещение чего-либо в ОС может принести вам некоторую эффективность, но как вы думаете, почему это будет заметно для пользователя? Мы говорим о сенсорной обработке - не особо трудоемкая задача. Вы действительно создали приложение, профиль и обнаружили, что его производительность недостаточна? Пока вы этого не сделаете, никогда не предполагайте, где будет узкое место. Слово для этого - "преждевременная оптимизация", и от этого каждый и кот дяди будут предупреждать вас.

Rawdrawandroid показывает, что нет ничего невозможного. Используя это, вы можете писать пользовательский интерфейс и обрабатывать события пользовательского интерфейса полностью на C / C++.

Примечание: java, classes.dex, байт-код не используются.

Пример приложения: https://play.google.com/store/apps/details?id=org.cnlohr.colorchord

Прочтите, как разработчик rawdraw решает распространенные ситуации:

С помощью этого фреймворка вы получаете:

  • Сделать окно с поддержкой OpenGL ES
  • Акселерометр / гироскоп, мультитач
  • Клавиатура Android для ввода клавиш
  • Возможность хранить файлы ресурсов в APK и читать их с помощью AAssetManager.
  • Поддержка разрешений на использование таких вещей, как звук. Пример в https://github.com/cnlohr/cnfa
  • Прямой доступ к USB-устройствам. Пример в https://github.com/cnlohr/androidusbtest

Пользовательский интерфейс NDK можно писать не на java.

Немного из этого также необходимо сделать, чтобы прикрепить это ко всем тем луддитам в Интернете, которые публикуют «это невозможно» или «вы делаете это неправильно» на вопросы о переполнении стека ... Запрос разрешений в JNI «о, у вас есть сделать это на Java »или что-то в этом роде. Мне совершенно неинтересно ваше мнение о том, что возможно, а что нет. Это информатика. Нет никаких ограничений. Я могу делать все, что хочу. Это просто биты. Ты не владеешь мной.

Вы получаете доступ к android api из C, так же, как java:

PS Если вам нужна куча примеров того, как делать на C на Android массу вещей, для которых вам «нужна» java, прокрутите этот файл до конца: - он показывает, как использовать JNI для маршаллинга https://github.com/cntools/rawdraw/blob/master / CNFGEGLDriver.cбольшого количества вещей в / из Android API без необходимости возвращаться в мир Java / Kotlin.

Другие вопросы по тегам