Перейти к содержанию
Fire Monkey от А до Я

[Статья][Android] Приложение будильник. Использование AlarmManager в FireMonkey на Андроиде


Рекомендуемые сообщения

  • Администраторы

Статья посвящена использованию Андроид AlarmManager в delphi приложения, позволяющего выполнять код в назначенное время даже, когда приложение закрыто. Все это рассматривается на примере приложения Будильник.

Ссылка на комментарий
  • 1 месяц спустя...

отредактировал

Делаю по статье с небольшими отклонениями, на скрине стрелкой у меня возникает ошибка - не могу разобраться

https://yadi.sk/i/wuXpygfIqVjxr

Я пытаюсь добиться того что я из программы поставил таймер на автозапуск сервиса каждые 10 секунд.
     

сгенерировал вот такой файл

 


unit Androidapi.JNI.BootCompletedReceiver;

interface

uses
  Androidapi.JNIBridge,
  Androidapi.JNI.GraphicsContentViewText,
  Androidapi.JNI.JavaTypes,
  Androidapi.JNI.Os;

type
// ===== Forward declarations =====

  JAccount = interface;//android.accounts.Account
  JBootCompletedReceiver = interface;//com.PanelControlReceiver.BootCompletedReceiver

// ===== Interface declarations =====

  JAccountClass = interface(JObjectClass)
    ['{94EE6861-F326-489F-8919-E20B39E3D9C1}']
    {class} function _GetCREATOR: JParcelable_Creator; cdecl;
    {class} function _Gettype: JString; cdecl;
    {class} function init(name: JString; type: JString): JAccount; cdecl; overload;//Deprecated
    {class} function init(in: JParcel): JAccount; cdecl; overload;//Deprecated
    {class} function hashCode: Integer; cdecl;
    {class} function toString: JString; cdecl;
    {class} procedure writeToParcel(dest: JParcel; flags: Integer); cdecl;
    {class} property CREATOR: JParcelable_Creator read _GetCREATOR;
    {class} property type: JString read _Gettype;
  end;

  [JavaSignature('android/accounts/Account')]
  JAccount = interface(JObject)
    ['{71476381-8B6E-471F-9189-9857ECD7508C}']
    function _Getname: JString; cdecl;
    function describeContents: Integer; cdecl;
    function equals(o: JObject): Boolean; cdecl;
    property name: JString read _Getname;
  end;
  TJAccount = class(TJavaGenericImport<JAccountClass, JAccount>) end;

  JBootCompletedReceiverClass = interface(JBroadcastReceiverClass)
    ['{8DF216DC-3DF7-4344-A5C9-927DCAFABA3F}']
    {class} function init: JBootCompletedReceiver; cdecl;//Deprecated
    {class} procedure onReceive(P1: JContext; P2: JIntent); cdecl;//Deprecated
  end;

  [JavaSignature('com/PanelControlReceiver/BootCompletedReceiver')]
  JBootCompletedReceiver = interface(JBroadcastReceiver)
    ['{07FF690C-FF5F-423D-B884-FB7EF3D91E78}']
  end;
  TJBootCompletedReceiver = class(TJavaGenericImport<JBootCompletedReceiverClass, JBootCompletedReceiver>) end;

implementation

procedure RegisterTypes;
begin
  TRegTypes.RegisterType('Androidapi.JNI.BootCompletedReceiver.JAccount', TypeInfo(Androidapi.JNI.BootCompletedReceiver.JAccount));
  TRegTypes.RegisterType('Androidapi.JNI.BootCompletedReceiver.JBootCompletedReceiver', TypeInfo(Androidapi.JNI.BootCompletedReceiver.JBootCompletedReceiver));
end;

initialization
  RegisterTypes;
end.

 

 

