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

Android蓝牙10秒未接收数据时触发震动提醒的实现方案问询

蓝牙设备10秒无数据接收的震动提醒实现方案

核心思路

  • 利用Handler的延迟任务机制:每次收到蓝牙数据时重置延迟任务,若10秒内无新数据,延迟任务触发超时提醒
  • 通过BtClientService的Handler向MyActivity发送超时消息,由UI层处理震动逻辑

具体实现步骤

1. 定义超时消息常量

在Constants类中新增超时消息标识:

public static final int MESSAGE_TIMEOUT = 0x0003; // 可根据现有常量调整数值

2. 改造BtClientService的ConnectedThread

在BtClientService中添加超时监控的Runnable和Handler逻辑,修改ConnectedThread的run方法:

private class ConnectedThread extends Thread {
    // 原有成员变量不变
    private Handler mTimeoutHandler = new Handler(Looper.getMainLooper());
    private Runnable mTimeoutRunnable = new Runnable() {
        @Override
        public void run() {
            // 10秒未收到数据,发送超时消息给UI
            mHandler.obtainMessage(Constants.MESSAGE_TIMEOUT).sendToTarget();
        }
    };

    public ConnectedThread(BluetoothSocket socket, String socketType) {
        // 原有构造逻辑不变
        Log.d(TAG, "create ConnectedThread: " + socketType);
        mmSocket = socket;
        InputStream tmpIn = null;
        OutputStream tmpOut = null;

        // Get the BluetoothSocket input and output streams
        try {
            tmpIn = socket.getInputStream();
            tmpOut = socket.getOutputStream();
        } catch (IOException e) {
            Log.e(TAG, "temp sockets not created ~ " + e.toString());
        }

        mmInStream = tmpIn;
        mmOutStream = tmpOut;
        mState = STATE_CONNECTED;
    }

    public void run() {
        Log.i(TAG, "BEGIN mConnectedThread");
        byte[] buffer = new byte[1024];
        int bytes;

        // 首次启动时就开始计时
        mTimeoutHandler.postDelayed(mTimeoutRunnable, 10000);

        while (mState == STATE_CONNECTED) {
            try {
                // Read from the InputStream
                bytes = mmInStream.read(buffer);

                // 收到数据,重置超时任务
                mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
                mTimeoutHandler.postDelayed(mTimeoutRunnable, 10000);

                // Send the obtained bytes to the UI Activity
                mHandler.obtainMessage(Constants.MESSAGE_READ, bytes, -1, buffer)
                        .sendToTarget();
            } catch (IOException e) {
                Log.e(TAG, "disconnected ~ " + e.toString());
                // 连接断开时移除超时任务
                mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
                connectionLost();
                break;
            }
        }
    }

    // 新增方法:当线程销毁时清理超时任务
    public void cancel() {
        mTimeoutHandler.removeCallbacks(mTimeoutRunnable);
        try {
            mmSocket.close();
        } catch (IOException e) {
            Log.e(TAG, "close() of connect socket failed", e);
        }
    }
}

3. 在MyActivity中处理超时消息并触发震动

修改MyActivity的mHandler,新增MESSAGE_TIMEOUT的处理逻辑:

private final Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        switch (msg.what) {
            case Constants.MESSAGE_READ:
                // 原有处理逻辑不变
                byte[] readBuf = (byte[]) msg.obj;
                String readMessage = new String(readBuf, 0, msg.arg1);
                mConversationArrayAdapter.add(mConnectedDeviceName + ":  " + readMessage);
                isReceived = !TextUtils.isEmpty(readMessage.trim());
                Log.d(TAG, "mHandler - MESSAGE_READ - isReceived = " + isReceived);
                break;
            case Constants.MESSAGE_DEVICE_NAME:
                // 原有处理逻辑不变
                mConnectedDeviceName = msg.getData().getString(Constants.DEVICE_NAME);
                Toast.makeText(getApplicationContext(), "Connected to "
                        + mConnectedDeviceName, Toast.LENGTH_SHORT).show();
                break;
            case Constants.MESSAGE_TIMEOUT:
                // 触发震动提醒
                Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
                if (vibrator != null && vibrator.hasVibrator()) {
                    // 震动500毫秒,可根据需求调整时长
                    vibrator.vibrate(500);
                }
                break;
        }
    }
};

4. 添加震动权限

在AndroidManifest.xml中添加震动权限:

<uses-permission android:name="android.permission.VIBRATE" />

关键疑问解答

  • 为什么不在MyActivity的mHandler中处理超时?
    mHandler仅在收到蓝牙数据时被回调,无法主动检测"未收到数据"的状态,必须依赖独立的定时监控机制。

  • 如何持续监控10秒内的数据接收状态?
    通过Handler.postDelayed()启动10秒延迟任务,每次收到数据时调用removeCallbacks()取消原有任务并重新启动新的延迟任务,确保只有连续10秒无数据时才触发超时。

  • BtClientService如何通知MyActivity?
    是的,通过BtClientService中已有的mHandler(用于发送MESSAGE_READ的Handler)发送自定义的MESSAGE_TIMEOUT消息即可,该Handler绑定UI线程Looper,能直接在MyActivity中处理。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.17 00:30:01