/* * © 2010 The Android Open Source Project * * Лицензировано по лицензии Apache License, версия 2.0 ( "Лицензия"); *этот файл можно использовать только в соответствии с лицензией. *Копию лицензии можно получить на веб-сайте * * http://www.apache.org/licenses/LICENSE-2.0 * *Если только не требуется в соответствии с применимым законодательством или согласовано в письменном виде, программное обеспечение * распространяется в рамках лицензии на УСЛОВИЯХ "КАК ЕСТЬ", * БЕЗ ГАРАНТИЙ И УСЛОВИЙ ЛЮБОГО РОДА, явно выраженных и подразумеваемых. * См. лицензию для получения информации об определенных разрешениях по использованию языка и * ограничениях в рамках лицензии. * */ #ifndef _ANDROID_NATIVE_APP_GLUE_H #define _ANDROID_NATIVE_APP_GLUE_H #include #include #include #include #include #include #ifdef __cplusplus extern "C" { #endif /** * Интерфейс NativeActivity, предоставленный , * основан на наборе предоставленных приложением обратных вызовов, которые вызываются *основным потоком действия при возникновении определенных событий. * * Это означает, что ни один из данных обратных вызовов _не_ _должен_ блокироваться, иначе * существует риск принудительного закрытия приложения системой. Эта модель программирования * прямая, простая, но имеет ограничения. * * Статическая библиотека threaded_native_app используется для обеспечения другой * модели выполнения, в которой приложение может реализовать свой собственный цикл главного события * в другом потоке вместо этого. Это работает так: * * 1/ Приложение должно предоставить функцию с именем android_main(), которая * будет вызываться при создании действия в новом потоке, * отличающемся от основного потока действия. * * 2/ android_main() получает указатель на допустимую структуру android_app, * которая содержит ссылки на другие важные объекты, например экземпляр объекта * ANativeActivity, где выполняется приложение. * * 3/ Объект android_app содержит экземпляр ALooper, который уже * ожидает две важных вещи: * * - событий жизненного цикла действия (например, "pause", "resume"). См. объявления APP_CMD_XXX * ниже. * * - входных событий, поступающих из очереди AInputQueue, присоединенной к действию. * * Каждое из этих событий соответствует идентификатору ALooper, возвращенному * ALooper_pollOnce со значениями LOOPER_ID_MAIN и LOOPER_ID_INPUT, *, соответственно. * * Ваше приложение может использовать тот же ALooper для прослушивания дополнительных * дескрипторов файла. Они могут быть основаны либо на обратных вызовах, либо поступают с идентификаторами возврата, * начинающимися с LOOPER_ID_USER. * * 4/ При получении события LOOPER_ID_MAIN или LOOPER_ID_INPUT * возвращенные данные будут указывать на структуру android_poll_source. Для нее * можно вызвать функцию process() и заполнить android_app->onAppCmd * и android_app->onInputEvent, для того чтобы они вызывались для вашей собственной обработки * события. * * Вместо этого можно вызвать функции нижнего уровня для чтения и обработки * данных непосредственно... посмотрите на реализации process_cmd() и process_input() * в приклеивании, чтобы выяснить, как это делается. * * См. пример "native-activity" в NDK с * полной демонстрацией использования. Также посмотрите JavaDoc в NativeActivity. */ struct android_app; /** * Данные, связанные с ALooper fd, которые будут возвращаться как outData * при готовности данных в этом источнике. */ struct android_poll_source { // Идентификатор данного источника. Может быть LOOPER_ID_MAIN или // LOOPER_ID_INPUT. int32_t id; // android_app, с которым связан данный идентификатор. struct android_app* app; // Функция, вызываемая для стандартной обработки данных из // этого источника. void (*process)(struct android_app* app, struct android_poll_source* source); }; /** * Это интерфейс стандартного кода приклеивания поточного * приложения. В этой модели код приложения выполняется * в своем собственном потоке, отдельном от основного потока процесса. * Не требуется связь данного потока с ВМ Java *, хотя это необходимо для выполнения вызовов JNI любых * объектов Java. */ struct android_app { // Приложение может поместить указатель на свой собственный объект состояния // здесь, если нужно. void* userData; // Введите здесь код функции для обработки основных команд приложения (APP_CMD_*) void (*onAppCmd)(struct android_app* app, int32_t cmd); // Введите здесь код функции для обработки входных событий. Сейчас // событие уже было предварительно отправлено и будет завершено при // возврате. Верните 1, если событие обработано, 0 — для любой диспетчеризации // по умолчанию. int32_t (*onInputEvent)(struct android_app* app, AInputEvent* event); // Экземпляр объекта ANativeActivity, в котором выполняется это приложение. ANativeActivity* activity; // Текущая конфигурация, в которой выполняется это приложение. AConfiguration* config; // Это последнее сохраненное состояние экземпляра, предоставленное во время создания. // Значение равно NULL, если состояния не было. Можно использовать это по мере необходимости; // память останется доступной до вызова android_app_exec_cmd() для // APP_CMD_RESUME, после чего она будет освобождена, а savedState получит значение NULL. // Эти переменные необходимо изменять только при обработке APP_CMD_SAVE_STATE, // когда их значения будут инициализироваться в NULL и можно будет выполнить malloc для // состояния и поместить здесь информацию. В этом случае память будет // освобождена позднее. void* savedState; size_t savedStateSize; // ALooper, связанный с потоком приложения. ALooper* looper; // Если значение не равно NULL, то это входная очередь, из которой приложение будет // получать входные события пользователя. AInputQueue* inputQueue; // Если значение не равно NULL, то это поверхность окна, в котором приложение может рисовать. ANativeWindow* window; // Текущий прямоугольник содержимого окна. Это область, в которой // должно помещаться содержимое окна, чтобы его видел пользователь. ARect contentRect; // Текущее состояние действия приложения. Может быть APP_CMD_START, // APP_CMD_RESUME, APP_CMD_PAUSE или APP_CMD_STOP; см. ниже. int activityState; // Значение не равно нулю, когда NativeActivity приложения // разрушается и ожидает завершения потока приложения. int destroyRequested; // ------------------------------------------------- // Ниже показан "частная" реализация кода прилипания. pthread_mutex_t mutex; pthread_cond_t cond; int msgread; int msgwrite; pthread_t thread; struct android_poll_source cmdPollSource; struct android_poll_source inputPollSource; int running; int stateSaved; int destroyed; int redrawNeeded; AInputQueue* pendingInputQueue; ANativeWindow* pendingWindow; ARect pendingContentRect; }; enum { /** * Идентификатор данных Looper команд, поступающих из основного потока приложения, который * возвращается как идентификатор от ALooper_pollOnce(). Данные для этого идентификатора * являются указателем на структуру android_poll_source. * Их можно извлечь и обработать с помощью android_app_read_cmd() * и android_app_exec_cmd(). */ LOOPER_ID_MAIN = 1, /** * Идентификатор данных Looper событий, поступающий из AInputQueue окна * приложения, который возвращается как идентификатор из * ALooper_pollOnce(). Данные этого идентификатора являются указателем на структуру * android_poll_source. Их можно прочитать через объект inputQueue * приложения android_app. */ LOOPER_ID_INPUT = 2, /** * Запуск определяемых пользователем идентификаторов ALooper. */ LOOPER_ID_USER = 3, }; enum { /** * Команда из основного потока: AInputQueue изменена. После обработки * этой команды android_app->inputQueue будет обновлена в новую очередь * (или NULL). */ APP_CMD_INPUT_CHANGED, /** * Команда из основного потока: новое окно ANativeWindow готово к использованию. После * получения этой команды окно android_app-> будет содержать новую поверхность *окна. */ APP_CMD_INIT_WINDOW, /** * Команда из основного потока: существующее окно ANativeWindow необходимо * прекратить. После получения этой команды окно android_app->по-прежнему * содержит существующее окно; после вызова android_app_exec_cmd * оно получит значение NULL. */ APP_CMD_TERM_WINDOW, /** * Команда из основного потока: текущее окно ANativeWindow изменило размер. * Перерисуйте согласно новом размеру. */ APP_CMD_WINDOW_RESIZED, /** * Команда из основного потока: системе необходимо, чтобы текущее окно ANativeWindow * было перерисовано. Необходимо перерисовать окно перед ее передачей в * android_app_exec_cmd(), чтобы избежать переходных сбоев рисования. */ APP_CMD_WINDOW_REDRAW_NEEDED, /** * Команда из основного потока: область содержимого окна изменена * таким образом, что из функционального ввода окно показывается или скрывается. Можно * найти новый прямоугольник содержимого в android_app::contentRect. */ APP_CMD_CONTENT_RECT_CHANGED, /** * Команда из основного потока: окно действия приложения получило * фокус ввода. */ APP_CMD_GAINED_FOCUS, /** * Команда из основного потока: окно действия приложения потеряло * фокус ввода. */ APP_CMD_LOST_FOCUS, /** * Команда из основного потока: изменена текущая конфигурация устройства. */ APP_CMD_CONFIG_CHANGED, /** * Команда из основного потока: системе не хватает памяти. * Попробуйте уменьшить использование памяти. */ APP_CMD_LOW_MEMORY, /** * Команда из основного потока: действие приложения было запущено. */ APP_CMD_START, /** * Команда из основного потока: действие приложения было возобновлено. */ APP_CMD_RESUME, /** * Команда из основного потока: приложение должно создать новое сохраненное состояние * для себя, чтобы восстанавливаться из него позднее в случае необходимости. Если вы сохранили состояние, * выделите его с использованием malloc и поместите в android_app.savedState с * размером android_app.savedStateSize. Память будет освобождена * позднее. */ APP_CMD_SAVE_STATE, /** * Команда из основного потока: пауза в действии приложения. */ APP_CMD_PAUSE, /** * Команда из основного потока: действие приложения было остановлено. */ APP_CMD_STOP, /** * Команда из основного потока: действие приложения уничтожается, * и ожидает очистки потока приложения и выхода перед обработкой. */ APP_CMD_DESTROY, }; /** * Вызовите, когда ALooper_pollAll() возвращает LOOPER_ID_MAIN, при чтении следующего сообщения команды *приложения. */ int8_t android_app_read_cmd(struct android_app* android_app); /** * Вызовите с помощью команды, возвращенной android_app_read_cmd() для выполнения * начальной предварительной обработки данной команды. Можно выполнить собственные * действия для команды после вызова этой функции. */ void android_app_pre_exec_cmd(struct android_app* android_app, int8_t cmd); /** * Вызовите с помощью команды, возвращенной android_app_read_cmd(), для * окончательной предварительной обработки данной команды. Необходимо завершить собственные * действия с командой до вызова этой функции. */ void android_app_post_exec_cmd(struct android_app* android_app, int8_t cmd); /** * Это функция, которую должен реализовать код приложения, представляет собой * главный вход в приложение. */ extern void android_main(struct android_app* app); #ifdef __cplusplus } #endif #endif /* _ANDROID_NATIVE_APP_GLUE_H */