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

Android Studio中Java多Activity全局蓝牙实现求助

作为Android Java开发的过来人,我完全理解你作为新手在跨Activity管理蓝牙连接时的困惑——毕竟蓝牙操作涉及后台生命周期、线程管理还有组件间通信,确实容易踩坑。下面我给你一套清晰、适合新手的实现方案,核心是用Service来托管蓝牙连接,让多个Activity都能安全复用这个连接:

一、核心思路:用Service托管蓝牙连接

为什么选Service?因为Activity的生命周期不稳定(切换页面、退到后台都会销毁/暂停),而Service是后台组件,能在后台持续保持蓝牙连接。多个Activity可以通过绑定Service获取蓝牙操作实例,实现跨页面的蓝牙功能。

二、第一步:创建蓝牙管理Service

我们需要写一个继承自Service的类,封装蓝牙的初始化、连接、数据收发逻辑,同时提供Binder让Activity绑定后调用这些方法。

public class BluetoothService extends Service {
    // 蓝牙核心对象
    private BluetoothAdapter mBluetoothAdapter;
    private BluetoothSocket mBluetoothSocket;
    private InputStream mInputStream;
    private OutputStream mOutputStream;
    // 用于Activity绑定的Binder
    private final IBinder mBinder = new LocalBinder();
    // 主线程Handler,用于更新UI状态
    private Handler mHandler = new Handler(Looper.getMainLooper());

    // 内部Binder类,Activity绑定后可获取Service实例
    public class LocalBinder extends Binder {
        BluetoothService getService() {
            return BluetoothService.this;
        }
    }

    @Override
    public IBinder onBind(Intent intent) {
        return mBinder;
    }

    // 初始化蓝牙适配器
    public boolean initBluetooth() {
        mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        if (mBluetoothAdapter == null) {
            sendBroadcast(new Intent("BLUETOOTH_STATUS").putExtra("msg", "设备不支持蓝牙"));
            return false;
        }
        if (!mBluetoothAdapter.isEnabled()) {
            sendBroadcast(new Intent("BLUETOOTH_STATUS").putExtra("msg", "请开启蓝牙"));
            return false;
        }
        return true;
    }

    // 连接蓝牙设备(参数为目标设备MAC地址)
    public void connectDevice(String deviceMac) {
        new Thread(() -> {
            try {
                BluetoothDevice device = mBluetoothAdapter.getRemoteDevice(deviceMac);
                // 通用串口UUID,需与设备端一致
                UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
                mBluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
                // 取消扫描避免干扰连接
                mBluetoothAdapter.cancelDiscovery();
                // 建立连接
                mBluetoothSocket.connect();
                // 获取读写流
                mInputStream = mBluetoothSocket.getInputStream();
                mOutputStream = mBluetoothSocket.getOutputStream();

                // 通知Activity连接成功
                mHandler.post(() -> sendBroadcast(new Intent("BLUETOOTH_STATUS").putExtra("msg", "连接成功")));
                // 开始监听接收数据
                listenForData();
            } catch (IOException e) {
                e.printStackTrace();
                mHandler.post(() -> sendBroadcast(new Intent("BLUETOOTH_STATUS").putExtra("msg", "连接失败:" + e.getMessage())));
                // 异常时关闭资源
                try {
                    if (mBluetoothSocket != null) mBluetoothSocket.close();
                } catch (IOException ex) {
                    ex.printStackTrace();
                }
            }
        }).start();
    }

    // 监听蓝牙接收的数据
    private void listenForData() {
        new Thread(() -> {
            byte[] buffer = new byte[1024];
            int bytes;
            while (mBluetoothSocket != null && mInputStream != null) {
                try {
                    bytes = mInputStream.read(buffer);
                    if (bytes > 0) {
                        String receivedData = new String(buffer, 0, bytes);
                        // 把数据广播给Activity
                        mHandler.post(() -> sendBroadcast(new Intent("BLUETOOTH_DATA").putExtra("data", receivedData)));
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                    break;
                }
            }
        }).start();
    }

    // 发送数据到蓝牙设备
    public void sendData(String data) {
        if (mOutputStream != null) {
            new Thread(() -> {
                try {
                    mOutputStream.write(data.getBytes());
                    mOutputStream.flush();
                    mHandler.post(() -> sendBroadcast(new Intent("BLUETOOTH_STATUS").putExtra("msg", "数据发送成功")));
                } catch (IOException e) {
                    e.printStackTrace();
                    mHandler.post(() -> sendBroadcast(new Intent("BLUETOOTH_STATUS").putExtra("msg", "发送失败:" + e.getMessage())));
                }
            }).start();
        } else {
            sendBroadcast(new Intent("BLUETOOTH_STATUS").putExtra("msg", "未连接蓝牙设备"));
        }
    }

    // 断开蓝牙连接
    public void disconnect() {
        try {
            if (mInputStream != null) mInputStream.close();
            if (mOutputStream != null) mOutputStream.close();
            if (mBluetoothSocket != null) mBluetoothSocket.close();
            sendBroadcast(new Intent("BLUETOOTH_STATUS").putExtra("msg", "已断开连接"));
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        disconnect();
    }
}
三、第二步:在Manifest中注册Service和权限

别忘了在AndroidManifest.xml中添加必要的权限和Service声明:

<!-- 蓝牙权限(适配不同Android版本) -->
<uses-permission android:name="android.permission.BLUETOOTH" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" android:maxSdkVersion="30" />
<uses-permission android:name="android.permission.BLUETOOTH_SCAN" android:usesPermissionFlags="neverForLocation" />
<uses-permission android:name="android.permission.BLUETOOTH_CONNECT" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" android:maxSdkVersion="30" />
<!-- 注册蓝牙Service -->
<service android:name=".BluetoothService" />
四、第三步:Activity绑定Service并操作蓝牙

每个需要使用蓝牙的Activity都可以绑定Service,绑定后就能调用蓝牙方法,同时通过广播接收状态和数据。

示例1:主Activity(连接蓝牙)

public class MainActivity extends AppCompatActivity {
    private BluetoothService mBluetoothService;
    private boolean mBound = false;
    // 广播接收器,接收Service的状态和数据
    private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            String action = intent.getAction();
            if ("BLUETOOTH_STATUS".equals(action)) {
                String msg = intent.getStringExtra("msg");
                Toast.makeText(MainActivity.this, msg, Toast.LENGTH_SHORT).show();
            } else if ("BLUETOOTH_DATA".equals(action)) {
                String data = intent.getStringExtra("data");
                Log.d("Bluetooth", "收到数据:" + data);
            }
        }
    };

