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」は有効のままにします。
フォーム側で受信するためのクラスを作成します。
受信したら、ログに出力します。
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;
次にサービス側を作成します。
サービスは、作成時に「ローカルサービス」を選択しています。
スレッドを保持するための変数「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