Android Kotlin跨应用:如何从Service向Activity传递数据?
跨应用场景下Service向Activity传数据(Kotlin实现)
问题
要在跨应用场景下实现Service往Activity传递数据,已经用Messenger搞定了Activity到Service的通信,但找不到Kotlin版的Service到Activity实现方案,不清楚怎么把Activity的IncomingHandler和Service的onServiceConnected绑定起来调用mService?.send(msg)。
你当前尝试的LocalBroadcast代码
Service端代码
val intent = Intent("TO_SALE_APP") intent.putExtra("RESPONSE_CODE", responseCode) intent.putExtra("STATUS", status) intent.putExtra("PAYMENT_TYPE", paymentType) LocalBroadcastManager.getInstance(this.applicationContext).sendBroadcast(intent)
Activity端代码
private val mMessageReceiver: BroadcastReceiver = object : BroadcastReceiver() { override fun onReceive(context: Context?, intent: Intent) { val responseCode = intent.getStringExtra("RESPONSE_CODE") val status = intent.getIntExtra("STATUS",0) val paymentType = intent.getIntExtra("PAYMENT_TYPE",0) Log.d("myTAG","data receive on activity!") } } override fun onCreate(savedInstanceState: Bundle?) { // 其他初始化代码 LocalBroadcastManager.getInstance(this).registerReceiver( mMessageReceiver, IntentFilter("TO_SALE_APP") ) }
注意:LocalBroadcast跨应用无效
LocalBroadcastManager仅支持同应用内通信,跨应用场景下完全无法传递数据,所以这个方案走不通,必须改用Messenger或AIDL。下面直接给出Messenger实现跨应用双向通信的Kotlin完整代码:
Messenger跨应用双向通信(Kotlin版)
1. Service端代码
Service需要保存Activity传递过来的Messenger,后续用它向Activity回传消息:
class RemoteService : Service() { // 处理Activity发来的消息 private val serviceMessenger = Messenger(object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { when (msg.what) { // 接收Activity请求,同时保存客户端的Messenger 0 -> { val clientMessenger = msg.replyTo // 模拟Service处理完任务后,向Activity回传数据 val replyMsg = Message.obtain(null, 1) val bundle = Bundle().apply { putString("RESPONSE_CODE", "SUCCESS") putInt("STATUS", 1) putInt("PAYMENT_TYPE", 2) } replyMsg.data = bundle // 发送消息给Activity clientMessenger?.send(replyMsg) } else -> super.handleMessage(msg) } } }) override fun onBind(intent: Intent): IBinder { return serviceMessenger.binder } }
别忘了在Manifest中注册Service,必须开启android:exported="true"允许跨应用绑定:
<service android:name=".RemoteService" android:exported="true"> <intent-filter> <action android:name="com.example.REMOTE_SERVICE" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </service>
2. Activity端代码
Activity需要自定义IncomingHandler接收Service的回传消息,绑定Service时把自己的Messenger传给Service:
class MainActivity : AppCompatActivity() { // 接收Service回传消息的Messenger private val clientMessenger = Messenger(object : Handler(Looper.getMainLooper()) { override fun handleMessage(msg: Message) { when (msg.what) { // 处理Service回传的数据 1 -> { val responseCode = msg.data.getString("RESPONSE_CODE") val status = msg.data.getInt("STATUS", 0) val paymentType = msg.data.getInt("PAYMENT_TYPE", 0) Log.d("myTAG", "收到Service数据:responseCode=$responseCode, status=$status, paymentType=$paymentType") } else -> super.handleMessage(msg) } } }) private var serviceMessenger: Messenger? = null private val serviceConnection = object : ServiceConnection { override fun onServiceConnected(name: ComponentName?, service: IBinder?) { // 绑定成功,获取Service的Messenger用于发消息 serviceMessenger = Messenger(service) // 向Service发送消息,并附带自己的Messenger让Service能回传 val msg = Message.obtain(null, 0) msg.replyTo = clientMessenger serviceMessenger?.send(msg) } override fun onServiceDisconnected(name: ComponentName?) { serviceMessenger = null } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_main) // 绑定跨应用的Service val intent = Intent("com.example.REMOTE_SERVICE") // 跨应用必须指定目标应用包名(替换为Service所在APP的包名) intent.setPackage("com.example.remoteapp") bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE) } override fun onDestroy() { super.onDestroy() // 解绑Service unbindService(serviceConnection) } }
重点提醒
- 跨应用绑定时,必须指定目标Service所在APP的包名,否则系统无法找到对应Service
- Service必须设置
android:exported="true",并通过intent-filter暴露可调用的action - Messenger基于Handler实现,所有消息处理都在主线程,适合轻量级跨进程通信;复杂场景建议使用AIDL
内容的提问来源于stack exchange,提问作者Sezai
相关产品推荐
相关产品推荐

