Можно ли создавать элементы интерфейса с помощью 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.