"Intent" є головною можливістю для міжпроцесорної взаємодії Android. В основному, Intent є об'єктом, який обробляється операційною системою і передається потім одній або більшій кількості встановлених програм, ґрунтуючись на його змісті. Це може бути екземпляр запиту відображення відео, в даному випадку тип intent повинен бути ACTION_VIEW і тип mime повинен бути встановлений відповідний. Програми можуть підписуватись на відповідні Intents у налаштуваннях фільтра intent у своїх маніфест файлах. Вперше користувачеві пристрою буде надано вибір, які типи intent відомі програмі та на які можна передплатити. Якщо вони вибрані, вони будуть встановлені за замовчуванням, або вибрані при питанні від кожного екземпляра програми у разі потреби.
Це перша з кількох статей, як використовувати intents з Qt для Android.
Сам механізм має досить загальний характер. Те, що описано вище є одним із способів використання, але intents також можуть бути використані і для іншого: Одним із таких випадків є запуск сервісів усередині програми. Це зазвичай називається "explicit intent", що означає, що передбачено для запуску повне ім'я сервісу, і не може бути перехоплено іншим додатком.
Іншим способом використання intents є широкомовний варіант (broadcast) для екземплярів, коли змінюється тимчасова зона пристрою. У цей час як дії описані вище дозволяють запускати тільки один певний додаток, обраний користувачем, то при широкомовному варіанті сигнал буде переданий у всі додатки, які були на нього підписані.
Цей варіант націлений на Android пристрої, але схожий механізм, званий app extensions , був введений у iOS 8.
У цій першій статті про intents на Android сфокусуємося на найпростішому варіанті використання: Створення прихованого intent з Qt для запуску невизначеної програми на цільовому пристрої. Наприклад, зроблено простий додаток, який представляє рецепти їжі. Кожен рецепт має час приготування. Натиснувши кнопку, ви можете встановити таймер, використовуючи зворотний відлік на пристрої. (Для більш корисного застосування можна надати кнопку встановлення часу для кожного кроку приготування рецепту, але в цьому простому прикладі використовуватимемо лише один таймер.)
Не будемо вдаватися у подробиці того, як програма була написана, але кому цікаво, то код може бути знайдений тут . Жодних зусиль для покращення зовнішнього вигляду додатка не було, тому не звертайте на це уваги. Програма базується на базі даних SQLite (яка заповнена деяким фейковим контентом при першому запуску) і має дуже простий інтерфейс користувача, написаний на Qt Quick Controls 2, який дозволяє користувачеві вибрати рецепт зі списку, подивитися його опис на окремій сторінці і натиснути кнопку в рецепті для установки таймера до системи.
А тепер сфокусуємось на коді, який фактично вимагає таймер від системи. Це міститься у файлі recipe.cpp , функції Recipe::createTimer() . У прикладі ми використовуємо наступний тип intent - AlarmClock.ACTION_SET_TIMER .
Ми будемо використовувати для цього зручний JNI API із модуля Qt Android Extras . Давайте пройдемо за кодом крок за кроком.
QAndroidJniObject ACTION_SET_TIMER = QAndroidJniObject::getStaticObjectField("android/provider/AlarmClock", "ACTION_SET_TIMER"); QAndroidJniObject intent("android/content/Intent", "(Ljava/lang/String;)V", ACTION_SET_TIMER.object());
Першим кроком створимо intent. Ми приймаємо ідентифікатор ACTION_SET_TIMER intent. Він є статичним учасником у android.provider.AlarmClock класі та має рядковий тип даних (String). Зауважте, що використання слешів замість точок у імені пакета класу. Це співвідноситься з представленням імен пакетів у байткоді (так склалося з історичних причин, дивіться специфікацію . 1) ) і відтак також використовується у підписі JNI.
Оскільки ми використовуємо лише функції з Qt Android Extras і не використовуємо явні виклики до JNI API, ми можемо не турбуватися про еталонному управлінні. Це головна зручність цього API.
Наступним кроком ми створимо об'єкт intent. Ми зробимо це, побудувавши QAndroidJniObject і передавши його в JNI-розбірник підписів Java конструктора, який бажаємо викликати, а також передамо ID дії, яку хочемо отримали з класу AlarmClock.
QAndroidJniObject EXTRA_MESSAGE = QAndroidJniObject::getStaticObjectField("android/provider/AlarmClock", "EXTRA_MESSAGE"); QAndroidJniObject messageObject = QAndroidJniObject::fromString(message); intent.callObjectMethod("putExtra", "(Ljava/lang/String;Ljava/lang/String;)Landroid/content/Intent;", EXTRA_MESSAGE.object(), messageObject.object()); QAndroidJniObject EXTRA_LENGTH = QAndroidJniObject::getStaticObjectField("android/provider/AlarmClock", "EXTRA_LENGTH"); intent.callObjectMethod("putExtra", "(Ljava/lang/String;I)Landroid/content/Intent;", EXTRA_LENGTH.object(), jint(m_time * 60)); QAndroidJniObject EXTRA_SKIP_UI = QAndroidJniObject::getStaticObjectField("android/provider/AlarmClock", "EXTRA_SKIP_UI"); intent.callObjectMethod("putExtra", "(Ljava/lang/String;Z)Landroid/content/Intent;", EXTRA_SKIP_UI.object(), jboolean(true));
Наступним кроком ми встановимо кілька аргументів, які хочемо надіслати в обробник дії Activity. Ми передаємо в описі таймер та кількість секунд для встановлення.
QAndroidJniObject activity = QtAndroid::androidActivity(); QAndroidJniObject packageManager = activity.callObjectMethod("getPackageManager", "()Landroid/content/pm/PackageManager;"); QAndroidJniObject componentName = intent.callObjectMethod("resolveActivity", "(Landroid/content/pm/PackageManager;)Landroid/content/ComponentName;", packageManager.object());
Потім ми дозволяємо цю дію. Вона скаже системі перевірити, чи є програма для обробки дії ACTION_SET_TIMER. І тоді ми спочатку отримаємо поточну діяльність (у нашому поточному контексті) для того, щоб отримати відповідний пакетний менеджер. Потім викличемо resolveActivity() на intent для передачі його в пакетний менеджер.
if (componentName.isValid()) { QtAndroid::startActivity(intent, 0); } else { qWarning() << "Unable to resolve activity"; }
Якщо повернене ім'я компонента є ненульовим, ми запускаємо activity використовуючи зручну функцію в Qt Android Extras. Якщо відповідної діяльності не було знайдено, тоді зробимо висновок про помилку в консоль. Правильне застосування має повідомляти про помилку в інтерфейсі користувача, але зауважте, що операційна система також повідомить користувачеві про проблеми в цьому місці.
Есть ли возможность приведения java типа у QAndroidJniObject? Интересует конкретно class to