Android蓝牙SPP - 如何停止传输内部发送缓冲区?
问题描述:
我试图使用Android SPP蓝牙套接字接口实时控制/操作来自Android手机的电机。电机应该以所谓的“死人”运行模式运行。所以只有当android APP上的按钮被触摸时,电机才会转动,如果触摸被释放,应该立即停止。Android蓝牙SPP - 如何停止传输内部发送缓冲区?
我通过每20ms不断发送20个字节的“保持转动”报文来实现此目的,以保持电机转动,并且一旦没有收到更多报文或收到停止报文,马达立即停止。
这似乎在某些电话上可以正常工作,但其他人在处理完MotionEvent.ACTION_UP事件并且没有更多数据正在发送之后仍继续发送'继续转动'报文。
我认为这是由一些内部缓冲区引起的,这些缓冲区会缓存发送数据并继续发送,直到缓冲区为空。
简单的问题:
- 有没有办法来清除BT流的发送缓冲区立即停止所有的数据传输?
- 或者我可以得到发送缓冲区的填充水平,在这种情况下,我不会把大约2个电报放入其中?
- 或者有没有办法指定打开流时的缓冲区大小?
在网络搜索中,我找不到任何关于缓冲区管理的BT流缓冲区大小的内容。
是的,我已经将读写功能实现为线程,并且在读取所有电报时没有任何问题,并且我不需要实时发送电报,但是我应该能够停止发送“继续转动'在大约50到100毫秒内发送电报。
任何提示都非常受欢迎。
答
我很抱歉,我没有添加代码,我认为它是直线前进,因为它可能没有必要:
@Override
public boolean onTouch(final View v,MotionEvent event) {
int eventAction = event.getAction();
switch (eventAction) {
case MotionEvent.ACTION_DOWN:
if (v == btnUp || v == btnDown) {
// Start a thread that sends the goUP or DOWN command every 10 ms until
// btnUp released
tvCounter.setText("----");
action_touched = true;
new Thread(new Runnable() {
@Override
public void run() {
int counter = 1;
// Disable heart beat
ServiceRequest.send(EnRequest.REQ_SET_HEARTBEAT,0);
// Send GoUp command plus a wrapping counter byte every nn ms
// until the button is released
while (action_touched) {
try {
setDeadmanMove(v==btnUp,counter);
Thread.sleep(20);
++counter;
}
catch (InterruptedException ex) {
action_touched = false;
}
catch (Exception ex) {
action_touched = false;
}
}
// Send a STOP command
setDeadmanStop();
// Enable heart beat again
ServiceRequest.send(EnRequest.REQ_SET_HEARTBEAT,1);
// We are done
}
}).start();
}
break;
case MotionEvent.ACTION_UP:
// Stop Thread
action_touched = false;
break;
}
return true;
}
下剪掉是管理蓝牙串行通信类的一部分通讯。
public void btWrite(DeviceRecord message) {
if (runBTreceiver) {
if (message.isValidRecord()) {
try {
lock.lock();
++lockCounter;
mmBufferedOut.write(message.getFullRecord());
mmBufferedOut.flush();
}
catch (IOException e) {
if (GlobalData.isDebugger) Log.i(TAG, "Failed sending " + message + " " + e.getMessage());
ServiceResponse.send(EnEvent.EVT_BT_RECEIVER_ERROR, "Error data send: " + e.getMessage());
resetConnection();
runBTreceiver=false;
}
finally {
--lockCounter;
lock.unlock();
}
}
}
}
代码剪断,其分配并打开蓝牙连接
try {
// Set up a pointer to the remote node using it's address.
BluetoothDevice device = myBluetoothAdapter.getRemoteDevice(myBluetoothMacId);
if (device != null)
{
// Two things are needed to make a connection:
// A MAC address, which we got above.
// A Service ID or UUID. In this case we are using the
// UUID for SPP.
try {
myBluetoothSocket = device.createRfcommSocketToServiceRecord(GlobalData.MY_UUID);
}
catch (IOException e) {
sendEventStatus(EnEvent.EVT_BTADAPTER_FAIL,
String.format(GlobalData.rString(R.string.srv_failcrt),BTERROR_CREATE,e.getMessage()));
}
// Establish the connection. This will block until it connects or
// timeout?
try {
if (! myBluetoothSocket.isConnected()) {
myBluetoothSocket.connect();
}
}
catch (IOException e) {
try {
Log.e("","trying fallback...");
myBluetoothSocket =(BluetoothSocket) device.getClass().getMethod("createRfcommSocket", new Class[] {int.class}).invoke(device,1);
myBluetoothSocket.connect();
}
catch (IOException e2) {
sendEventStatus(EnEvent.EVT_BTADAPTER_FAIL,e2.getMessage());
}
}
}
else {
sendEventStatus(EnEvent.EVT_BTADAPTER_FAIL,
String.format(GlobalData.rString(R.string.srv_failcrt),BTERROR_DEVICE,"getRemoteDevice failed"));
}
}
catch (Exception e) {
sendEventStatus(EnEvent.EVT_BTADAPTER_FAIL, e.getMessage());
return;
}
InputStream tmpIn = null;
OutputStream tmpOut = null;
mmSocket = socket;
// Get the input and output streams, using temp objects because
// member streams are final
try {
tmpIn = socket.getInputStream();
tmpOut = socket.getOutputStream();
}
catch (IOException e) {
ServiceResponse.send(EnEvent.EVT_ERROR, GlobalData.rString(R.string.srv_failcst) + e.getMessage());
resetConnection();
runBTreceiver=false;
}
mmInStream = tmpIn;
// mmOutStream = tmpOut;
mmBufferedOut = new BufferedOutputStream(tmpOut,80);
// Initial request
btWrite(new DeviceRecord(0, 4));
我从来没有发现任何问题发送,并通过该代码接收数据。所有记录都正确发送和接收。唯一的问题是我无法在释放操作按钮时清除发送缓冲区。
为了解决这个问题,我改变了协议,一次只发送一个“保持转动”的电报,下一个电报将在另一端的响应后发送握手),然后程序继续运行这个ping/pong直到按钮被释放。 此方法工作得很好,因为发送缓冲区一次不会保存多个报文。
提到的问题虽然解决了,但我仍然没有它是否有可能清除发送缓冲器
这是一个非常不可能的问题没有真正看到你的代码来回答的线索。我们不知道你实际在做什么(而不是你想做什么),所以我们不能告诉你,如果你做错了什么。 – 2015-01-09 18:48:00