必須謹記的幾點:java
1. service的全部onXXXX( )都是運行在main thread,包括onStartCommand()。Because all service's onXXXX() functions are called via handleMessage() of handler which is created with the main thread's loop.android
client的onServiceConnected()和onServiceDisonnected()也都是運行在main thread,because they are also called via handler which is created with the main thread's loop,安全
2. All IPC are executed via binder and executed in the binder thread. Android app framework will create binder thread during startup which is created using native code(such thread may be spawned if necessary,系統會維護一個binder thread的線程池,以保證全部的IPC均可以被handle). app
3. onStartCommand()不須要考慮線程安全,由於onStartCommand() is executed in the main thread in turn。But if we use bound service, 須要考慮線程安全,由於all IPC are executed in the binder thread(binder thread maybe multiple).less
4. ADIL是同步調用,而service的全部其它接口(bind, unbind, startService, stopService)都是異步接口,當即返回。異步
service有兩種啓動方式:Started和Bound。ide
Started方式:使用startService()啓動。一旦啓動,service will run indefinitely,unless stopSelf() or stopService() is called。oop
優勢:使用簡單,client端只須要簡單的調用startService(),service端只須要在onStartCommand()進行處理。spa
缺點:線程
1. 必須調用stopSelf() or stopService()關閉service;
2. client端沒法獲取返回值(雖然能夠經過向service傳遞PendingIntent for Broadcast實現);
3. 單向調用,只能由client端向service端發送intent。
Bound方式:使用bindService()啓動。一旦啓動,service will run indefinitely。 Multiple components can bind to the same service, but only when all of them unbind, the service is destroyed.
優勢:
1. 能夠經過AIDL或Messager實現IPC(實際都是經過Binder實現的);
2. 能夠實現雙向IPC,client能夠經過onServiceConnected()取得service的Binder,以後也能夠經過Binder將本身的Binde發送r給service,從而實現雙向IPC。
混合方式:service can work both ways,it can be started and also allow binding.
onStartCommand()的返回值
Notice that onStartCommand() must return an integer, which describes how the system should re-start the service after it is killed:
START_STICKY:
service will be re-created(onCreate() is called), and system will guarantee onStartCommand() is called, but do not re-deliver the last intent. Instead, the system calls onStartCommand() with a null intent(?我的試驗未成功?), unless there were pending intents to start the service.
START_STICKY_COMPATIBILITY
compatibility version of START_STICKY that does not guarantee that onStartCommand() will be called.
START_NOT_STICKY:
service will NOT be re-created unless there are pending intents to the service.
START_REDELIVER_INTENT
service will be re-created, and system will call onStartCommand() with the last intent that was delivered to the service. Any pending intents are delivered in turn.
不得不說的幾點:
1. service能夠聲明爲私有。you can declare the service as private in the manifest file by setting the android:exported to "false", and block access from other applications. Only components of the same application or applications with the same user ID can start the service or bind to it. You can also use the permission attribute to limit the external components that can interact with the service).
2. service能夠運行在其它進程。Normally, all components of an application run in the default process created for the application. It has the same name as the application‘s package name. The <application> element's android:process attribute can set a different default name for all components. But component can override the default with its own process attribute, allowing you to spread your application across multiple processes.
If the name assigned begins with a colon (':'), a new process, private to the application, is created to run the service.(?我的試驗未成功?)
If the name begins with a lowercase, the service will run in a global process of that name.
可是須要注意的是,一旦建立新的進程,無論是unbind仍是stopService,即便service已經被destroy,系統也不會kill該進程!
2. AIDL(Android Interface Definition Language )文件中定義的接口會被編譯生成對應的java文件,能夠看到其中關鍵的
service啓動流程
======== case 1. bind a service ============
TestAidl-Client: ------ =====> bindService()------
TestAidl-Client: ------ <===== bindService()------
TestAidl-Service: ------ service onCreate()------
TestAidl-Service: ------ service onBind()------ :onBind() is only called once, even we call bindService() multiple times, onBind() wont't be invoked.
TestAidl-Client: ------ onServiceConnected()------
======== case 2. unbind a service ============
TestAidl-Client: ------ =====> unbindService()------:if unbindService() is called with an un-bound service, exception will occur : java.lang.IllegalArgumentException: Service not registered
TestAidl-Client: ------ <===== unbindService()------:NOTE: onServiceDisconnected() won't be called due to unbindService(), 只有當servie異常退出時,系統纔會調用onServiceDisconnected()
TestAidl-Service: ------ service onUnbind()------:onUnbind() is only called once when the last bound component unbind from the service, usually the service onDestroy() will be called afterwards..
【TestAidl-Service: ------ service onDestroy()------】
======== case 3. start a service ============
TestAidl-Client: ------ =====> startService()------
TestAidl-Client: ------ <===== startService()------
TestAidl-Service: ------ service onCreate()------
TestAidl-Client: ------ service onStartCommand()------:You should never call onStartCommand() directly.
======== case 4. stop a service ============
TestAidl-Client: ------ =====> stopService()------:stopService() can be called multiple times, nothing happened.
TestAidl-Client: ------ <===== stopService()------
【TestAidl-Service: ------ service onDestroy()------】
因此,在Service,只有onStart( )可被屢次調用(經過屢次startService調用),其餘onCreate( ),onBind( ),onUnbind( ),onDestory( )在一個生命週期中只能被調用一次。
service的生命週期
1. A Started service will be destroyed once stopService() is called, no matter which component calls.
2. A bound service will be destroyed only when the last bound component calls the unbindService().
3. if a service is both started and bound, it will be destroyed when stopService() is called and no one is bound to the service at that time,除此以外,無論是調用unbindService()或者stopService()都是不起做用的。