「Android の StartService のアプリを Delphi で作ってみた」を書いたので、もうひとつの BindService も書かないと
BindService は StartService と同様にアプリによって開始されます
BindService でサービスに接続して、UnBindService でサービスとの接続を解除します
StartService が自身で停止するのと違い、BindService の場合は、他から使われている限り実行し続け、誰からも使われなくなったら、サービスを破棄します
参考: Android Developer - Service
どんなアプリを作るの?
Android の StartService のアプリを Delphi で作ってみた で作ったアプリ・サービスを修正・拡張します
修正・拡張するので、メインのアプリにサービスを登録する作業を再度行なう必要はありません
修正・拡張の内容ですが
- メイン側のアプリは BindService のボタンを押すとサービスを開始し、BindService でそのサービスに接続します
- メイン側のアプリは UnBindService のボタンを押すと、サービスとの接続を解除します
- サービス側は、BindService の機能を追加しますが、やることは同じで通知を行ないます
- サービス側では解除=サービス停止とします
メイン側の画面の拡張
ボタンを1個、新しく配置するだけの簡単なお仕事
分かりやすいように、「BindService」「UnBindService」と Text プロパティを変更
メイン側の動作の拡張
「BindService」のボタンのクリックイベントを次のように修正します
procedure TForm1.Button1Click(Sender: TObject);
begin
// Service 起動
if mService = nil then begin
mService := TLocalServiceConnection.Create;
mService.StartService('Project2');
end;
// Service に Bind
mService.BindService('Project2', 0);
end;
「UnBindService」のボタンのクリックイベントを次のように記述します
procedure TForm1.Button2Click(Sender: TObject);
begin
if mService <> nil then begin
mService.UnbindService; // Service との接続解除
mService := nil;
end;
end;
サービス側の拡張
DM(TDM) に新たに OnBind イベントと、OnUnBind イベントを追加
OnStartCommand イベントのコードを次のように修正します
function TDM.AndroidServiceStartCommand(const Sender: TObject; const Intent: JIntent; Flags, StartId: Integer): Integer;
begin
// サービスの開始
// StartService は result を返す
Result := TJService.JavaClass.START_STICKY;
end;
OnBind イベントのコードを次のように記述します
function TDM.AndroidServiceBind(const Sender: TObject; const AnIntent: JIntent): JIBinder;
var
mNotice: TNotification;
begin
// BindService として通知の実行
mNotice := NotificationCenter1.CreateNotification;
mNotice.Title := 'BindService通知';
mNotice.AlertBody := 'メッシャアーッ';
NotificationCenter1.PresentNotification(mNotice);
mNotice.DisposeOf;
// IBinder オブジェクトを戻り値として返す
Result := GetBinder;
end;
OnUnBind イベントのコードを次のように記述します
function TDM.AndroidServiceUnBind(const Sender: TObject; const AnIntent: JIntent): Boolean;
begin
// このサンプルでは解除=停止
// サービスの停止
JavaService.stopService(AnIntent);
Result := False;
end;
動かしてみる
まずはアプリ起動(この画面を撮っていなかったのに後から気付いたため、この画面ショットだけ時系列がズレていますw)
BindService をタップするとサービスが起動し、そのサービスに接続して「通知」が行なわれます
UnBindService をタップするとサービスとの接続を解除して、サービスを停止します
BindService のボタンを続けて2回タップしても通知は1つだけです
これは、まだ Bind が解除されていないので OnBind イベントが発生しないのです
UnBindService のボタンをタップしてから、BindService のボタンをタップすると、OnBind イベントが発生し通知が行なわれます
参考
BindService のライフサイクル
Android Developer より
あとがき
Delphi で Android サービスを作る際に 4 つの選択
- ローカルサービス
- インテントローカルサービス
- リモートサービス
- インテントリモートサービス
が出てきます
「ローカル」と「リモート」の違いは、
ローカル - そのアプリだけで使用できる private のサービス
リモート - public であり、他のアプリからアクセスすることができる
です
「インテントxxxxサービス」は、サービスで IntentService を使用したい場合に選択します
IntentService はバッググラウンドで特定のタスクを実行し、ワーカスレッドでタスクキューを受け取り順に処理します
サービスの停止はキュー内の作業が全て終わったときに自動的に行なわれるので、明示的に停止する必要はありません