Android Hacks - 合宿 Service

4,885 views
4,678 views

Published on

「Android Hacks ―プロが教えるテクニック & ツール」(株式会社ブリリアントサービス 著)を教材とした勉強会でのまとめ資料です。

http://www.oreilly.co.jp/books/9784873114569/

Published in: Technology
0 Comments
2 Likes
Statistics
Notes
  • Be the first to comment

No Downloads
Views
Total views
4,885
On SlideShare
0
From Embeds
0
Number of Embeds
58
Actions
Shares
0
Downloads
16
Comments
0
Likes
2
Embeds 0
No embeds

No notes for slide

Android Hacks - 合宿 Service

  1. 1. ANDROID HACKS #26 サービスを使う 担当:太田 Twitter : @ahyask Blog : http://mou.yatte.nai 09/19/11
  2. 2. この資料について <ul><li>この資料は下記の本をベースに勉強会で作成した資料です。 </li></ul><ul><ul><li>『 Android Hacks 』(株式会社ブリリアントサービス著、オライリー・ジャパン刊) </li></ul></ul><ul><li>この本の紹介ページが下記にあります。 </li></ul><ul><ul><li>http://www.oreilly.co.jp/books/9784873114569/ </li></ul></ul>09/19/11
  3. 3. 今回も敵が多かった
  4. 4. 09/19/11
  5. 5. 09/19/11
  6. 6. アジェンダ <ul><li>Service とは </li></ul><ul><li>Service を動かす </li></ul><ul><li>Bind 後の Service 利用 </li></ul><ul><li>AIDL(Android Interface Definition Language) </li></ul><ul><li>その他補足 </li></ul>
  7. 7. 1. Service とは
  8. 8. 1. Service とは <ul><li>バックグラウンドでアプリを動かす機能 </li></ul><ul><ul><li>常駐アプリを作る </li></ul></ul><ul><ul><li>複数フロントエンドを持つ何か </li></ul></ul><ul><li>Toast クラスもサービスを利用している </li></ul><ul><ul><li>呼び出し元 Activity が表示されていなくても表示される理由 </li></ul></ul><ul><li>Service はシングルトン </li></ul><ul><ul><li>Start は何度も呼べるが, Stop は一度きり </li></ul></ul><ul><ul><li>同じものが使いまわされているだけ </li></ul></ul>
  9. 9. 2.Service のライフサイクル <ul><li>開始 </li></ul><ul><ul><li>onCreate() </li></ul></ul><ul><ul><ul><li>一度のみ </li></ul></ul></ul><ul><ul><ul><li>同じサービスを複数起動しても呼ばれない </li></ul></ul></ul><ul><ul><li>onStart() </li></ul></ul><ul><ul><ul><li>同じサービスを複数起動した都度に呼ばれる </li></ul></ul></ul><ul><li>処理実行部 </li></ul><ul><ul><li>Service running な状態 </li></ul></ul><ul><li>終了 </li></ul><ul><ul><li>onDestroy() </li></ul></ul>
  10. 10. 3. サービスとクライアントの関係 サービス様 クライアント クライアント クライアント Intent ブロードキャスト これやっといて Sir , Yes Sir!! Sir , Yes Sir!! Sir , Yes Sir!! サービスからクライアントへは Intent を発行できる
  11. 11. 3. サービスとクライアントの関係 サービス様 クライアント クライアント クライアント クライアントは Bind 後にアクションをお願いできる Bind お願いしたいことがあるのですが… 言ってみたまえ
  12. 12. 4.Bind のライフサイクル <ul><li>Bind 時 </li></ul><ul><ul><li>onBind() </li></ul></ul><ul><li>処理部 </li></ul><ul><li>Bind 開放時 </li></ul><ul><ul><li>onUnbind() </li></ul></ul>
  13. 13. 2. Service を動かす
  14. 14. 1. Activity からサービスを    start する <ul><li>Intent は作っておきましょう </li></ul><ul><ul><li>Intent i = new Intent(this,UpdateService.class); </li></ul></ul><ul><li>サービスを開始 </li></ul><ul><ul><li>Context.startService(i); </li></ul></ul><ul><ul><ul><li>本当は一度でも start していればいらないはず </li></ul></ul></ul><ul><ul><ul><li>Android による kill 対策としてはとりあえず呼んでおく </li></ul></ul></ul><ul><ul><ul><li>この時サービス側では onCreate() (初回のみ) , onStart() (毎回)が呼ばれる </li></ul></ul></ul><ul><li>サービスを終了 </li></ul><ul><ul><li>Context.stopService(i); </li></ul></ul><ul><ul><li>Service.stopSelf(); </li></ul></ul><ul><ul><ul><li>Service が自分を停止することも可能 </li></ul></ul></ul><ul><ul><li>終了時にサービス側では onDestroy() が呼ばれる </li></ul></ul>
  15. 15. 2. Activity からサービスを    bind する <ul><li>サービスを bind </li></ul><ul><ul><li>Context.bindService(i, connection, Context.BIND_AUTO_CREATE); </li></ul></ul><ul><ul><ul><li>connection についてはあとで触れる </li></ul></ul></ul><ul><ul><ul><li>BIND オプションについてもあとで触れる </li></ul></ul></ul><ul><ul><li>サービス側では onBind() が呼ばれる </li></ul></ul><ul><li>サービスを unbind </li></ul><ul><ul><li>unbindService(connection); </li></ul></ul><ul><ul><li>サービス側では onUnbind() が呼ばれる </li></ul></ul><ul><ul><li>サービスは残り続ける </li></ul></ul><ul><ul><ul><li>いつでも bindService() で bind しなおせる </li></ul></ul></ul><ul><ul><ul><li>他のプロセスから bind することもできる </li></ul></ul></ul><ul><ul><ul><li>全ての bind が unbind されていないと Service は停止できない </li></ul></ul></ul>
  16. 16. 3. Bind 時のオプション <ul><li>Context.BIND_AUTO_CREATE </li></ul><ul><ul><li>基本的にこのオプションが用いられる </li></ul></ul><ul><ul><li>サービスが立ち上がっていない場合に立ち上げてくれる </li></ul></ul><ul><ul><li>サービス側の挙動 </li></ul></ul><ul><ul><ul><li>onCreate(),onBind() の順に呼ばれる </li></ul></ul></ul><ul><ul><ul><li>onStart() は呼ばれない </li></ul></ul></ul><ul><li>他のオプション </li></ul><ul><ul><li>まあ使ってるのを見ない </li></ul></ul><ul><ul><li>BIND_DEBUG_UNBIND </li></ul></ul><ul><ul><ul><li>debug オンリー. debug 出力を垂れ流すので本番ではやらない </li></ul></ul></ul><ul><ul><ul><li>unbind しわすれによるリークを発見しやすくする </li></ul></ul></ul><ul><ul><li>BIND_NOT_FOREGROUND </li></ul></ul><ul><ul><ul><li>メモリ管理的には Android の機構に準拠する </li></ul></ul></ul><ul><ul><ul><li>CPU 利用優先度を Foreground 相当まで昇格することを制限する </li></ul></ul></ul>
  17. 17. 3. Bind 後の Service 利用
  18. 18. 1. ServiceConnection <ul><li>文字通りのコネクションとして考えればよい </li></ul><ul><ul><li>接続してる相手にコマンド発行するくらいのノリで </li></ul></ul><ul><li>以下のコールバックを持つ </li></ul><ul><ul><li>onServiceConnected() </li></ul></ul><ul><ul><ul><li>コネクション成立時 </li></ul></ul></ul><ul><ul><ul><li>IBinder オブジェクトを受け取る </li></ul></ul></ul><ul><ul><ul><ul><li>サービス側にコールバックするためのインタフェース </li></ul></ul></ul></ul><ul><ul><li>onServiceDisconnected() </li></ul></ul><ul><ul><ul><li>コネクション切断時 </li></ul></ul></ul><ul><li>注意 </li></ul><ul><ul><li>onServiceConnected() はコネクション確立まで呼ばれない </li></ul></ul><ul><ul><ul><li>bindService() から Service が使えるまでに時間的ラグがある </li></ul></ul></ul><ul><ul><ul><li>すぐに onServiceConnected() 呼ばれるならコールバックに しないでしょう常識的に考えて </li></ul></ul></ul>
  19. 19. 2. Ibinder の定義 <ul><li>bind 時に Service から取得する何か </li></ul><ul><ul><li>ServiceConnection.onServiceConnection() コールバック経由 </li></ul></ul><ul><ul><li>Service との通信は IBinder を介して行う </li></ul></ul><ul><li>実際は Service.onBind() の戻り値 </li></ul><ul><ul><li>どのようなアクセス法を提供するかは onBind() の実装で決定できる </li></ul></ul>
  20. 20. 3. やってみる <ul><li>Service 側の定義 </li></ul><ul><ul><li>public class MyService extends Service { (略) @Override public IBinder onBind(Intent intent)    { return new LocalBinder(); } class LocalBinder extends Binder {    MyService getService() { return MyService.this; } } public void somemethod() { // 呼び出される Service 側のメソッド } } </li></ul></ul>
  21. 21. 3. やってみる <ul><li>呼び出し側の定義 </li></ul><ul><ul><li>public class MyActivity extends Activity { (略) MyService myservice; private void startServiceMethod(){ // どっかから呼んでもらう    Intent i = new Intent( this, MyService.class);    bindService(i, conn, Context.BIND_AUTO_CREATE); } private void someServiceCall(){ // どっかから呼んでもらう    myservice.somemethod(); } private MyConnection conn = new ServiceConnection() {    @Override    public void onServiceConnected(ComponentName name, IBinder binder) {      myservice = ((MyService.LocalBinder)binder).getService();    }    @Override    public void onServiceDisconnected(ComponentName name) {      myservice = null;    } } } </li></ul></ul>
  22. 22. 4. AIDL Android Interface Definition Language
  23. 23. 1. サービスの種類 <ul><li>Local Service </li></ul><ul><ul><li>同一プロセス内の Service </li></ul></ul><ul><ul><ul><li>そのプロセス内で start したもの </li></ul></ul></ul><ul><ul><li>直接 Service の参照を取得できる </li></ul></ul><ul><ul><ul><li>今までの手法 </li></ul></ul></ul><ul><ul><ul><li>AIDL いらない </li></ul></ul></ul><ul><li>Remote Service </li></ul><ul><ul><li>他プロセスになっている Service </li></ul></ul><ul><ul><ul><li>他のアプリケーション , パッケージで start したもの </li></ul></ul></ul><ul><ul><li>直接 Service の参照を取得できない </li></ul></ul><ul><ul><ul><li>AIDL 必要 </li></ul></ul></ul>
  24. 24. 2. AIDL とは <ul><li>Android Interface Definition Language </li></ul><ul><ul><li>RPC やデータのやり取りをお手軽にやるためのもの </li></ul></ul><ul><li>作り方 </li></ul><ul><ul><li>[File]>[New]>[File] IMyService.aidl </li></ul></ul><ul><ul><ul><li>aidl ファイルとしたけど,内容はインタフェース宣言 </li></ul></ul></ul><ul><ul><ul><li>interface IMyService { 使いたいコールバックの宣言 } </li></ul></ul></ul><ul><ul><li>ビルドすると勝手に AIDL コンパイラが以下を作る </li></ul></ul><ul><ul><ul><li>IMyService.java </li></ul></ul></ul><ul><ul><ul><ul><li>public interface IMyService extends IInterface </li></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>Android 組み込みの Interface </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><ul><li>Stub extends Binder を内部に持つ </li></ul></ul></ul></ul></ul><ul><ul><ul><ul><li>Servlet 的な手続きを実現するために必要なもの </li></ul></ul></ul></ul>
  25. 25. 3. AIDL が作ってくれたものを使う <ul><li>Binder は Service.onBind() が返さなければならない </li></ul><ul><ul><li>public IBinder onBind(Intent intent){ return IMyServiceBinder; } </li></ul></ul><ul><li>Service 中に以下も定義しておく </li></ul><ul><ul><li>private IMyService.Stub IMyServiceBinder; </li></ul></ul><ul><ul><li>IMyServiceBinder = new IMyService.Stub() { // IMyService で宣言した各コールバック } </li></ul></ul><ul><li>呼び出し側 </li></ul><ul><ul><li>どこかで IMyService mybinder; を定義しておく </li></ul></ul><ul><ul><li>ServiceConnection </li></ul></ul><ul><ul><ul><li>public void onServiceConnected(ComponentName name, IBinder binder) {      mybinder = IMyService.Stub.asInterface(binder); } </li></ul></ul></ul><ul><ul><li>利用時 </li></ul></ul><ul><ul><ul><li>mybinder. 宣言したコールバック </li></ul></ul></ul>
  26. 26. 5. その他補足
  27. 27. 1. receiver と filter <ul><li>Service は Intent をブロードキャストできるので, Activity 側で Intent を受け取るようにしておく </li></ul><ul><li>BroadcastReceiver </li></ul><ul><ul><li>受け取った Intent の処理を定義 </li></ul></ul><ul><li>IntentFilter </li></ul><ul><ul><li>Receive する Intent を宣言 </li></ul></ul><ul><ul><ul><li>IntentFilter.addAction() で Intent 追加可能 </li></ul></ul></ul><ul><li>Context.registerReceiver(BroadcastReceiver,IntentFilter) </li></ul><ul><ul><li>登録 </li></ul></ul><ul><li>Context.unregisterReceiver(BroadcastReceiver) </li></ul><ul><ul><li>解除 </li></ul></ul>
  28. 28. 2. Service の優先度,    Kill 可能性 <ul><li>Android のプロセス優先度管理 </li></ul><ul><ul><li>Foreground > Visible > Service > Background > Empty </li></ul></ul><ul><ul><li>Service は不可視プロセス中では優先度が高い </li></ul></ul><ul><li>例外事項 </li></ul><ul><ul><li>onCreate() , onStart() , onDestroy() 中は Foreground 扱い </li></ul></ul><ul><ul><li>bind されている場合, bind しているクライアントのうち最も優先度の高いものと同じ優先度 </li></ul></ul><ul><ul><li>強制的にフォアグラウンド状態に置くことも可能 </li></ul></ul><ul><ul><ul><li>Service.startForeground() </li></ul></ul></ul><ul><li>以上から Service は Kill され難いプロセスになっている </li></ul>
  29. 29. 3. startService    bindService <ul><li>どちらも Service を起動できるが,少し挙動が違う </li></ul><ul><li>Context.bindService() で起動する場合 </li></ul><ul><ul><li>Context.bindService() </li></ul></ul><ul><ul><ul><li>Service.onCreate() </li></ul></ul></ul><ul><ul><ul><li>Service.onBind() </li></ul></ul></ul><ul><ul><li>Context.unbindService() </li></ul></ul><ul><ul><ul><li>Service.onUnbind() </li></ul></ul></ul><ul><ul><ul><li>Service.onDestroy() </li></ul></ul></ul><ul><li>Context.startService() で起動済みの場合 </li></ul><ul><ul><li>Context.bindService() </li></ul></ul><ul><ul><ul><li>Service.onBind() </li></ul></ul></ul><ul><ul><li>Context.unbindService() </li></ul></ul><ul><ul><ul><li>Service.onUnbind() </li></ul></ul></ul>
  30. 30. 参考 URL <ul><li>Android Developers </li></ul><ul><ul><li>http://developer.android.com/intl/ja/index.html </li></ul></ul><ul><ul><li>http://developer.android.com/reference/android/content/Context.html#BIND_DEBUG_UNBIND </li></ul></ul><ul><li>@IT - 常駐アプリが作成できる Android の“サービス”とは </li></ul><ul><ul><li>http://www.atmarkit.co.jp/fsmart/articles/android07/android07_1.html </li></ul></ul><ul><li>Shifft - Android のプロセス管理を知る </li></ul><ul><ul><li>http://www.shifft.in/blog/featured/android-process/ </li></ul></ul>09/19/11

×