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

Android多Activity共享蓝牙通信后台线程实现方案咨询

可行实现方案:基于Bound Service + HandlerThread的蓝牙通信架构

核心思路

把蓝牙连接、消息收发、延迟循环逻辑全部托管给后台Bound Service,两个Activity通过绑定Service实现与后台通信线程的交互。这种方案能避开Activity生命周期波动带来的连接中断、消息丢失问题,同时保证所有蓝牙操作都在后台线程执行,不阻塞UI。

具体实现步骤

1. 创建蓝牙通信Service

Service是Android系统托管的后台组件,生命周期独立于Activity,适合长期持有蓝牙连接并处理循环任务。

  • 内部用HandlerThread创建专属后台线程,承载蓝牙读写、延迟循环逻辑
  • 通过Messenger实现与Activity的消息传递(同一进程下高效且无需复杂IPC)
  • 统一管理蓝牙Socket、输入输出流,在Service生命周期内维护连接
public class BluetoothCommService extends Service {
    private HandlerThread mCommThread;
    private Handler mServiceHandler;
    private Messenger mMessenger;
    private BluetoothSocket mSocket;
    private InputStream mInStream;
    private OutputStream mOutStream;

    // 消息类型常量
    public static final int MSG_SEND_DATA = 1;
    public static final int MSG_REGISTER_CLIENT = 2;
    public static final int MSG_UNREGISTER_CLIENT = 3;
    public static final int MSG_RECEIVE_DATA = 4;

    // 保存已注册的Activity客户端,用于回传数据
    private final ArrayList<Messenger> mClients = new ArrayList<>();

    @Override
    public void onCreate() {
        super.onCreate();
        // 初始化后台通信线程
        mCommThread = new HandlerThread("BluetoothWorker");
        mCommThread.start();
        mServiceHandler = new Handler(mCommThread.getLooper()) {
            @Override
            public void handleMessage(Message msg) {
                switch (msg.what) {
                    case MSG_SEND_DATA:
                        // 接收Activity发送的指令,写入蓝牙输出流
                        sendToArduino((String) msg.obj);
                        break;
                    case MSG_REGISTER_CLIENT:
                        // 注册Activity的Messenger,用于回传数据
                        mClients.add(msg.replyTo);
                        break;
                    case MSG_UNREGISTER_CLIENT:
                        mClients.remove(msg.replyTo);
                        break;
                }
            }
        };
        mMessenger = new Messenger(mServiceHandler);
        // 后台初始化蓝牙连接
        mServiceHandler.post(this::initBluetoothConnection);
        // 启动循环读取Arduino数据的任务
        startReadLoop();
    }

    private void initBluetoothConnection() {
        try {
            // 替换为你的蓝牙设备配对逻辑,这里假设已获取目标BluetoothDevice
            BluetoothDevice device = ...;
            mSocket = device.createRfcommSocketToServiceRecord(
                UUID.fromString("00001101-0000-1000-8000-00805F9B34FB")
            );
            mSocket.connect();
            mInStream = mSocket.getInputStream();
            mOutStream = mSocket.getOutputStream();
        } catch (IOException e) {
            e.printStackTrace();
            // 可添加重连逻辑,比如延迟3秒后重试
            mServiceHandler.postDelayed(this::initBluetoothConnection, 3000);
        }
    }

    private void startReadLoop() {
        Runnable readTask = new Runnable() {
            @Override
            public void run() {
                if (mInStream == null) {
                    mServiceHandler.postDelayed(this, 100);
                    return;
                }
                byte[] buffer = new byte[1024];
                try {
                    int bytesRead = mInStream.read(buffer);
                    if (bytesRead > 0) {
                        String received = new String(buffer, 0, bytesRead);
                        // 把数据回传给所有已注册的Activity
                        broadcastToClients(received);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    // 读取异常,触发重连
                    initBluetoothConnection();
                }
                // 延迟100ms后再次执行,实现循环监听
                mServiceHandler.postDelayed(this, 100);
            }
        };
        mServiceHandler.post(readTask);
    }

    private void sendToArduino(String data) {
        if (mOutStream == null) return;
        try {
            mOutStream.write(data.getBytes());
            mOutStream.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private void broadcastToClients(String data) {
        Iterator<Messenger> iterator = mClients.iterator();
        while (iterator.hasNext()) {
            Messenger client = iterator.next();
            try {
                Message msg = Message.obtain(null, MSG_RECEIVE_DATA);
                msg.obj = data;
                client.send(msg);
            } catch (RemoteException e) {
                // 客户端已断开,移除
                iterator.remove();
            }
        }
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return mMessenger.getBinder();
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        // 释放蓝牙资源
        try {
            if (mInStream != null) mInStream.close();
            if (mOutStream != null) mOutStream.close();
            if (mSocket != null) mSocket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }
        // 终止后台线程
        mCommThread.quit();
    }
}

2. Activity绑定Service并通信

两个Activity(Configure和Operate)通过相同的逻辑绑定Service,发送指令并接收回传数据:

public class ConfigureActivity extends AppCompatActivity {
    private Messenger mServiceMessenger;
    private boolean mIsBound;
    // 用于接收Service回传消息的客户端Messenger
    private final Messenger mClientMessenger = new Messenger(new Handler(Looper.getMainLooper()) {
        @Override
        public void handleMessage(Message msg) {
            if (msg.what == BluetoothCommService.MSG_RECEIVE_DATA) {
                String data = (String) msg.obj;
                // 更新UI,比如显示Arduino返回的配置数据
                updateConfigUI(data);
            }
        }
    });

    private final ServiceConnection mServiceConn = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName name, IBinder service) {
            mServiceMessenger = new Messenger(service);
            mIsBound = true;
            // 注册客户端,告知Service需要回传数据
            try {
                Message msg = Message.obtain(null, BluetoothCommService.MSG_REGISTER_CLIENT);
                msg.replyTo = mClientMessenger;
                mServiceMessenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onServiceDisconnected(ComponentName name) {
            mServiceMessenger = null;
            mIsBound = false;
        }
    };

    @Override
    protected void onStart() {
        super.onStart();
        // 绑定蓝牙通信Service
        bindService(new Intent(this, BluetoothCommService.class), mServiceConn, BIND_AUTO_CREATE);
    }

    @Override
    protected void onStop() {
        super.onStop();
        if (mIsBound) {
            // 取消注册,避免Service继续向已销毁的Activity发消息
            try {
                Message msg = Message.obtain(null, BluetoothCommService.MSG_UNREGISTER_CLIENT);
                msg.replyTo = mClientMessenger;
                mServiceMessenger.send(msg);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
            unbindService(mServiceConn);
            mIsBound = false;
        }
    }

    // 发送配置数据到Arduino的方法,比如点击保存按钮时调用
    private void sendConfigData(String config) {
        if (!mIsBound || mServiceMessenger == null) return;
        try {
            Message msg = Message.obtain(null, BluetoothCommService.MSG_SEND_DATA);
            msg.obj = config;
            mServiceMessenger.send(msg);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    private void updateConfigUI(String data) {
        // 实现UI更新逻辑
    }
}

关键优势

  • 蓝牙连接稳定:Service生命周期独立,不会因Activity切换、销毁而中断连接
  • 线程安全:所有蓝牙操作都在HandlerThread中执行,避免UI线程阻塞
  • 多Activity共享:两个Activity只需绑定Service即可复用同一通信通道,无需重复初始化蓝牙
  • 灵活扩展:可在Service中添加重连、日志、数据解析等逻辑,不侵入Activity代码

内容的提问来源于stack exchange,提问作者Gerald Eberhardt

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.14 21:15:17