Service和Activity间的通信
Activity传递数据到Service 使用Intent Service传递数据到Activity 使用Binder 使用EventBus
使用Binder通信
private fun initView ( ) {
MyService. start ( this )
MyService. bind ( this ) {
Log. d ( TAG, "initView: $it " )
}
}
class MyService : Service ( ) {
companion object {
private const val TAG = "MyService"
var starter: Intent? = null
fun start ( context: Context) {
if ( starter == null ) {
starter = Intent ( context, MyService:: class . java)
}
context. startService ( starter)
}
fun stop ( context: Context) {
starter? . let {
context. stopService ( starter)
}
}
var listener: ( num: Int) -> Unit = { }
var connection = object : ServiceConnection {
override fun onServiceConnected ( name: ComponentName? , service: IBinder? ) {
Log. e ( TAG, "onServiceConnected: " )
val simpleBinder = service as SimpleBinder
simpleBinder. onListener = listener
}
override fun onServiceDisconnected ( name: ComponentName? ) {
Log. e ( TAG, "onServiceDisconnected: " )
}
}
fun bind ( context: Context, listener: ( num: Int) -> Unit = { } ) {
this . listener = listener
if ( starter == null ) {
starter = Intent ( context, MyService:: class . java)
}
context. bindService ( starter, connection, BIND_AUTO_CREATE)
}
fun unbind ( context: Context) {
context. unbindService ( connection)
}
}
private val simpleBinder: SimpleBinder by lazy { SimpleBinder ( ) }
override fun onBind ( intent: Intent? ) : IBinder {
return simpleBinder
}
var job: Job? = null
override fun onCreate ( ) {
super . onCreate ( )
job = GlobalScope. launch {
repeat ( 20 ) {
Log. d ( TAG, "onCreate: $it " )
simpleBinder. onListener. invoke ( it)
delay ( 1000 )
}
}
}
override fun onStartCommand ( intent: Intent? , flags: Int, startId: Int) : Int {
Log. e ( TAG, "onStartCommand: " )
return super . onStartCommand ( intent, flags, startId)
}
override fun onDestroy ( ) {
super . onDestroy ( )
job? . cancel ( )
Log. e ( TAG, "onDestroy: " )
}
}
class SimpleBinder : Binder ( ) {
var onListener: ( num: Int) -> Unit = { }
}
D/MainActivity: initView: 0
D/MainActivity: initView: 1
D/MainActivity: initView: 2
...
另一个简洁版的
class RemoteActivity : AppCompatActivity ( ) {
override fun onCreate ( savedInstanceState: Bundle? ) {
super . onCreate ( savedInstanceState)
setContentView ( R. layout. activity_remote)
}
fun onClick ( view: View) {
RemoteService. bind ( this ) {
Log. d ( TAG, "onClick: $it " )
}
}
}
class RemoteService : Service ( ) {
companion object {
fun bind ( context: Context, listener: ( num: Int) -> Unit) {
context. bindService ( Intent ( context, RemoteService:: class . java) , object : ServiceConnection {
override fun onServiceConnected ( name: ComponentName? , service: IBinder? ) {
val simpleBinder = service as SimpleBinder
simpleBinder. onListener = listener
}
override fun onServiceDisconnected ( name: ComponentName? ) {
TODO ( "Not yet implemented" )
}
} , BIND_AUTO_CREATE)
}
}
private val simpleBinder: SimpleBinder by lazy { SimpleBinder ( ) }
override fun onBind ( intent: Intent) : IBinder {
return simpleBinder
}
private lateinit var job: Job
override fun onCreate ( ) {
super . onCreate ( )
job = GlobalScope. launch {
repeat ( 20 ) {
Log. d ( TAG, "onCreate: $it " )
simpleBinder. onListener. invoke ( it)
delay ( 1000 )
}
}
}
override fun onDestroy ( ) {
super . onDestroy ( )
job. cancel ( )
}
}
class SimpleBinder : Binder ( ) {
var onListener: ( num: Int) -> Unit = { }
}
多进程中的问题
我们将RemoteService放入单独的一个进程中
< service
android: name= ".remote.RemoteService"
android: process= ":remote"
android: enabled= "true"
android: exported= "true" / >
Process: com. zhangyu. myservice, PID: 28693
java. lang. ClassCastException: android. os. BinderProxy cannot be cast to com. zhangyu. myservice. remote. SimpleBinder
at com. zhangyu. myservice. remote. RemoteService$Companion$bind$1 . onServiceConnected ( RemoteService. kt: 25 )
at android. app. LoadedApk$ServiceDispatcher. doConnected ( LoadedApk. java: 1956 )
at android. app. LoadedApk$ServiceDispatcher$RunConnection. run ( LoadedApk. java: 1988 )
at android. os. Handler. handleCallback ( Handler. java: 883 )
at android. os. Handler. dispatchMessage ( Handler. java: 100 )
at android. os. Looper. loop ( Looper. java: 224 )
at android. app. ActivityThread. main ( ActivityThread. java: 7562 )
at java. lang. reflect. Method. invoke ( Native Method)
at com. android. internal. os. RuntimeInit$MethodAndArgsCaller. run ( RuntimeInit. java: 539 )
at com. android. internal. os. ZygoteInit. main ( ZygoteInit. java: 950 )