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

[Статья]Как создать простой Android Broadcast Receiver. How to implement simplest Android Broadcast Receiver in Delphi


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

Опубликовано (изменено)

Как создать простейший Android Broadcast Receiver.

Создайте класс, для приема Intent уведомлений:

 

uses
  Androidapi.JNIBridge,
  Androidapi.JNI.Embarcadero,
  Androidapi.JNI.GraphicsContentViewText;

type
  TMyReceiver = class(TJavaLocal, JFMXBroadcastReceiverListener)
  public
    constructor Create;
    procedure onReceive(context: JContext; intent: JIntent); cdecl;
  end;

uses 
  Androidapi.Helpers,
  Androidapi.JNI.JavaTypes;

{ TMyReceiver }

constructor TMyReceiver.Create;
begin
  inherited;
end;

procedure TMyReceiver.onReceive(context: JContext; intent: JIntent);
begin
  Log.d('Broadcast Received = ' + JStringToString(intent.getAction));
end;

 

Регистрируем тип уведомлений и приемник в событиях формы:

 

type
  TForm1 = class(TForm)
    procedure FormCreate(Sender: TObject);
    procedure FormDestroy(Sender: TObject);
  private
    { private  }
    FMyListener: TMyReceiver;
    FBroadcastReceiver: JFMXBroadcastReceiver;
  public
    { public  }
  end;

procedure TForm1.FormCreate(Sender: TObject);
var
  Filter: JIntentFilter;
begin
  FMyListener := TMyReceiver.Create;
  FBroadcastReceiver := TJFMXBroadcastReceiver.JavaClass.init(FMyListener);

  Filter := TJIntentFilter.JavaClass.init;
  Filter.addAction(TJIntent.JavaClass.ACTION_SCREEN_OFF);
  Filter.addAction(TJIntent.JavaClass.ACTION_SCREEN_ON);
  TAndroidHelper.context.getApplicationContext.registerReceiver
    (FBroadcastReceiver, Filter);
end;

procedure TForm1.FormDestroy(Sender: TObject);
begin
  TAndroidHelper.context.getApplicationContext.unregisterReceiver
    (FBroadcastReceiver);
end;

Все.

Теперь когда вы запустите программу и выключите\включите экран, лог покажет :

FMX: BroadcastSample: Broadcast Received = android.intent.action.SCREEN_OFF
FMX: BroadcastSample: Broadcast Received = android.intent.action.SCREEN_ON

Takashi Yamamoto

Изменено пользователем ENRGY
Опубликовано (изменено)

Мой вариант Broadcast Receiver, на мой взгляд наиболее оптимизирован и удачен. По сравнению с известным кодом от barisatalay .

Отличия -

исправлена утечка,

чуть быстрее работает, за счет того что создается один фильтр в него добавляется несколько Actions  и одна регистрация на него, 

нет лишних конвертирований с Jstring to string и обратно,

адаптирован под Delphi 10 (JFMXBroadcastReceiver) ,

упрощена работа с классом (не нужно помнить о регистрации и вызывать ее заранее) ,

и самое главное - может получать getResultCode текущего ресивера (к примеру он нужен при получении статуса смс сообщения и в других случаях.). 

unit BroadcastReceiver;

interface

{$IFDEF ANDROID}
uses
  Androidapi.JNI.Embarcadero, Androidapi.JNI.GraphicsContentViewText, Androidapi.helpers,
  Androidapi.JNIBridge, FMX.Helpers.Android, Androidapi.JNI.JavaTypes,
  System.Classes, System.SysUtils;

type
  TBroadcastReceiver = class;

  TListener = class(TJavaLocal, JFMXBroadcastReceiverListener)
  private
    fOwner: TBroadcastReceiver;
    fReceiver: JFMXBroadcastReceiver;
  public
    constructor Create(aOwner: TBroadcastReceiver);
    destructor Destroy; override;
    procedure onReceive(context: JContext; intent: JIntent); cdecl;
  end;


  TOnReceive = procedure (aContext: JContext; aIntent: JIntent; aResultCode: integer) of object;

  TBroadcastReceiver = class
  private
    fListener : TListener;
    fRegistered: boolean;
    fOnReceive: TOnReceive;
  public
    constructor Create(aOnReceiveProc: TOnReceive);
    destructor Destroy; override;
    procedure AddActions(const Args: array of JString);
    procedure SendBroadcast(const aValue: string);
  end;
{$ENDIF}

