You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android中如何将BluetoothSocket从一个Activity传递到另一个Activity?

传递BluetoothSocket到另一个Activity的方案

核心限制说明

BluetoothSocket 既不实现 Serializable 也不实现 Parcelable,所以不能直接通过Intent.putExtra()传递,必须通过共享对象的方式实现。


推荐方案:用后台Service管理蓝牙连接

这是Android蓝牙开发的标准实践,蓝牙连接属于长期运行的后台任务,放在Service中可以避免Activity销毁导致连接中断,同时能安全地在多个Activity间共享连接实例。

实现步骤:

  1. 创建蓝牙Service类:在Service中完成蓝牙连接的建立、维护,提供获取BluetoothSocket的方法,或直接封装数据收发API。
  2. Activity绑定Service:连接Activity和控制Activity都通过bindService()绑定到该Service,获取Service实例后即可访问蓝牙连接。

代码示例:

1. 蓝牙Service类

class BluetoothConnectionService : Service() {
    private var bluetoothSocket: BluetoothSocket? = null
    // 用于和绑定Activity通信的Binder
    private val binder = LocalBinder()

    inner class LocalBinder : Binder() {
        fun getService(): BluetoothConnectionService = this@BluetoothConnectionService
    }

    override fun onBind(intent: Intent): IBinder {
        return binder
    }

    // 对外提供获取Socket的方法
    fun getBluetoothSocket(): BluetoothSocket? {
        return bluetoothSocket
    }

    // 建立蓝牙连接的逻辑
    fun connectToDevice(device: BluetoothDevice) {
        // 省略设备连接的前置校验逻辑
        bluetoothSocket = device.createRfcommSocketToServiceRecord(UUID.fromString("00001101-0000-1000-8000-00805F9B34FB"))
        bluetoothSocket?.connect()
    }

    // 封装数据发送方法,控制Activity可直接调用
    fun sendData(data: ByteArray) {
        bluetoothSocket?.outputStream?.write(data)
    }
}

2. 连接Activity中绑定并建立连接

class ConnectionActivity : AppCompatActivity() {
    private lateinit var service: BluetoothConnectionService
    private var isServiceBound = false

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, serviceBinder: IBinder) {
            val binder = serviceBinder as BluetoothConnectionService.LocalBinder
            service = binder.getService()
            isServiceBound = true
            // 用户选中设备后调用连接方法
            val selectedDevice: BluetoothDevice = ... // 获取选中的蓝牙设备
            service.connectToDevice(selectedDevice)
            // 连接成功跳转控制页
            startActivity(Intent(this@ConnectionActivity, ControlActivity::class.java))
        }

        override fun onServiceDisconnected(arg0: ComponentName) {
            isServiceBound = false
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 绑定Service
        Intent(this, BluetoothConnectionService::class.java).also { intent ->
            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        if (isServiceBound) {
            unbindService(serviceConnection)
            isServiceBound = false
        }
    }
}

3. 控制Activity中绑定Service并使用连接

class ControlActivity : AppCompatActivity() {
    private lateinit var service: BluetoothConnectionService
    private var isServiceBound = false

    private val serviceConnection = object : ServiceConnection {
        override fun onServiceConnected(className: ComponentName, serviceBinder: IBinder) {
            val binder = serviceBinder as BluetoothConnectionService.LocalBinder
            service = binder.getService()
            isServiceBound = true
            // 获取已建立的Socket或直接调用发送方法
            val socket = service.getBluetoothSocket()
            // 启动数据收发逻辑
        }

        override fun onServiceDisconnected(arg0: ComponentName) {
            isServiceBound = false
        }
    }

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        // 绑定Service
        Intent(this, BluetoothConnectionService::class.java).also { intent ->
            bindService(intent, serviceConnection, Context.BIND_AUTO_CREATE)
        }
    }

    override fun onDestroy() {
        super.onDestroy()
        if (isServiceBound) {
            unbindService(serviceConnection)
            isServiceBound = false
        }
    }

    // 示例:发送文本消息
    private fun sendMessage(message: String) {
        if (isServiceBound) {
            service.sendData(message.toByteArray())
        }
    }
}

备选方案:使用单例类持有BluetoothSocket

如果场景简单,不需要长期后台连接,可以用单例类全局持有Socket实例,但要注意内存泄漏问题,在不需要时及时释放资源。

代码示例:

object BluetoothSocketHolder {
    var socket: BluetoothSocket? = null

    // 释放资源的方法,在应用退出或连接断开时调用
    fun release() {
        socket?.close()
        socket = null
    }
}

连接Activity中赋值:

// 连接成功后
BluetoothSocketHolder.socket = bluetoothSocket
startActivity(Intent(this, ControlActivity::class.java))

控制Activity中获取:

val socket = BluetoothSocketHolder.socket
// 使用socket进行数据收发

注意事项:

  • 单例持有Socket会导致其生命周期与进程绑定,若Activity销毁但进程未结束,Socket会一直存在,可能引发内存泄漏,需在合适时机调用release()。
  • 多线程环境下需注意同步,可加锁或用线程安全方式访问。

内容的提问来源于stack exchange,提问作者Shady Abdulmunim

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.26 07:35:20