Delphi 10 SeattleのAndroidアプリで、LocalBroadcastManagerを使ってローカルサービスからフォームに通信する

Delphi 10 SeattleのAndroidアプリで、LocalBroadcastManagerを使ってServiceからフォームに通信する方法です。

LocalBroadcastManagerクラスは、android-support-v4.jarにあります。
Java2OPを使ってLocalBroadcastManagerクラスのブリッジファイルを生成します。

Java2OP.exe -jar android-support-v4.jar -classes android.support.v4.content.LocalBroadcastManager -unit Androidapi.JNI.LocalBroadcastManager

作成したAndroidapi.JNI.LocalBroadcastManager.pasは、プロジェクトに追加して、LocalBroadcastManagerクラスを使用するユニットのusesに追加します。

ライブラリの「android-support-v4.dex.jar」は有効のままにします。

LocalBroadcastManager02

フォーム側で受信するためのクラスを作成します。
受信したら、ログに出力します。

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

{ TMyReceiver }

constructor TMyReceiverListener.Create;
begin
  inherited Create;
end;

procedure TMyReceiverListener.onReceive(context: JContext; intent: JIntent);
begin
  Log.d('TMyReceiverListener.onReceive:' + JStringToString(intent.getAction));
end;

フォームに次の変数を追加します。

  TForm1 = class(TForm)
  …
  private
    { private 宣言 }
    FMyListener: TMyReceiverListener;
    FBroadcastReceiver: JFMXBroadcastReceiver;
    FIntentFilter: JIntentFilter;
    FLocalBroadcastManager: JLocalBroadcastManager;
  public
    { public 宣言 }
  end;

フォームのOnCreateイベントで、受信するための設定を行います。

procedure TForm1.FormCreate(Sender: TObject);
begin
  FLocalBroadcastManager := TJLocalBroadcastManager.JavaClass.getInstance
    (TAndroidHelper.Activity.getApplicationContext);
  FMyListener := TMyReceiverListener.Create;
  FBroadcastReceiver := TJFMXBroadcastReceiver.JavaClass.init(FMyListener);
  FIntentFilter := TJIntentFilter.Create;
  FIntentFilter.addAction(StringToJString('ACTION_NAME'));
  FLocalBroadcastManager.registerReceiver(FBroadcastReceiver, FIntentFilter);
end;

OnDestroyイベントで、設定を解除します。

procedure TForm1.FormDestroy(Sender: TObject);
begin
  FLocalBroadcastManager.unregisterReceiver(FBroadcastReceiver);
  FBroadcastReceiver := nil;
  FMyListener.Free;
  FMyListener := nil;
  FIntentFilter := nil;
end;

フォームにボタンを配置します。
ボタンを押したら、サービスを起動します。

const
  SERVICE_NAME = …;

procedure TForm1.Button1Click(Sender: TObject);
begin
  TLocalServiceConnection.StartService(SERVICE_NAME);
end;

次にサービス側を作成します。

サービスは、作成時に「ローカルサービス」を選択しています。

LocalBroadcastManager01

スレッドを保持するための変数「FThreads」を追加します。

type
  TAndroidServiceDM = class(TAndroidService)
    …
  private
    { Private declarations }
    FThreads: TObjectList<TThread>;
  public
    { Public declarations }
  end;

OnCreateイベントで「FThreads」を生成します。

procedure TAndroidServiceDM.AndroidServiceCreate(Sender: TObject);
begin
  if JavaService <> nil then
  begin
    FThreads := TObjectList<TThread>.Create;
  end;
end;

OnDestroyイベントで「FThreads」を破棄します。

procedure TAndroidServiceDM.AndroidServiceDestroy(Sender: TObject);
begin
  FThreads.Free;
end;

OnStartCommandイベントが発生したら、2秒待機してから、フォームに通知します。

function TAndroidServiceDM.AndroidServiceStartCommand(const Sender: TObject;
  const Intent: JIntent; Flags, StartId: Integer): Integer;
var
  LThread: TThread;
begin
  LThread := TThread.CreateAnonymousThread(
    procedure
    begin
      Sleep(2000);
      TJLocalBroadcastManager.JavaClass.getInstance(JavaService)
        .sendBroadcast(TJIntent.JavaClass.init(StringToJString('ACTION_NAME')));
      JavaService.stopSelf(StartId);
    end);
  LThread.FreeOnTerminate := False;
  FThreads.Add(LThread);
  LThread.Start;

  Result := TJService.JavaClass.START_STICKY;
end;

以上で完成です。

アプリケーションを実行して、フォームのボタンを押します。
2秒後にログに次のように出力されます。

FMX: SampleService02App: TMyReceiverListener.onReceive:ACTION_NAME

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

このサイトはスパムを低減するために Akismet を使っています。コメントデータの処理方法の詳細はこちらをご覧ください