Модераторы Andrey Efimov Опубликовано 15 февраля, 2016 Модераторы Опубликовано 15 февраля, 2016 Ссылка: http://delphifmandroid.blogspot.ru/2016/02/alarmmanager-rad-studio.html Автор: Ефимов Андрей Описание: [AlarmManager] Автозапуск приложения в назначенное время Brovin Yaroslav, Dev, AngryOwl и 3 других 6 Цитата
ENERGY Опубликовано 22 февраля, 2017 Опубликовано 22 февраля, 2017 (изменено) Привет. Я тут узнал что оказывается начиная с XE7 не нужно создавать Dex файл затем подменять его на classes.dex. Достаточно создать Jar файл и подключить его к проекту. Я проверил на новом проекте - все прекрасно работает. Проект автозапускается из AlarmManager (делал на основе этой статьи ) .А Dex файлы нужны для XE5 и XE6. Узнал я это из этого вопроса на stackoverflow. Пожалуйста Вы не могли бы обновить статью? Просто дописав эту заметку? На мой взгляд это важно. Я также обновил бат файл, он будет примерно такой: @echo off setlocal if x%ANDROID% == x set ANDROID=c:\Users\Alex\Documents\Embarcadero\Studio\18.0\PlatformSDKs\android-sdk-windows set ANDROID_PLATFORM=%ANDROID%\platforms\android-24 set PROJ_DIR=%CD% set VERBOSE=0 echo. echo Compiling the Java service activity source files echo. mkdir output 2> nul mkdir output\classes 2> nul if x%VERBOSE% == x1 SET VERBOSE_FLAG=-verbose javac -source 1.7 -target 1.7 %VERBOSE_FLAG% -Xlint:deprecation -cp %ANDROID_PLATFORM%\android.jar -d output\classes src\com\TestReceiver\AlarmReceiver.java echo. echo Creating jar containing the new classes echo. mkdir output\jar 2> nul if x%VERBOSE% == x1 SET VERBOSE_FLAG=v jar c%VERBOSE_FLAG%f output\jar\test_classes.jar -C output\classes com echo. echo Now we have the end result, in directory output\jar\ pause Также еще один ньюанс. Для варианта 2 никакой Dex файл не нужен. Также не нужен и Jar файл. Также ничего не нужно в манифест добавлять, т.к. вызывается activity напрямую, без BroadcastReceiver.Но это только для варианта 2. Для первого варианта (Broadcast) все это нужно.Я проверял на новом проекте с вариантом 2 - все работает. Изменено 23 февраля, 2017 пользователем ENRGY Евгений Корепов и Rusland 2 Цитата
Модераторы Andrey Efimov Опубликовано 23 февраля, 2017 Автор Модераторы Опубликовано 23 февраля, 2017 По поводу "как подключать JAVA класс": процитирую ответ в блоге: Цитата По поводу JAR файла. Для подобных статей, я всегда стараюсь детально описать каждый шаг дальнейших действий. Это направлено на то, чтобы человек, начал понимать, что он делает, а не просто копипастить и потом на форуме кучу тем создавать с вопросами, как и что. Если вам хочется добавлять JAR через Project Manager, то и пожалуйста, http://delphifmandroid.blogspot.ru/2015/03/jar.html По поводу Цитата "Также еще один ньюанс. Для варианта 2 никакой Dex файл не нужен. Также не нужен и Jar файл. Также ничего не нужно в манифест добавлять, т.к. вызывается activity напрямую, без BroadcastReceiver.Но это только для варианта 2. Для первого варианта (Broadcast) все это нужно. " Цитата из ответа в блоге: Цитата Да, всё правильно, для второго варианта dex не нужен. Два примера использованы в одном приложении. Видимо недостаточно понятно описал в статье, различия между getBroadcast и getActivity, а также между двумя тестовыми вариантами. Расчёт был на то, что читатель хотя бы поинтересуется в официальной справке, что делают два этих метода. К слову, по названию методов уже понятно, для чего каждый из них предназначен. Но раз есть один прецедент, то может быть и второй. Поэтому я уже добавил прямое указание различий у двух примеров. p.s. Не нужно заниматься кросспостингом. Update. Все три статьи обновлены. Конкретно в этой статье постарался объяснить в тексте поверхностные отличия двух примеров, которые мне, до сегодняшнего дня казались очевидными. Чуть позже выложу ещё всё на ГитХаб, чтобы не терялось Равиль Зарипов (ZuBy), Rusland и ENERGY 3 Цитата
ENERGY Опубликовано 23 февраля, 2017 Опубликовано 23 февраля, 2017 (изменено) Большое спасибо что поддерживаете статьи в актуальном состоянии! Я также часто ссылаюсь на ваши статьи на других сайтах - англоязычных. Что удивительно подобная информация редко вcтречается на англоязычных сайтах, к примеру про Alarm Manager и Delphi нет ни одной статьи, даже на сайте Embarcadero этот вопрос долгое время висел без ответа, пока я не дал ссылку на вашу статью. Непопулярность Delphi Mobile как раз и связана с тем, кроме цены, что на многие вопросы почти нет ответов, при этом Java сообщество пестрит готовыми Copy Paste решениями, что увеличивает и без того большую армию пользователей. Но Java нет на iOS. И на Java не сделаешь кроссплатформенный проект с единым кодом и GUI, поэтому Delphi здесь на шаг впереди. Поэтому мне и показалось важным указать на ньюанс с JAR в темах связанными с DEX (заодно кстати и осветили баг с батником, помните javac -source 1.7 -target 1.7? - ведь на этом этапе у человека изучающего Delphi может пропасть желание изучать дальше), столько плясок с бубном с этим dex, и разбросать чтобы больше людей увидели более удобный и простой вариант. Изменено 23 февраля, 2017 пользователем ENRGY Евгений Корепов и Rusland 2 Цитата
Евгений Корепов Опубликовано 25 февраля, 2017 Опубликовано 25 февраля, 2017 Спасибо за статью, все отлично работает. Вот только не допру как запустить не приложение, а сервис. Все темы в разделе Сервис перечитал, но информацию не нашел :-( Делаю по второму примеру: procedure TForm2.Button2Click(Sender: TObject); var Intent: JIntent; PendingIntent: JPendingIntent; begin // Создаём Интент Intent := TJIntent.Create; Intent.setClassName(TAndroidHelper.Context, StringToJString('com.embarcadero.firemonkey.FMXNativeActivity')); // Оборачиваем Интент в PendingIntent PendingIntent := TJPendingIntent.JavaClass.getActivity(TAndroidHelper.Context, 1, Intent, 0); // Устанавливаем оповещение TAndroidHelper.AlarmManager.&set(TJAlarmManager.JavaClass.RTC_WAKEUP, getTimeAfterInSecs(30), PendingIntent); end; Но activity "com.embarcadero.firemonkey.FMXNativeActivity" одинаковые у приложения и сервиса. Запускается именно приложение. Как сделать только запуск сервиса? Цитата
Модераторы Andrey Efimov Опубликовано 25 февраля, 2017 Автор Модераторы Опубликовано 25 февраля, 2017 Евгений, внимательнее читайте статью, там есть раздел теории, а конкретно такие строчки: Цитата Основные методы: getActivity –для запуска Activity getBroadcast – для BroadcastReciver getService – для Service это половина ответа на ваш вопрос. Вторую половину можно найти например в этой статье [Android Service+BroadcastReceiver] Автозапуск службы после рестарта ОС. В ней говорится, какое имя будет у сервиса после создания: Цитата Имя сервиса в студии всегда будет иметь начало «com.embarcadero.services.», а далее будет написано название вашего Сервиса. Rusland и Равиль Зарипов (ZuBy) 2 Цитата
Евгений Корепов Опубликовано 25 февраля, 2017 Опубликовано 25 февраля, 2017 Andrey Efimov, огромное спасибо! Так и думал что глаз замылился и ответ перед глазами! Причем вашу статью раза четыре перечитал :-) Цитата
ENERGY Опубликовано 7 марта, 2017 Опубликовано 7 марта, 2017 (изменено) Блин, проблема. Уже сутки не могу решить. Если телефон подключен к USB - то Alarm запускает активити. Если он на батареях, то он спит себе дальше и ничего не происходит. Ну понятно почему, - на батареях он уходит в sleep режим. Я уже пробовал и WakeLock и флаги FLAG_TURN_SCREEN_ON or FLAG_DISMISS_KEYGUARD or FLAG_SHOW_WHEN_LOCKED.- все в OnCreate (даже до и после Application.Initialize пробовал), пробовал и первый и второй метод со статьи (Activity и BroadcastReceiver) Проблема в том, что когда срабатывает RTC - система просыпается, но просыпается ненадолго. Где то на 2-3 секунды. Т,е. фактически не доходит до кода с WakeLock или кода с флагами (я уже пробовал его и до и после инициализации). Есть один рабочий вариант - ставить WakeLock в java коде с BroadcastReceiver (это кстати рекомендованный способ для запуска сервисов) - это работает, я пробовал, но я пока не знаю как отключить его. Пример Возможно у кого то есть рабочий вариант? Был бы очень благодарен. Странно что никто об этом не говорил.. Изменено 7 марта, 2017 пользователем ENRGY Цитата
ENERGY Опубликовано 7 марта, 2017 Опубликовано 7 марта, 2017 (изменено) Ребят, а можете отозваться у кого работает без Wake Lock? Возможно у автора статьи, ведь Андрей даже никаких намеков не давал. Я просто удивлен что никто с этим не сталкивался. Изменено 7 марта, 2017 пользователем ENRGY Цитата
ENERGY Опубликовано 7 марта, 2017 Опубликовано 7 марта, 2017 (изменено) Фух. Наконец то проспался и понял как сделать. Нужно просто поставить Alarm еще раз, напр. чтобы выполнился через 3 секунды. (неудобный, есть вероятность попасть на ошибку) просто вызвать его в Broadcast после Activity . (не всегда работает) Запустить Activity и в BroadcastReceiver подождать 8 секунд, а затем там же снять WakeLock. Это вариант работает прекрасно. Также с этим кодом Alarm срабатывает если Activity уже запущено либо в фоне. Нужно перехватывать WillBecomeForeground, BecameActive и там включать экран. Процессор включается в WakeLock, но не на долго, вам нужно включить экран при помощи функции ниже, сделать работу затем отключить экран). В моем случае, в отдельном потоке крутиться самописный планировщик, для других задач, который возбуждает события, по нему я и включаю\отключаю экран. Итак выстраданный бесcонными ночами Java код, обратите внимание на TestLauncher.putExtra("StartedFromAM", true), это чтобы знать из Activity что запустились из Broadcast (предложенный Blong'гом EXTRA_ALARM_COUNT с BroadcastReceiver всегда вернет ноль, он работает только если запускать напрямую Activity!) : package com.TestReceiver; import android.content.BroadcastReceiver; import android.content.Context; import android.content.Intent; import android.os.PowerManager; import android.os.Handler; public class AlarmReceiver extends BroadcastReceiver { private static PowerManager.WakeLock mWakeLock; @Override public void onReceive(Context context, Intent intent) { if (mWakeLock == null) { PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE); mWakeLock = pm.newWakeLock(PowerManager.PARTIAL_WAKE_LOCK, "Delphi"); mWakeLock.acquire(); } Intent TestLauncher = new Intent(); TestLauncher.setClassName(context, "com.embarcadero.firemonkey.FMXNativeActivity"); TestLauncher.setFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP | Intent.FLAG_ACTIVITY_NEW_TASK); // I TestLauncher.putExtra("StartedFromAM", true); context.startActivity(TestLauncher); // Handler h = new Handler(); h.postDelayed(new Runnable(){ public void run(){ mWakeLock.release(); mWakeLock = null; } }, 8000); //Toast.makeText(context, "Reelase! ("+mcounter.toString()+")", Toast.LENGTH_SHORT).show(); // For example } } PARTIAL_WAKE_LOCK означает что процессор во время выполнения этого кода, не будет уходить в спящий режим. Теперь в OnCreate нашей формы добавляем флаги чтобы включить экран, но при условии что запустились мы из AlarmManager : function StartedFromAlarmManager: boolean; begin {$IFDEF ANDROID} Result := TAndroidHelper.Activity.getIntent.getBooleanExtra(StringToJString('StartedFromAM'), false); // this will work only if using Activity instead of Broadcast - TJPendingIntent.JavaClass.getActivity: // Result := TAndroidHelper.Activity.getIntent.getIntExtra(TJIntent.JavaClass.EXTRA_ALARM_COUNT, 0); {$ELSE} Result := false; {$ENDIF} end; {$IFDEF ANDROID} procedure TurnOnAndKeepScreenAndroid(aEnable: boolean); var vFlags: integer; begin vFlags := TJWindowManager_LayoutParams.JavaClass.FLAG_TURN_SCREEN_ON or TJWindowManager_LayoutParams.JavaClass.FLAG_DISMISS_KEYGUARD or TJWindowManager_LayoutParams.JavaClass.FLAG_SHOW_WHEN_LOCKED or TJWindowManager_LayoutParams.JavaClass.FLAG_KEEP_SCREEN_ON; if aEnable then begin CallInUIThread ( // uses FMX.Helpers.Android procedure begin TAndroidHelper.Activity.getWindow.setFlags (vFlags, vFlags); end ); end else CallInUIThread ( procedure begin TAndroidHelper.Activity.getWindow.clearFlags (vFlags); end ); end; {$ENDIF} И сразу же отключаем наш WakeLock устанавливая второй раз Alarmmanager на срабатывание через 3 сек (соответственно запуститься BroadcastReceiver и освободит WakeLock). (уже отключается сам в Broadcast сразу после старта Activity)- т.к. во флагах окна, уже указан FLAG_KEEP_SCREEN - это будет держать экран и систему включенной. Не забудьте поставить разрешение WAKE LOCK = true! Изменено 8 марта, 2017 пользователем ENRGY amok, Rusland и Евгений Корепов 2 1 Цитата
Рекомендуемые сообщения
Присоединяйтесь к обсуждению
Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.