часть кода из класса вырезал, но суть оставил - это вызов запуска сервиса. и не совсем понятно - можно ли как то ловить только события будильника. как например ловится при автостарте

  if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {

 

 

 

 

package com.PanelControlReceiver;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;

import java.text.Format;
import java.text.SimpleDateFormat;
import java.util.Date;
 
import android.app.AlarmManager;
import android.app.PendingIntent;
import android.os.Bundle;
import android.os.PowerManager;
import android.widget.Toast;
import java.util.Calendar;
import java.util.*;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Calendar;

import java.io.File;

public class BootCompletedReceiver extends BroadcastReceiver {

 public void onReceive(Context context, Intent intent) {
     
Intent TestLauncher = new Intent();
//создаем класс     
     
     
     
TestLauncher.setClassName(context, "com.embarcadero.services.PanelControlService");
context.startService(TestLauncher);    
//Обычный запуск сервиса     
     
  }

}   

 

Изменено пользователем fsdb
Ссылка на комментарий

я просто закоментировал строчки на которые ругался компилятор. что то про аккаунт - не знаю откуда но я так понял они мне не нужны.

Вроде все работает, но скажите пожалуйста почему когда я добавляю строчку  у меня просто рушится выполнение в OnRecive?  я хотел обработать событие загрузки ОС...

if (intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)) {

Скажите пожалуйста как мне идентифицировать событие AlarmManager в OnReciver - как например что ОС только что загрузилась 

intent.getAction().equals(Intent.ACTION_BOOT_COMPLETED)

 

встает вопрос а сами классы можно как то разделить? что бы оба обрабатывали onRecive но один из них только для загрузку ОС обрабатывал что бы избжать проблему что я описал выше

 

После перезагрузки ОС, мой таймер установленный в AlarmManager перестал работать. т.е. обнулился.  это нормально? я думал один раз поставил и больше не забудет AlarmManager

 

В вашем проекте я нашел строчку написанную ниже, скажите где можно увидеть этот самый лог.

 Log.d("FMX", "AlarmReceiver.onReceive");

 

Я заметил что интерфейс (например ['{A27E897E-3AE0-4953-BA9C-FD2056EBAF2C}'] )  меняется каждый раз.. на сколько критично что бы там были цифры самые актуальные, т.е. последнесгенерированные.

Изменено пользователем fsdb
Ссылка на комментарий
В 26.03.2016 в 19:39, fsdb сказал:

В вашем проекте я нашел строчку написанную ниже, скажите где можно увидеть этот самый лог.


 Log.d("FMX", "AlarmReceiver.onReceive");

 

Нужно запустить Monitor.bat - он показывает все что происходит в устройстве. Путь такой (если у вас Delphi 10): C:\Users\Public\Documents\Embarcadero\Studio\17.0\PlatformSDKs\android-sdk-windows\tools\monitor.bat

Ссылка на комментарий
  • 3 недели спустя...

Ярослав, спасибо за статью, очень интересно!

Коллеги, помогите пожалуйста примером, как правильно ловить и обрабатывать событие, когда пользователь устройства в стандартном будильнике «откладывает звонок будильника на попозже». Т.е. человек занят, и не готов, что сейчас будет выполняться некая процедура, и нажимает кнопку «отложить на 10 минут». Возможно ли такое событие ловить не только в Android, но и в iOS?

Задайте пожалуйста наводящий вопрос, если я непонятно высказался.

 

Изменено пользователем Pax Beach
Ссылка на комментарий
  • 3 месяца спустя...
  • 7 месяцев спустя...

Привет.

Я тут узнал что оказывается начиная с XE7 не нужно создавать Dex файл затем подменять его на classes.dex.

Достаточно создать Jar файл и подключить его к проекту.  

А 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
Ссылка на комментарий
В 4/18/2016 в 10:14, Pax Beach сказал:

как правильно ловить и обрабатывать событие, когда пользователь устройства в стандартном будильнике «откладывает звонок будильника на попозже». Т.е. человек занят, и не готов, что сейчас будет выполняться некая процедура, и нажимает кнопку «отложить на 10 минут».

Т.е. звонит будильник и человек останавливает и откладывает его на 10 мин?

Нужно автозапускать свое Activity как расписано в этой статье и просто устанавливать новый интервал в AlarmManager. 

Кстати, начиная с XE7 вместо генерации Dex  и подмены classes.dex можно просто подключить Jar файл. Надеюсь Ярослав осветит это в своей статье (заодно там bat файл нужно обновить, он не работает на новых версиях java).

Изменено пользователем ENRGY
Ссылка на комментарий

Присоединяйтесь к обсуждению

Вы можете написать сейчас и зарегистрироваться позже. Если у вас есть аккаунт, авторизуйтесь, чтобы опубликовать от имени своего аккаунта.

Гость
Ответить в этой теме...

×   Вставлено с форматированием.   Вставить как обычный текст

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отображать как обычную ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.

  • Последние посетители   0 пользователей онлайн

    • Ни одного зарегистрированного пользователя не просматривает данную страницу
×
×
  • Создать...