在绑定服务后,会回调onBind
方法,此方法会返回IBinder
。我们可以通过扩展自己的Binder
来达到自己的目的。下面直接上代码:
class BinderService : Service() {
companion object {
val TAG = "BinderService"
}
private val mBinder: IBinder = TestBinder()
override fun onCreate() {
Log.d(TAG, "onCreate")
super.onCreate()
}
override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int {
Log.d(TAG, "onStartCommand")
return super.onStartCommand(intent, flags, startId)
}
override fun onBind(intent: Intent?): IBinder? {
Log.d(TAG, "onBind")
return mBinder
}
override fun onUnbind(intent: Intent?): Boolean {
Log.d(TAG, "onUnbind")
return true
}
override fun onRebind(intent: Intent?) {
Log.d(TAG, "onRebind")
super.onRebind(intent)
}
override fun onDestroy() {
Log.d(TAG, "onDestroy")
super.onDestroy()
}
fun toDoAnything() {
Log.d(TAG, "toDoAnyThing")
}
inner class TestBinder : Binder() {
fun getService() : BinderService {
return this@BinderService
}
}
}
我们在TestService
内部创建一个TestBinder
,并在其中提供一个获取TestService
实例的方法。然后在TestService
中定义一个toDoAnything()
方法。再来看下Activity的使用:
class BinderActivity : AppCompatActivity() {
private var serviceIntent: Intent? = null
private var isBindService = false
private var mBinder: BinderService.TestBinder? = null
private var mService: BinderService? = null
private val serviceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
isBindService = false
mBinder = null
mService = null
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
isBindService = true
mBinder = service as BinderService.TestBinder?
mService = mBinder?.getService()
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_service)
serviceIntent = Intent(this, BinderService::class.java)
btnBind.setOnClickListener {
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE)
}
btnUnBind.setOnClickListener {
unbindService(serviceConnection)
}
btn.setOnClickListener {
if (isBindService) {
mService?.toDoAnything()
}
}
}
override fun onDestroy() {
if (isBindService)
unbindService(serviceConnection)
super.onDestroy()
}
}
代码很简单,主要是利用bindService
时,传递的ServiceConnection
。在其onServiceConnected()
方法中获取Binder
,在通过Binder
获取到TestService
实例,然后就可以调用TestService
中相应的方法了。
我们在清单文件中将TestService
设置为在单独的进程中运行:
".TestService"
android:process=":remote" />
再次运行程序,并进行相应的操作,你会发现应用程序会挂掉。没错,扩展Binder的方式,只适用于本应用程序内适用,即组件和Service在同一个进程中。
那么有没有方法可以进行进程间的交互呢?别着急,下面的方式就可以了。
如需让服务与远程进程通信,则可使用 Messenger 为您的服务提供接口。
以下是 Messenger 的使用方法摘要:
这样,客户端并没有调用服务的“方法”。而客户端传递的“消息”(Message 对象)是服务在其 Handler 中接收的。
下面来看下具体的使用:
class MessengerService : Service() {
companion object {
private val TAG = "MessengerService"
val MSG_SAY_HELLO = 1
val MSG_TO_CLIENT = 2
val EXTRA_REPLY_STR_TO_CLIENT = "extra_reply_str_to_client"
val EXTRA_SEND_STR_TO_SERVICE = "extra_send_str_to_service"
private class ServiceHandler(messengerService: MessengerService) : Handler() {
private var mReference: WeakReference = WeakReference(messengerService)
override fun handleMessage(msg: Message) {
val service: MessengerService? = mReference.get()
service?.let {
when (msg.what) {
MSG_SAY_HELLO -> {
Log.d(TAG, "process id is ${Process.myPid()}, Hello!")
Toast.makeText(service.applicationContext, "hello!", Toast.LENGTH_SHORT).show()
val messenger: Messenger = msg.replyTo // 获取用于回复的Messenger
val serviceMessage: Message = Message.obtain(null, MSG_TO_CLIENT)
val bundle = Bundle()
bundle.putString(EXTRA_REPLY_STR_TO_CLIENT, "I have received your message")
serviceMessage.data = bundle
messenger.send(serviceMessage)
}
else -> super.handleMessage(msg)
}
}
}
}
}
private val mMessenger: Messenger = Messenger(ServiceHandler(this))
override fun onBind(intent: Intent?): IBinder? {
Log.d(TAG, "onBind")
return mMessenger.binder
}
}
class MessengerActivity : AppCompatActivity() {
companion object {
// 此handler用于接收Service的回复信息
private class ClientHandler(messengerActivity: MessengerActivity) : Handler() {
private val mReference: WeakReference = WeakReference(messengerActivity)
override fun handleMessage(msg: Message) {
val activity = mReference.get()
activity?.let {
when(msg.what) {
MessengerService.MSG_TO_CLIENT -> {
Log.d(activity.localClassName, "${msg.data[MessengerService.EXTRA_REPLY_STR_TO_CLIENT]}, process id is ${Process.myPid()}")
}
else -> super.handleMessage(msg)
}
}
}
}
}
private var serviceIntent: Intent? = null
private var isBindService = false
private var mServiceMessenger: Messenger? = null
private var mClientMessenger: Messenger = Messenger(ClientHandler(this))
private val serviceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceDisconnected(name: ComponentName?) {
isBindService = false
mServiceMessenger = null
}
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
isBindService = true
mServiceMessenger = Messenger(service) // 获取Service的Messenger
Log.d(localClassName, "ServiceConnection onServiceConnected()")
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_service)
serviceIntent = Intent(this, MessengerService::class.java)
btnStart.setOnClickListener {
startService(serviceIntent)
}
btnStop.setOnClickListener {
stopService(serviceIntent)
}
btnBind.setOnClickListener {
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE)
}
btnUnBind.setOnClickListener {
unbindService(serviceConnection)
}
btn.setOnClickListener {
Log.d("MessengerActivity", "process id is ${Process.myPid()}")
if (isBindService)
sayHello()
}
}
private fun sayHello() {
val message: Message = Message.obtain(null, MessengerService.MSG_SAY_HELLO)
val bundle = Bundle()
bundle.putString(MessengerService.EXTRA_SEND_STR_TO_SERVICE, "hello, this is client.")
message.data = bundle
message.replyTo = mClientMessenger // 设置用于回复消息的Messenger
mServiceMessenger?.send(message)
}
override fun onDestroy() {
if (isBindService)
unbindService(serviceConnection)
super.onDestroy()
}
}
在向服务端发送信息时,通过Message.replyTo
将客户端的Messenger
传递给服务端。服务端接收到消息后,通过Message.replyTo
获取客户端的Messenger
,然后用此向客户端发送消息。
AIDL:Android Interface Definition Language,即Android接口定义语言;用于让某个Service与多个应用程序组件之间进行跨进程通信,从而可以实现多个应用程序共享同一个Service的功能。
Friend.java
实现了Parcelable,那么就需要向下面一样,创建Friend.aidl进行声明。它们两的包名需要一致:// Friend.aidl
package com.demo.service.aidl.bean;
parcelable Friend;
import
显示导入。in
、out
或inout
。
in
:代表数据为输入型(客户端提供数据,服务端获取。服务端改变数据,不会影响客户端测数据)
out
:代表数据为输出型(数据由服务端提供输出给客户端。客户端给的初始值,服务端并不会获取到;服务端改变数据,客户端所拥有的数据也会随之改变)
inout
:代表数据为输入输出型(结合了in
和out
的特性,客户端提供的数据,服务端可以获取到;服务端改变数据,客户端数据也会随之改变)
下面用一个简单的小例子来演示如何使用AIDL:演示一个朋友群,添加了新朋友后,通知其他人有新的朋友被添加了。
Friend
类,并且实现Parcelable
package com.demo.service.aidl.bean
import android.os.Parcel
import android.os.Parcelable
class Friend(var name: String, var isNew: Boolean) : Parcelable {
constructor(source: Parcel) : this(
source.readString(),
1 == source.readInt()
)
override fun describeContents() = 0
override fun writeToParcel(dest: Parcel, flags: Int) = with(dest) {
writeString(name)
writeInt((if (isNew) 1 else 0))
}
companion object {
@JvmField
val CREATOR: Parcelable.Creator = object : Parcelable.Creator {
override fun createFromParcel(source: Parcel): Friend = Friend(source)
override fun newArray(size: Int): Array = arrayOfNulls(size)
}
}
}
Friend
的aidl
文件,注意此文件包名需和Friend
类包名一致// Friend.aidl
package com.demo.service.aidl.bean;
parcelable Friend;
aidl
的回调接口文件// IOnNewFriendAddListener.aidl
package com.demo.service.aidl;
import com.demo.service.aidl.bean.Friend;
interface IOnNewFriendAddedListener {
void onNewFriendAdded(in Friend newFriend);
}
Service
需要实现的aidl
文件,在其中编写相应的方法// IFriendService.aidl
package com.demo.service.aidl;
import com.demo.service.aidl.bean.Friend;
import com.demo.service.aidl.IOnNewFriendAddedListener;
interface IFriendService {
void addFriend(in Friend friend);
void registerListener(in IOnNewFriendAddedListener listener);
void unRegisterListener(in IOnNewFriendAddedListener listener);
}
Service
,并在onBind
方法中返回IFriendService.Stub
的具体实现class FriendGroupService : Service() {
companion object {
val TAG = "FriendGroupService"
}
private val friendList: CopyOnWriteArrayList by lazy {
CopyOnWriteArrayList()
}
private val callbackList: RemoteCallbackList by lazy {
RemoteCallbackList()
}
private val mBind = object : IFriendService.Stub() {
override fun addFriend(friend: Friend?) {
friend?.let {
Log.d(TAG, "Friend is added")
friendList.add(friend)
if (friend.isNew) {
val num = callbackList.beginBroadcast()
for (i in 0 until num) {
val callback = callbackList.getBroadcastItem(i)
callback?.let { callback.onNewFriendAdded(friend) }
}
callbackList.finishBroadcast()
}
}
}
override fun registerListener(listener: IOnNewFriendAddedListener?) {
listener?.let { callbackList.register(listener) }
}
override fun unRegisterListener(listener: IOnNewFriendAddedListener?) {
listener?.let { callbackList.unregister(listener) }
}
}
override fun onBind(intent: Intent?): IBinder? {
return mBind
}
}
service
的绑定,onServiceConnected
中获取IFriendService
,从而使用它进行回调注册,相应方法的使用。class ClientActivity : AppCompatActivity() {
private var mService: IFriendService? = null
private var isBindService = false
private var serviceIntent: Intent? = null
private var num: Int = 0
private val callback = object : IOnNewFriendAddedListener.Stub() {
override fun onNewFriendAdded(newFriend: Friend?) {
newFriend?.let { Log.d(localClassName, "Friend is added, Friend's name is ${newFriend.name}") }
}
}
private val serviceConnection: ServiceConnection = object : ServiceConnection {
override fun onServiceConnected(name: ComponentName?, service: IBinder?) {
mService = IFriendService.Stub.asInterface(service)
mService?.let {
mService!!.registerListener(callback)
}
isBindService = true
}
override fun onServiceDisconnected(name: ComponentName?) {
isBindService = false
mService = null
}
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
setContentView(R.layout.activity_service)
serviceIntent = Intent(this, FriendGroupService::class.java)
btnStart.setOnClickListener {
startService(serviceIntent)
}
btnStop.setOnClickListener {
stopService(serviceIntent)
}
btnBind.setOnClickListener {
bindService(serviceIntent, serviceConnection, Context.BIND_AUTO_CREATE)
}
btnUnBind.setOnClickListener {
unbindService(serviceConnection)
}
btn.setOnClickListener {
addFriend()
}
}
private fun addFriend() {
if (isBindService) {
mService?.let {
num++
val friend = Friend("Friend$num", true)
mService!!.addFriend(friend)
}
}
}
override fun onDestroy() {
mService?.let {
if (mService!!.asBinder().isBinderAlive) {
try {
mService!!.unRegisterListener(callback)
} catch (e: RemoteException) {
}
}
}
if (isBindService)
unbindService(serviceConnection)
super.onDestroy()
}
}
Log
输出结果:
com.demo.service:remote D/FriendGroupService: Friend is added
com.demo.service D/aidl.ClientActivity: Friend is added, Friend's name is Friend1
com.demo.service:remote D/FriendGroupService: Friend is added
com.demo.service D/aidl.ClientActivity: Friend is added, Friend's name is Friend2
com.demo.service:remote D/FriendGroupService: Friend is added
com.demo.service D/aidl.ClientActivity: Friend is added, Friend's name is Friend3
com.demo.service:remote D/FriendGroupService: Friend is added
com.demo.service D/aidl.ClientActivity: Friend is added, Friend's name is Friend4
前往Github查看完整代码