必须谨记的几点:
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.
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).
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).
4. ADIL是同步调用,而service的所有其它接口(bind, unbind, startService, stopService)都是异步接口,立即返回。
service有两种启动方式:Started和Bound。
Started方式:使用startService()启动。一旦启动,service will run indefinitely,unless stopSelf() or stopService() is called。
优点:使用简单,client端只需要简单的调用startService(),service端只需要在onStartCommand()进行处理。
缺点:
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()都是不起作用的。