android开发SPP经典蓝牙
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了android开发SPP经典蓝牙相关的知识,希望对你有一定的参考价值。
参考技术A android 开发SPP经典蓝牙。1、传统蓝牙采用的是SPP(Serial Port Profile)协议进行数据传输。
2、SPP的UUID:00001101-0000-1000-8000-00805F9B34FB
3、手机一般以客户端的角色主动连接SPP协议设备
概念:
BluetoothAdapter:
本地蓝牙适配器,是所有蓝牙交互的入口,表示蓝牙设备自身的一个蓝牙适配器,整个系统只有一个蓝牙适配器,通过他可以发现其他蓝牙设备,查询绑定(配对)设备列表,使用MAC地址实例化BluetoothDevice以及创建BluetoothServerSocket用来侦听来自其他设备的通信。
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//获取默认的蓝牙Adapter
BluetoothDevice:
远程的蓝牙设备。
private static BluetoothDevice myDevice;
myDevice = myBluetoothAdapter.getRemoteDevice(BDAddr);//获取远程设备,通过蓝牙的MAC地址来获取一个远程对象
两种连接方式
BluetoothSocket
客户端:调用BluetoothDevice的createRfcommSocketToServiceRecord()可以获取该对象;调用connect()方法可以建立连接。
private static BluetoothSocket mySocket = null;
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Method m = myDevice.getClass().getMethod("createRfcommSocket", new Class[] int.class);//由BluetoothDevice衍生出BluetoothSocket, createRfcommSocket来选择连接的服务和协议
mySocket = (BluetoothSocket) m.invoke(myDevice, 1);
BluetoothServerSocket:
服务端:通过BluetoothServerSocket对象可以创建BluetoothSocket对象,调用BluetoothServerSocket的accept()的方法可以得到改对象。
开发流程:
1:声明权限:
<uses-permission android:name="android.permission.BLUETOOTH"/>
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN"/>
2:启动和关闭蓝牙
获取蓝牙适配器,使用close()接口可以关闭蓝牙适配器
myBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();//获取默认的蓝牙Adapter
启动蓝牙
if (!blueadapter.isEnabled())
//判断本机蓝牙是否打开
//如果没打开,则打开蓝牙
blueadapter.enable();
3.使用BlueAdatper搜索
使用bluetoothAdapter搜索设备,bluetoothAdapter.startDiscovery()在搜索过程中,系统会发出三个广播信息:
ACTION_DISCOVERY_START:开始搜索
ACTION_DISCOVERY_FINISHED:搜索结束
ACTION_FOUND:找到设备
if (bluetoothAdapter.isDiscovering())
bluetoothAdapter.cancelDiscovery();//如果蓝牙设备未连接则取消搜索
bluetoothAdapter.startDiscovery();
4:(1)通过注册广播获取搜索到的设备。
IntentFilter intentFilter = new IntentFilter();
intentFilter.addAction(BluetoothDevice.ACTION_FOUND);//找到设备广播
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);//搜索完成广播
registerReceiver(receiver, intentFilter);//注册广播接收器
// receiver
private final BroadcastReceiver receiver = new BroadcastReceiver()
@Override
public void onReceive(Context context, Intent intent)
String action = intent.getAction();
if (BluetoothDevice.ACTION_FOUND.equals(action))
// find a device
BluetoothDevice device = intent .getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
if (device.getBondState() != BluetoothDevice.BOND_BONDED)
//未配对设备
newDeviceArrayAdapter.add(device.getName() + "\n" + device.getAddress());
else
//已经配对过的设备
TextView tvPaired = (TextView)findViewById(R.id.tv_paired);
tvPaired.setVisibility(View.VISIBLE);
lvPairedDevices.setVisibility(View.VISIBLE);
pairedDeviceArrayAdapter.add(device.getName() + "\n" + device.getAddress());
Log.i(TAG,"name:" + device.getName() + " address"+ device.getAddress());
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED.equals(action)
// search finish
Log.i(TAG, "search finish!");
;
(2),直接得到当前的蓝牙设备后,就可用通过遍历pairedDevices ,得到当前手机已经配对过的蓝牙设备。
Set<BluetoothDevice> pairedDevices = myBluetoothAdapter.getBondedDevices();//获取当前蓝牙设备
if (pairedDevices.size() <= 0) return false;
for (BluetoothDevice device : pairedDevices)
Map<String, String> map = new HashMap<String, String>();
map.put("DeviceName", device.getName());
map.put("BDAddress", device.getAddress());
list.add(map);
5.建立连接
private static final UUID SPP_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
Method m = myDevice.getClass().getMethod("createRfcommSocket", new Class[] int.class);//由BluetoothDevice衍生出BluetoothSocket, createRfcommSocket来选择连接的服务和协议
mySocket = (BluetoothSocket) m.invoke(myDevice, 1);
mySocket.connect();//使用BluetoothSocket来连接设备
6.把得到的蓝牙设备给通过点击ListView选择设备。
listView.setOnItemClickListener(new ListView.OnItemClickListener()
public void onItemClick(AdapterView<?> arg0, View arg1, int arg2, long arg3)
SelectedBDAddress = list.get(arg2).get("BDAddress");
if (((ListView) arg0).getTag() != null)
((View) ((ListView) arg0).getTag()).setBackgroundDrawable(null);
((ListView) arg0).setTag(arg1);
arg1.setBackgroundColor(Color.BLUE);
myDevice = myBluetoothAdapter.getRemoteDevice(SelectedBDAddress);
);
7.客户端发送数据
当两个设备成功连接之后,双方都会有一个BluetoothSocket对象,这时,就可以在设备之间传送数据了。
1.使用getOutputStream()方法来获取输出流来处理传输。
2.调用write()。
os = socket.getOutputStream();//获取输出流
if (os != null) //判断输出流是否为空
os.write(message.getBytes("UTF-8"));
os.flush();//将输出流的数据强制提交
os.close();//关闭输出流
将输出流中的数据提交后,要记得关闭输出流,否则,可能会造成只能发送一次数据。
8.服务端接收数据
1.使用getInputStream()方法来获取输入流来处理传输。
2.调用read()。
InputStream im=null;
im=bluetoothSocket.getInputStream();
byte buf[] = new byte[1024];
if (is != null)
is.read(buf, 0, buf.length);//读取发来的数据
String message = new String(buf);//把发来的数据转化为String类型
BuletoothMainActivity.UpdateRevMsg(message);//更新信息在显示文本框
is.close();//关闭输入流
使用服务端接收数据时,要先从客户端向服务端发起连接,只有接收到连接请求之后,才会返回一个BluetoothSocket对象。有BluetoothSocket对象才能获取到输入流。
Android 上的实时蓝牙 SPP 数据流仅工作 5 秒
【中文标题】Android 上的实时蓝牙 SPP 数据流仅工作 5 秒【英文标题】:Real-time Bluetooth SPP data streaming on Android only works for 5 seconds 【发布时间】:2014-12-01 13:47:30 【问题描述】:我有一个自制的蓝牙设备以 500Hz 测量心电图:设备每 2 毫秒发送 9 个字节的数据(页眉、心电图测量、页脚)。所以这大概是一个 9*500=4.5kbytes/s 的数据流。
我有一个 C++ Windows 程序能够连接设备并检索数据流(使用 Qt/qwt 显示它)。在这种情况下,我使用 Windows 控制面板来绑定设备,并使用 boost serial_port 接口通过虚拟 COM 端口连接它。这非常有效,我正在实时接收我的数据流:我每 2 毫秒左右得到一个测量点。
我通过 QtCreator (Qt 5.3.2) 将整个 C++ 程序移植到 Android 上。我遇到了实时问题。数据流在前 5 秒内处于“实时”状态,然后性能会急剧下降(请参阅 How to do good real-time data streaming using Java Android SDK)。
因为我认为问题可能是由于 C++/Qt,我使用 Eclipse 编写了一个完全空白的纯 Java/Android 项目。也有同样的问题!!!
问题是:这段代码有问题吗?为什么我只能在前 5 秒实时接收数据?在 Android 平台上密集使用 BT 5 秒后会发生什么,为什么会减慢 BT 数据接收速度?
这是我的 Java 程序:
BluetoothHelper.java(具有连接/断开/读取和写入数据的功能:
package com.example.helloworld;
import android.util.Log;
import android.content.Context;
import android.os.Bundle;
import java.util.Locale;
import java.util.concurrent.Semaphore;
import java.lang.String;
import java.lang.Thread;
import java.io.IOException;
import java.io.OutputStream;
import java.io.InputStream;
import java.text.SimpleDateFormat;
import java.lang.InterruptedException;
import android.app.Activity;
import android.app.AlertDialog;
import android.bluetooth.BluetoothAdapter;
import android.bluetooth.BluetoothDevice;
import android.bluetooth.BluetoothSocket;
import android.bluetooth.BluetoothManager;
import android.util.SparseArray;
import android.content.Intent;
import android.content.IntentFilter;
import android.content.BroadcastReceiver;
import java.util.UUID;
import java.util.Date;
import java.util.Calendar;
import java.util.Vector;
import java.util.Set;
import java.util.Arrays;
public class BluetoothHelper
private BluetoothManager mBluetoothManager;
private BluetoothAdapter mBluetoothAdapter;
private BluetoothDevice mDevice;
private BluetoothSocket mSocket;
private OutputStream mOutputStream;
private InputStream mInputStream;
private BroadcastReceiver mReceiver;
private Activity myActivity;
private Vector<BluetoothDevice> mDevices;
private byte[] mHeader;
private byte[] mFrame;
public BluetoothHelper(Activity a)
myActivity = a;
mHeader = new byte[3];
mFrame = new byte[256];
mDevices = new Vector();
/* Check bluetooth is enabled, return "" if OK, else, return error string */
public String initializeBluetooth()
String error = "";
System.out.println("Initializing bluetooth...");
mBluetoothManager = (BluetoothManager) myActivity.getSystemService(Context.BLUETOOTH_SERVICE);
if ( mBluetoothManager == null )
error = "Bluetooth manager is not found";
else
mBluetoothAdapter = mBluetoothManager.getAdapter();
if( mBluetoothAdapter == null )
error = "Bluetooth adapter is not found";
else if( ! mBluetoothAdapter.isEnabled() )
error = "Bluetooth adapter is off";
else
System.out.println("Bluetooth successfully initialized");
return "";
return error;
private void addDevice( final BluetoothDevice device )
mDevices.add(device);
public Vector<BluetoothDevice> getDevices() return mDevices;
/* Clear previously detected device list */
public boolean clearDeviceList()
// Clear old list
mDevices.clear();
return true;
/* Fill local device list with paired devices */
public boolean addPairedDevices()
//System.out.println("Entering addPairedDevices");
if( mBluetoothAdapter == null )
System.out.println("No bluetooth adapter");
return false;
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0)
//System.out.println("Found paired devices");
// Loop through paired devices
for (BluetoothDevice device : pairedDevices)
addDevice( device );
return true;
public String connectToDevice(final BluetoothDevice device)
if ( mDevice != null )
disconnectDevice();
if( mBluetoothAdapter == null || myActivity == null )
return "System not initialized or bluetooth not active";
if ( device.getBondState() != BluetoothDevice.BOND_BONDED )
// TODO: find a way to do a synchronized bounding operation
return "Device is not bonded";
final boolean[] the_result = new boolean[1];
the_result[0] = false;
final Semaphore mutex = new Semaphore(0);
Runnable connectRunnable = new Runnable()
@Override
public void run()
UUID MY_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
try
mSocket = device.createInsecureRfcommSocketToServiceRecord( MY_UUID );
System.out.println("Created RFcomm socket");
mSocket.connect();
if ( mSocket.isConnected() )
System.out.println("Connected RFcomm socket");
mOutputStream = mSocket.getOutputStream();
mInputStream = mSocket.getInputStream();
System.out.println("Retrieved output stream");
the_result[0] = true;
else
System.out.println("Failed to connect RFcomm socket");
catch (IOException e)
System.out.println("Failed to open RFcomm socket (createRfcommSocketToServiceRecord)");
System.out.println(e.toString());
mutex.release();
;
myActivity.runOnUiThread( connectRunnable );
// waiting for thread to be completed...
try
mutex.acquire();
catch (InterruptedException e)
e.printStackTrace();
if ( the_result[0] )
System.out.println("Connection succeeded");
return "";
else
System.out.println("Connection failed");
return "Failed to connect device";
/* Request to disconnect the device */
public boolean disconnectDevice()
System.out.println("Disconnecting device...");
if ( mSocket != null )
// block read/write
mOutputStream = null;
mInputStream = null;
try
mSocket.close();
catch( IOException e )
e.printStackTrace();
return false;
mSocket = null;
mDevice = null;
return true;
/* Send bytes to the connected device */
public boolean writeData( byte[] buffer )
if( mOutputStream == null )
System.out.println("No connection, can't send data");
else
try
mOutputStream.write( buffer );
return true;
catch (IOException e)
System.out.println( "Failed to send data" );
e.printStackTrace();
return false;
public static String byteArrayToHex(byte[] a, int size)
StringBuilder sb = new StringBuilder(size * 5);
for( int i = 0; i != size; ++i )
sb.append(String.format("0x%02x ", a[i] & 0xff));
return sb.toString();
public int getBytesPending()
try
return mInputStream.available();
catch (IOException e)
return 0;
/* Non blocking read function. Read bytes from the connected device.
* Return number of bytes read
* return 0 if not enough bytes available
* return -1 in case of error
*/
public int readData( byte[] buffer, int size, boolean blocking )
if ( mInputStream == null )
System.out.println("No connection, can't receive data");
else
try
final boolean verbose = false;
if ( blocking )
if ( verbose )
System.out.println( "Blocking request of " + buffer.length + " byte(s)" );
int res = 0;
int temp = 0;
while ( true )
temp = mInputStream.read( buffer, res, size - res );
res += temp;
if ( res >= size )
break;
else
if ( verbose )
System.out.println( "Received " + res + " byte(s) to far : " + byteArrayToHex(buffer,size) );
try
Thread.sleep(10);
catch(InterruptedException ex)
if ( verbose )
System.out.println( "Received " + res + " byte(s) : " + byteArrayToHex(buffer,size) );
return res;
else
int available = mInputStream.available();
if ( verbose && available != 0 )
Calendar c = Calendar.getInstance();
Date date = new Date();
c.setTime(date);
c.get(Calendar.MILLISECOND);
SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
String currentTime = sdf.format(date);
System.out.println( currentTime + ":" + c.get(Calendar.MILLISECOND) + " - " + available + " bytes available, requested " + buffer.length );
if ( available >= size )
int res = mInputStream.read( buffer, 0, size ); // only call read if we know it's not blocking
if ( verbose )
System.out.println( "Received " + res + " byte(s) : " + byteArrayToHex(buffer,size) );
return res;
else
return 0;
catch (IOException e)
System.out.println( "Failed to read data...disconnected?" );
//e.printStackTrace();
return -1;
public byte[] readNextFrame( boolean blocking )
if ( readData( mHeader, mHeader.length, blocking ) == mHeader.length )
int size = mHeader[2];
if ( size < 0 )
size = -size;
if ( readData( mFrame, size, blocking ) == size )
byte[] res = new byte[mHeader.length + size];
System.arraycopy(mHeader, 0, res, 0, mHeader.length);
System.arraycopy(mFrame, 0, res, mHeader.length, size);
return res;
return null;
*/ read frame but without allocating any memory, does not retur condumed bytes */
public boolean eatNextFrame( boolean blocking )
if ( readData( mHeader, mHeader.length, blocking ) == mHeader.length )
int size = mHeader[2];
if ( size < 0 )
size = -size;
if ( readData( mFrame, size, blocking ) == size )
return true;
return false;
public boolean startECG()
// some code sending instructions to configure my device
主 Java 文件,连接并进行 10 秒采集:
// Here is the code for Medoc:
BluetoothHelper helper = new BluetoothHelper(this);
String error = helper.initializeBluetooth();
if ( error.isEmpty() )
if ( helper.addPairedDevices( ) )
if ( !helper.getDevices().isEmpty() )
if ( helper.getDevices().size() == 1 )
BluetoothDevice device = helper.getDevices().firstElement();
error = helper.connectToDevice( device );
if ( error.isEmpty() )
if ( helper.startECG() )
// acquiere data for 10 seconds
Date start = new Date();
Date end = new Date();
Date empty = null;
int lastMinute = 0;
int maxBufferSize = 0;
boolean receivedData = false;
while ( end.getTime() - start.getTime() < 10 * 1000 )
int currentMinute = (int) (( end.getTime() - start.getTime() ) / 1000);
if ( currentMinute != lastMinute )
if ( receivedData )
System.out.println( "During second #" + lastMinute + " max buffer size was : " + maxBufferSize );
else
System.out.println( "During second #" + lastMinute + " no data was received!" );
maxBufferSize = 0;
receivedData = false;
lastMinute = currentMinute;
if ( helper.eatNextFrame(false) )
receivedData = true;
if ( helper.getBytesPending() == 0 )
if ( empty == null )
empty = new Date();
else
if ( empty != null )
Date now = new Date();
int elapsed = (int) ( now.getTime() - empty.getTime() );
if ( elapsed > 100 )
System.out.println( "No pending data, during " + elapsed + "ms" );
empty = null;
maxBufferSize = Math.max( helper.getBytesPending(), maxBufferSize );
end = new Date();
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
dlgAlert.setMessage( "Done" );
dlgAlert.setPositiveButton("Ok",null);
dlgAlert.create().show();
else
error = "Failed to start ECG";
helper.disconnectDevice();
else
error = "Too many devices found";
else
error = "No device found";
else
error = "Failed to scan for devices";
if ( !error.isEmpty() )
AlertDialog.Builder dlgAlert2 = new AlertDialog.Builder(this);
dlgAlert2.setMessage( error );
dlgAlert2.setPositiveButton("Ok",null);
dlgAlert2.create().show();
这里是程序的输出:
12-01 14:12:51.755: I/System.out(15940): During second #0 max buffer size was : 63
12-01 14:12:52.755: I/System.out(15940): During second #1 max buffer size was : 133
12-01 14:12:53.755: I/System.out(15940): During second #2 max buffer size was : 66
12-01 14:12:54.755: I/System.out(15940): During second #3 max buffer size was : 61
12-01 14:12:55.755: I/System.out(15940): During second #4 max buffer size was : 129
12-01 14:12:56.705: I/System.out(15940): No pending data, during 501ms
12-01 14:12:56.755: I/System.out(15940): During second #5 max buffer size was : 939
12-01 14:12:57.755: I/System.out(15940): During second #6 max buffer size was : 980
12-01 14:12:58.755: I/System.out(15940): During second #7 max buffer size was : 1008
12-01 14:12:59.195: I/System.out(15940): No pending data, during 488ms
12-01 14:12:59.695: I/System.out(15940): No pending data, during 489ms
12-01 14:12:59.755: I/System.out(15940): During second #8 max buffer size was : 990
12-01 14:13:00.185: I/System.out(15940): No pending data, during 490ms
12-01 14:13:01.205: I/System.out(15940): Disconnecting device...
如您所见,在最初的 5 秒内,读取缓冲区仍然很小,并且没有任何时刻缓冲区为空超过 100 毫秒(请参阅输出“无待处理数据”的代码)。然后,从第五秒开始我们:
即使我的设备永久向 Android 发送数据,读取缓冲区仍为空(InputStream::available() 返回 0)的时间很长(约 500 毫秒)。 可以看到缓冲区最大大小显着增长。在数据采集的前 5 秒之后,就好像数据在某处被缓冲,并且可以在 InputStream 中以大约 500 毫秒的块读取......
有时,情况可能更糟,5 秒后根本没有接收到数据:
12-01 14:35:54.595: I/System.out(16386): During second #0 max buffer size was : 22
12-01 14:35:55.595: I/System.out(16386): During second #1 max buffer size was : 93
12-01 14:35:56.595: I/System.out(16386): During second #2 max buffer size was : 108
12-01 14:35:57.595: I/System.out(16386): During second #3 max buffer size was : 61
12-01 14:35:58.595: I/System.out(16386): During second #4 max buffer size was : 64
12-01 14:35:59.595: I/System.out(16386): During second #5 max buffer size was : 63
12-01 14:36:00.595: I/System.out(16386): During second #6 no data was received!
12-01 14:36:01.595: I/System.out(16386): During second #7 no data was received!
12-01 14:36:02.595: I/System.out(16386): During second #8 no data was received!
注意:在创建BluetoothHelper
和调用startECG()
之前,我尝试睡几秒钟。相同的行为(采集速度减慢或在 5 秒后停止)。
编辑:我正在经历这种情况:
Nexus 5 手机,Android 4.4.2 Nexus 7 平板电脑,Android 4.4.2 搭载 Android 4.4.2 的 Galaxy S4但不是在带有自定义 CyanogenMod 11 Android 4.4.2 的 Galaxy S3 上:数据流看起来很完美,5 秒后没有冻结并且数据实时到达......
12 月 15 日编辑:
按照建议,将读取移至单独的线程:
使 BluetoothHelper
实现 Runnable
并将这些方法/属性添加到类中:
private int mFramesReceived;
private long mLongestPause;
public void clearReceived()
mFramesReceived = 0;
mLongestPause = 0;
public int received()
return mFramesReceived;
public long longestPause()
return mLongestPause;
@Override
public void run()
System.out.println( "Started thread" );
int lastSeconde = 0;
long currentTimeMillis = System.currentTimeMillis();
long started = System.currentTimeMillis();
// Keep listening to the InputStream until an exception occurs
while (true)
if ( eatNextFrame( true ) )
//System.out.println( "Got some data" );
mLongestPause = Math.max( mLongestPause, System.currentTimeMillis() - currentTimeMillis );
currentTimeMillis = System.currentTimeMillis();
mFramesReceived++;
int currentSeconde = (int) (( System.currentTimeMillis() - started ) / 1000);
if ( currentSeconde != lastSeconde )
if ( mFramesReceived != 0 )
System.out.println( "During second #" + lastSeconde + " max pause was : " + mLongestPause );
else
System.out.println( "During second #" + lastSeconde + " no data was received!" );
clearReceived();
lastSeconde = currentSeconde;
else
System.out.println( "Failed to get some data, connection closed?" );
break;
然后将调用者更改为:
if ( helper.startECG() )
new Thread(helper).start();
try
Thread.sleep(10000); // wait 10 seconds
catch(InterruptedException ex)
Thread.currentThread().interrupt();
AlertDialog.Builder dlgAlert = new AlertDialog.Builder(this);
dlgAlert.setMessage( "Done" );
dlgAlert.setPositiveButton("Ok",null);
dlgAlert.create().show();
else
error = "Failed to start ECG";
helper.disconnectDevice();
它并没有解决问题,这是输出:
During second #0 max pause was : 48
During second #1 max pause was : 45
During second #2 max pause was : 33
During second #3 max pause was : 35
During second #4 max pause was : 58
During second #5 max pause was : 498
During second #6 max pause was : 477
During second #7 max pause was : 480
During second #8 max pause was : 986
During second #9 max pause was : 497
【问题讨论】:
这可能会有所帮助:***.com/questions/27274766/… 查看答案。 不敢相信,这解决了我的问题。每秒发送一个虚拟的“keep-alive”命令使连接和数据流完全稳定!请发布一个真实的答案,以便我可以将其标记为“好答案”! 您可以将其添加为(自己的)接受的答案,这样会更明显 @tomash:我原以为 Tupelo Honey 会这样做(然后赢得一些声誉),但他没有这样做,而且正如你所建议的那样,我做到了。你是对的,它会使解决方案更加明显。 【参考方案1】:这个问题显然与here 报告的问题相似。
5 秒后,我要么失去了连接,要么是实时流显着变慢了。
正如hereAndroid >4.3 所说,显然不喜欢超过 5 秒的单向通信。所以我现在每 1 秒向设备发送一个虚拟命令(一种“保持活动”命令),现在 Android 很高兴,因为它不再是单向通信......比之前的第五秒!
【讨论】:
【参考方案2】:使用线程概念在外围设备上同时读取和写入字节。使用安卓蓝牙数据传输示例解决问题。您正在使用普通的 java 类向另一个无效方法的设备发送和接收数据。您应该使用线程概念通过蓝牙发送和接收数据。
请参考以下链接以通过蓝牙读取和写入数据。
http://developer.android.com/guide/topics/connectivity/bluetooth.html
【讨论】:
感谢您的帮助,但是,正如我对 stacher 所说,它不能解决问题(请参阅我原帖末尾的编辑) 你试过android开发者链接上给出的例子吗? 当然,复制/粘贴代码并使用new Thread( new ConnectedThread( mSocket )).start();
启动线程,在其中添加时间跟踪代码,并注意到两个read
函数返回之间的时间在5 日之后从~35ms 移动到~500ms第二次收购。【参考方案3】:
您不应依赖InputStream.available()
来判断流中有多少字节可用(有关详细信息,请参阅https://developer.android.com/reference/java/io/InputStream.html#available())。
由于您知道数据包的确切大小(9 个字节),因此每次将 9 个字节读入缓冲区:mInputStream.read(buffer, 0, 9)
。
使用蓝牙很难保证实时二进制传输,因为延迟的原因可能有很多(例如设备之间的距离增加、障碍物等)。因此,最好经常调用read
并将检索到的数据部分转发给处理组件。例如,在我的一个项目中,我实现了 Android Service
等待来自蓝牙的数据包并用接收到的数据通知 UI。您可以为此实现Service
或AsyncTask
。
另一个建议:避免在您经常调用的方法中进行不必要的内存分配(例如readData
)。您可以使用System.currentTimeMillis()
测量经过的时间。垃圾收集可能是您遇到性能下降的原因之一。
【讨论】:
感谢您的建议。我刚刚将读取数据的代码移到了单独的Thread
中的while 循环中,并确保在循环中没有分配任何数据。我使用了阻塞read
函数并输出了read
函数的两次返回之间经过的时间。它没有解决问题....在 5 秒内两次读取之间经过的最大时间约为 40 毫秒,在第 5 秒后,它在 500 毫秒和几乎 1000 毫秒之间....
我对我的原始帖子进行了编辑以显示线程实现和结果...以上是关于android开发SPP经典蓝牙的主要内容,如果未能解决你的问题,请参考以下文章