    // Service连接回调
    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            BluetoothService.LocalBinder binder = (BluetoothService.LocalBinder) service;
            mBluetoothService = binder.getService();
            mBound = true;
            // 初始化蓝牙
            mBluetoothService.initBluetooth();
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // 动态申请蓝牙权限(Android 6.0+必需)
        requestPermissions(new String[]{Manifest.permission.BLUETOOTH_SCAN, Manifest.permission.BLUETOOTH_CONNECT, Manifest.permission.ACCESS_FINE_LOCATION}, 100);

        // 注册广播接收器
        IntentFilter filter = new IntentFilter();
        filter.addAction("BLUETOOTH_STATUS");
        filter.addAction("BLUETOOTH_DATA");
        registerReceiver(mBluetoothReceiver, filter);

        // 绑定Service
        Intent intent = new Intent(this, BluetoothService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

        // 连接蓝牙按钮(替换为你的设备MAC地址)
        Button connectBtn = findViewById(R.id.connect_btn);
        connectBtn.setOnClickListener(v -> {
            if (mBound) {
                mBluetoothService.connectDevice("00:1A:7D:DA:71:13"); // 替换成目标设备MAC
            }
        });

        // 跳转第二个Activity,测试跨页面操作
        Button goSecondBtn = findViewById(R.id.go_second_btn);
        goSecondBtn.setOnClickListener(v -> startActivity(new Intent(MainActivity.this, SecondActivity.class)));
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBluetoothReceiver);
        // 若需后台保持连接,不要解绑Service
        // unbindService(mConnection);
        // mBound = false;
    }
}

示例2:第二个Activity(发送数据)

public class SecondActivity extends AppCompatActivity {
    private BluetoothService mBluetoothService;
    private boolean mBound = false;
    private BroadcastReceiver mBluetoothReceiver = new BroadcastReceiver() {
        @Override
        public void onReceive(Context context, Intent intent) {
            if ("BLUETOOTH_STATUS".equals(intent.getAction())) {
                String msg = intent.getStringExtra("msg");
                Toast.makeText(SecondActivity.this, msg, Toast.LENGTH_SHORT).show();
            }
        }
    };

    private ServiceConnection mConnection = new ServiceConnection() {
        @Override
        public void onServiceConnected(ComponentName className, IBinder service) {
            BluetoothService.LocalBinder binder = (BluetoothService.LocalBinder) service;
            mBluetoothService = binder.getService();
            mBound = true;
        }

        @Override
        public void onServiceDisconnected(ComponentName arg0) {
            mBound = false;
        }
    };

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_second);

        IntentFilter filter = new IntentFilter("BLUETOOTH_STATUS");
        registerReceiver(mBluetoothReceiver, filter);

        // 绑定Service
        Intent intent = new Intent(this, BluetoothService.class);
        bindService(intent, mConnection, Context.BIND_AUTO_CREATE);

        // 发送数据按钮
        Button sendBtn = findViewById(R.id.send_btn);
        sendBtn.setOnClickListener(v -> {
            if (mBound) {
                mBluetoothService.sendData("Hello from Second Activity!");
            }
        });
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        unregisterReceiver(mBluetoothReceiver);
    }
}
五、新手常见坑提示
  • 权限问题:务必确保动态权限申请成功,Android 12+的BLUETOOTH_CONNECT和BLUETOOTH_SCAN权限是必需的。
  • UUID一致性:连接时的UUID必须和蓝牙设备端一致,通用串口UUID是00001101-0000-1000-8000-00805F9B34FB,自定义设备需确认UUID。
  • 线程操作:蓝牙的连接、读写必须在子线程进行,否则会触发ANR(应用无响应),上面代码已用Thread处理。
  • Service生命周期:若需持续保持蓝牙连接,不要在Activity退出时解绑Service,仅在App完全退出时解绑即可。

慢慢测试,先确保Service能正常绑定,再测试蓝牙连接,最后验证跨Activity数据收发,遇到问题查看Logcat的错误信息,大部分问题都出在权限、UUID或线程上。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.22 10:02:27