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
相关产品推荐
相关产品推荐

