Android サービスの作成
Android アプリケーションの作成 への移動
目次
Android サービスとは、ユーザー インターフェイスを持たない、バックグラウンド タスクを実行するアプリケーションです。このサービスには、本質的に以下の 2 種類があります。
- 起動型サービス: このサービスは Android アプリケーションによって起動されます。サービスは、アプリケーションが終了した後も、バックグラウンドで無期限に動作し続けることができます。この種類のサービスは、通常、1 つのタスクを実行し、それが終了すると自動的に停止します。
- バインド型サービス: このサービスは、Android アプリケーションにバインドされている間のみ動作します。アプリケーションとサービスの間で対話が行われ、アプリケーションがバインドを解除するまでアクティブなままになります。複数のアプリケーションを同じ 1 つのサービスにバインドすることができます。
Android サービス プロジェクトを作成するには:
- Android サービスの新規作成 ウィザードを使用すると、Android サービスを作成することができます。「Android サービスの作成」を参照してください。
- Use the 新規 Android サービスの追加 ウィザードを使用すると、Android サービスをマルチデバイス アプリケーションに追加することができます。「アプリケーションへの Android サービスの追加」を参照してください。
スタンドアロン アプリケーションと Android サービス プロジェクト アプリケーションには、異なる点があります。
- ターゲット プラットフォーム (Android) 下にはノードはない: ターゲット、構成、ライブラリ
- Android のみがターゲット プラットフォームとして利用可能
- 配置マネージャ は無効になってる
- オプション [実行]や[デバッガを使わずに実行]は無効になってる
Android サービスの作成
RAD Studio では、Android サービス プロジェクトを作成するための、ウィザードが用意されています。
Android サービス プロジェクトを新規作成するには、[ファイル|新規作成|その他...]を選択し、それから以下を選択します。
- [Delphi プロジェクト|Android サービス]
このウィザードで、サービスの種類(ローカルまたはリモート)を指定します。
- ローカル サービスは、そのアプリケーションだけで使用できる private のサービスです。Android マニフェスト ファイルに以下の行が追加され、他のアプリケーションからのアクセスが阻止されます。
<service android:exported="false" android:name="com.embarcadero.services.<service_name>"/>
- リモート サービスは public であり、他のアプリケーションからアクセスすることができます。Android マニフェスト ファイルに以下の行が追加され、サービスへのアクセスが認められます。
<service android:exported="true" android:name="com.embarcadero.services.<service_name>"/>
さまざまなオプションの詳細は、「Android サービス」を参照してください。
Android マニフェスト属性の詳細は、「Exported Provider Element(provider 要素のエクスポート)」を参照してください。
アプリケーションへの Android サービスの追加
Android サービスはスタンドアロン アプリケーションではありませんが、マルチデバイス アプリケーションと一緒に動作します。
一度作成されたサービスは、プロジェクト マネージャに、lib<project_name>.so という名前で表示されます。
Android サービス プロジェクトをマルチデバイス アプリケーションに追加するには:
- ビジュアル コンポーネントをデータ モジュールに、関数と手続きをコードに追加します。
- Android サービス プロジェクトを保存します。
- メモ 1: Android サービス プロジェクトは、それぞれ異なるフォルダに保存してください。
- メモ 2: Android サービス プロジェクトに Service という名前を付けてはなりません。
- Android サービス プロジェクトをビルドしてからアプリケーションに追加し、バイナリ ファイルを生成します。
- サービスを追加する先のアプリケーションを[プロジェクト マネージャ]に追加します。
- 既存のアプリケーションの場合には、プロジェクト グループを右クリックし、[既存プロジェクトを追加...]を選択します。
- マルチデバイス アプリケーションを新規作成する場合は、プロジェクト グループを右クリックし、[新規プロジェクトを追加...]を選択してから、以下を選択します。
- [Delphi プロジェクト|マルチデバイス アプリケーション]
- そのマルチデバイス アプリケーションで、ターゲット プラットフォームに[Android]を選択します。
- [Android]ターゲット プラットフォームを右クリックし、[Android サービスの追加...]を選択します。
- [新規 Android サービスの追加]ウィザードが開きます。 新しい Android サービスを追加する際、2 つのオプションがあります。次のいずれかを選択します。
- [プロジェクトの基底パスから自動的にファイルを検索する]
- [必要なファイルをすべて手動で選択する]
- [次へ]をクリックします。
- 何も問題なければ、マルチデバイス アプリケーションに追加されるファイルがリストに表示されます。
- Android サービスのパスの情報を要求するウィンドウが開いた場合には、Android サービスを保存しビルドしてからやり直してください。
- [完了]をクリックすると、以下のファイルがアプリケーションに追加されます。
- メインのバイナリ ファイル、lib<プロジェクト名>.so。 バイナリ ファイルは配置マネージャに追加されます。
- libProxyAndroidService.so ファイル。このライブラリは配置マネージャに追加されます。
- メモ: このファイルは、アプリケーションに追加されたすべてのサービスで共有されます。
- Java アーカイブ ファイル <プロジェクト名>.jar。この jar ファイルは、[プロジェクト マネージャ]の[Android]ターゲット プラットフォームの下にある[ライブラリ]ノードに追加されます。
- データ モジュール ファイル <プロジェクト名>.pas。このデータ モジュールは[プロジェクト マネージャ]に追加されます。
- マルチデバイス アプリケーションをコンパイルして、Android マニフェスト ファイルを生成します。先ほど選択したサービスのタイプ(ローカルまたはリモートで)に応じた行が自動的に追加されます。「Android サービスの作成」を参照してください。
- メモ: サービスごとに、対応する <service> の宣言を AndroidManifest.xml に追加する必要があります。これは IDE によって自動的に追加されます。
アプリケーションへの複数の Android サービスの追加
任意の数のサービスを Android アプリケーションに追加することができます。
追加するサービスそれぞれについて、「アプリケーションへの Android サービスの追加」の手順を実施してください。
以下はその際の注意事項です。
- Android Services プロジェクトが複数、同じフォルダ内にあり、そこから特定の 1 つを含みたい場合、ステップ 5.2 での 2 つ目のオプションを選択してください。そうでなければ、ウィザードは希望していない Android サービスを追加する可能性があります。
- プロジェクトそれぞれに異なる名前を付けてから、メイン アプリケーションに追加します。
- Android サービス プロジェクト:lib<サービス名>.so。
-
- メモ: Android サービス プロジェクトに Service という名前を付けてはなりません。
- ユニット ファイル。
- データ モジュール: [オブジェクト インスペクタ]の Name プロパティで名前を変更できます。
プロジェクトの依存関係
マルチデバイス アプリケーションに追加された Android サービス プロジェクトは、プロジェクト間の依存関係 として表示されます。
ホスト アプリケーションに関連づけられた Android サービス プロジェクトは、[プロジェクト間の依存関係] で自動的に有効になり、ホスト アプリケーションの前に常にビルドされます。
アプリケーションからの Android サービスの削除
そのマルチデバイス アプリケーションで、ターゲット プラットフォームに[Android]を選択します。
- [Android]ターゲット プラットフォームを右クリックし、[Android サービスの削除...]を選択します。
- Android サービスの削除 ウィザードが現れます。
- 一覧から削除するサービスを選択します。
- Next をクリックします。
- ウィザードでは、データ モジュール、.so 拡張子ファイル、.jar 拡張子ファイルの削除など、実行するアクションのリストが表示されます。
- Finish をクリックします。
サービスの起動
サービスは、ALocalServiceConnection.StartService('<サービス名>') と ALocalServiceConnection.BindService('<サービス名>')、または ARemoteServiceConnection.StartService('<サービス名>') と ARemoteServiceConnection.BindService('<サービス名>') を使って起動することができます。
起動時またはバインド時に、TLocalServiceConnection 変数を具体的なサービスに初期化します。その後、残りのメソッドでサービス名を参照する必要はありません。
Android サービスをマルチデバイス アプリケーションに追加したら、以下を行います。
- 以下のユニットをインターフェイスの uses 句 に追加します。
Uses System.Android.Service; // Unit that contains the methods to work with services.
- <サービス名>.pas ユニットを実装の uses 句に追加します。これで、サービス データ モジュールに定義されたすべてのメソッドを使用できるようになります。
implementation uses MyLocalService; //Key sensitive {$R *.fmx}
- ローカル サービスの場合は TLocalServiceConnetion 変数、リモート サービスの場合は TRemoteServiceConnection 変数を作成します。
- TLocalServiceConnection/TRemoteServiceConnection 変数を宣言します。
type TForm1 = class(TForm) ... private { Private declarations } FServiceConnection1: TLocalServiceConnection; // For a local service. FServiceConnection2: TRemoteServiceConnection; // For a remote service. public { Public declarations } end;
- TLocalServiceConnection/TRemoteServiceConnection 変数を作成します。
FServiceConnection1 := TLocalServiceConnection.Create; // For a local service. FServiceConnection2 := TRemoteServiceConnection.Create; // For a remote service.
- TLocalServiceConnection/TRemoteServiceConnection 変数を宣言します。
起動型サービス
起動型サービスの場合は、StartService('<サービス名>')
を呼び出してサービスを起動します。
サービスを起動型として使用する場合、自分でサービス プロセスを管理し、JavaService.stopSelf;
を使ってサービスを停止する必要があります。
スティッキーでの起動
サービスの OnStartCommand イベントは、デフォルトでは START_NOT_STICKY と定義されています。
- START_STICKY は、明示的に起動され、必要に応じて停止されるサービスに使用します。システムは、サービスが強制終了されると、サービスの再起動を試みます。
- START_NOT_STICKY は、送られてきたコマンドを処理する間だけ実行しておきたいサービスに使用します。プロセスが強制終了されても、サービスは自動的に再起動されません。
OnStartCommand イベントを START_STICKY にしたい場合は、それをサービスに指定する必要があります。
function TService1DM.AndroidServiceStartCommand(const Sender: TObject;
const Intent: JIntent; Flags, StartId: Integer): Integer;
begin
Result := TJService.JavaClass.START_STICKY;
end;
詳細は、「Service Lifecycle(サービスのライフサイクル)」を参照してください。
バインド型サービス
バインド型サービスの場合は、BindService('<サービス名>')
を呼び出してサービスをバインドし、対話を始められるようにしたり、UnBindService
を呼び出してサービスとの接続を解除します。
詳細は、「Bound Services(バインド型サービス)」を参照してください。
BindService/UnBindService メソッド
メイン アプリケーションで BindService('<サービス名>')
を呼び出すと、サービスが動作しているメモリ アドレスを指すポインタが接続変数に設定されます。
特定のサービスに対する接続を確立した後で、UnBindService
を呼び出したときに、そのサービスにバインドしているのがそのアプリケーションだけであれば、サービスは自身を解放します。 メイン アプリケーションの接続変数は、同じメモリ アドレスを指したままになることに注意してください。 同じサービスに再びバインドするとメイン アプリケーションがクラッシュする可能性があります。サービスのメモリ アドレスが不正である可能性があるためです。
この状況に対処する方法は 2 つあります。
- ARC(自動参照カウント)を、[UnSafe] 属性 を使用して使わないようにする。
- サービスとのバインドを解除する前に変数に
Nil
を代入する
[Unsafe] 属性の利用
private
{ Private declarations }
[Unsafe] Service1: TAndroidService1DM;
詳細は、「Unsafe 属性」を参照してください。
OnBind イベント
アプリケーションの BindService('<サービス名>')
を呼び出すと、Android サービス プロジェクトで OnBind イベントが発生します。OnBind メソッドは、サービスとの接続を実際に管理する責任を負う IBinder オブジェクトを返します。
OnBind メソッドを上書きすると、メイン アプリケーションがサービスからデータ モジュールを取り出すために必要な IBinder オブジェクトが、イベントから返されなくなります。
OnBind メソッドを使用するには:
- OnBind メソッドで IBinder オブジェクトを返します。
function TAndroidServiceDM.AndroidServiceBind(const Sender: TObject;
const AnIntent: JIntent): JIBinder;
begin
// .... User's code
Result := GetBinder(Self);
end;