implementation

{$IFDEF ANDROID}

{ TBroadcastReceiver }

constructor TBroadcastReceiver.Create(aOnReceiveProc: TOnReceive);
begin
  inherited Create;
  fListener := TListener.Create(Self);
  fOnReceive := aOnReceiveProc;
end;

destructor TBroadcastReceiver.Destroy;
begin
  fListener.Free;
  inherited;
end;

procedure TBroadcastReceiver.AddActions(const Args: array of JString);
var
  vFilter: JIntentFilter;
  i: Integer;
begin
  if fRegistered then
    TAndroidHelper.context.getApplicationContext.UnregisterReceiver(fListener.fReceiver);

  vFilter := TJIntentFilter.JavaClass.init;
  for i := 0 to High(Args) do
    vFilter.addAction(Args[i]);

  TAndroidHelper.context.getApplicationContext.registerReceiver(fListener.fReceiver, vFilter);
  fRegistered := true;
end;

procedure TBroadcastReceiver.SendBroadcast(const aValue: string);
var
  Inx: JIntent;
begin
  Inx := TJIntent.Create;
  Inx.setAction(StringToJString(aValue));
  TAndroidHelper.Context.sendBroadcast(Inx);
end;

constructor TListener.Create(aOwner: TBroadcastReceiver);
begin
  inherited Create;
  fOwner := aOwner;
  fReceiver := TJFMXBroadcastReceiver.JavaClass.init(Self);
end;

destructor TListener.Destroy;
begin
  TAndroidHelper.context.getApplicationContext.unregisterReceiver(fReceiver);
  inherited;
end;

// usually android call it from "UI thread" - it's not main Delphi thread
procedure TListener.onReceive(context: JContext; intent: JIntent);
begin
  if Assigned(fOwner.fOnReceive) then
    fOwner.fOnReceive(Context, Intent, fReceiver.getResultCode);
end;

{$ENDIF}

end.

 

Как использовать

 

  // указывать нужно сразу все нужные вам Actions в Add через запятую, не по одной. 
  fBroadcast := TBroadcastReceiver.Create(OnReceiveBroadcast);
  fBroadcast.AddActions([StringToJString(SENT_ACTION)]); << Custom action
-------------
  // или например сразу несколько Actions
  fBroadcast.AddActions([TJIntent.JavaClass.ACTION_SCREEN_OFF, TJIntent.JavaClass.ACTION_SCREEN_ON]);

 

Изменено пользователем ENRGY
  • 10 месяцев спустя...
Опубликовано

Можно пример, как использовать Ваш ресивер для перехвата входящих и исходящих звонков с получением номера телефона.

И ещё вопрос. В AndroidManifest.template.xml что-то надо прописывать в <%receivers%>?

 

Опубликовано
Только что, x11 сказал:

Можно пример, как использовать Ваш ресивер для перехвата входящих и исходящих звонков с получением номера телефона.

И ещё вопрос. В AndroidManifest.template.xml что-то надо прописывать в <%receivers%>?

 

Конкретно перехватом звонков я не занимался.

Вы можете поискать как это сделать на Java на StackOverflow напр, и адаптировать код на Delphi, это самый простой путь.

Опубликовано

Как правильно уничтожить BroadcastReceiver?

Есть код

procedure TDMSrv.BroadCastReiverFree;
begin
  if Assigned(BroadcastReceiver) then
  begin
    Log('BR is assigned');
    BroadcastReceiver.Destroy;
  end;

  if Assigned(BroadcastReceiver) then
  begin
    Log('BR is assigned');
  end;
end;

 

Так вот, в лог попадает строка "BR is assigned" два раза подряд, т.к. после строки:

BroadcastReceiver.Destroy 

объект BroadcastReceiver всё равно не равен nil и Assigned возвращает True.

Но если после ещё добавить строку:

BroadcastReceiver := nil;

то на этой строке появляется исключение.

 

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

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

Гость
К сожалению, ваш контент содержит запрещённые слова. Пожалуйста, отредактируйте контент, чтобы удалить выделенные ниже слова.
Ответить в этой теме...

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

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

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

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

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

×
×
  • Создать...