我正在尝试在运行GUMSTIX(Linux)的嵌入式系统上编写程序,以通过蓝牙连接并与Android 2.x设备通信。 GUMSTIX是客户端,Android是服务器。我试图找到我的Android服务使用的频道号码,以便GUMSTIX可以连接到它但由于某种原因,我的例程没有返回频道号,因为它似乎找不到具有匹配UUID的服务。 / p>
我怀疑提供给GUMSTIX例程的UUID和Android设备上的UUID实际上并不是相同的数字。 Android需要128位UUID:
UUID是一个不可变的表示形式 一个128位普遍独特的 标识符(UUID)。
有多种不同的布局 UUID,但这个课程是基于 RFC 4122的变体2,Leach-Salz 变种。这个类可以用来 模型替代变体,但大多数 这些方法将不受支持 那些案件;
查看每种方法
在android中使用的UUID:
public static final String UUID_STRING = "00000000-0000-0000-0000-00000000ABCD";
private static final UUID MY_UUID = UUID.fromString(UUID_STRING);
GUMSTIX中的C代码查找指示失败位置的注释
int main(int argc , char **argv)
{
//Android wants a 128 bit UUID why are we only giving a 32 bit UUID
uint32_t svc_uuid_int[] = { 0 , 0 , 0 , 0xABCD } ;
int status ;
bdaddr_t target ;
uuid_t svc_uuid ;
sdp_list_t *response_list , *search_list , *attrid_list ;
sdp_session_t *session = 0;
uint32_t range = 0x0000ffff ;
uint8_t port = 0;
if(argc < 2)
{
fprintf(stderr , "usage: %s <bt_addr>\n" , argv [ 0 ] ) ;
exit ( 2 ) ;
}
str2ba ( argv[1] , &target ) ;
// connect to the SDP server running on the remote machine
session = sdp_connect ( BDADDR_ANY, &target, SDP_RETRY_IF_BUSY );
// printf("session %u\n",session);
sdp_uuid128_create( &svc_uuid, &svc_uuid_int ) ;
search_list = sdp_list_append( 0, &svc_uuid ) ;
attrid_list = sdp_list_append( 0, &range ) ;
// get a list of service records that have UUID 0xabcd
response_list = NULL ; //ERROR: response_list SHOULD GET INITIALIZED BUT IT STAYS NULL CAUSING THE PROGRAM TO NEVER ENTER THE FOR LOOP BELOW.
status = sdp_service_search_attr_req(session , search_list , SDP_ATTR_REQ_RANGE , attrid_list, &response_list ) ;
printf("status %d\n",status);
if( status == 0 )
{
sdp_list_t *proto_list = NULL ;
sdp_list_t *r = response_list ;
// go through each of the service records
for ( ; r ; r = r->next )
{
sdp_record_t *rec = (sdp_record_t * ) r->data ;
// get a list of the protocol sequences
if( sdp_get_access_protos( rec, &proto_list ) == 0 )
{
// get the RFCOMM port number
port = sdp_get_proto_port( proto_list , RFCOMM_UUID ) ;
sdp_list_free( proto_list, 0 );
}
sdp_record_free( rec ) ;
}
}
sdp_list_free( response_list, 0 );
sdp_list_free( search_list, 0 );
sdp_list_free( attrid_list, 0 );
sdp_close( session ) ;
if( port != 0 )
{
printf( "found service running on RFCOMM port %d\n" , port ) ;
}
return 0;
}
编辑:
acceptThread的Android代码(接受连接),ConnectThread(完成连接)和ConnectedThread(维护连接,建立处理程序)
/**
* This thread runs while listening for incoming connections. It behaves
* like a server-side client. It runs until a connection is accepted
* (or until canceled).
*/
private class AcceptThread extends Thread {
// The local server socket
private final BluetoothServerSocket mmServerSocket;
public AcceptThread() {
BluetoothServerSocket tmp = null;
// Create a new listening server socket
try {
tmp = mAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
} catch (IOException e) {
Log.e(TAG, "listen() failed", e);
}
mmServerSocket = tmp;
}
public void run() {
if (D) Log.d(TAG, "BEGIN mAcceptThread" + this);
setName("AcceptThread");
BluetoothSocket socket = null;
// Listen to the server socket if we're not connected
while (mState != STATE_CONNECTED) {
try {
// This is a blocking call and will only return on a
// successful connection or an exception
if(D) Log.i("prism", "Waiting to connect************");
socket = mmServerSocket.accept();
if(D) Log.i("prism", "We have accepted connection and are connected***************");
} catch (IOException e) {
Log.e(TAG, "accept() failed", e);
break;
}
// If a connection was accepted
if (socket != null) {
synchronized (BluetoothServer.this) {
switch (mState) {
case STATE_LISTEN:
case STATE_CONNECTING:
// Situation normal. Start the connected thread.
connected(socket, socket.getRemoteDevice());
break;
case STATE_NONE:
case STATE_CONNECTED:
// Either not ready or already connected. Terminate new socket.
try {
if (D) Log.i("prism", "Bluetooth already connected, abandoning request from " + socket.getRemoteDevice().getName());
socket.close();
} catch (IOException e) {
Log.e(TAG, "Could not close unwanted socket", e);
}
break;
}
}
}
}
if (D) Log.i(TAG, "END mAcceptThread");
}
public void cancel() {
if (D) Log.d(TAG, "cancel " + this);
try {
mmServerSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of server failed", e);
}
}
}
/**
* This thread runs while attempting to make an outgoing connection
* with a device. It runs straight through; the connection either
* succeeds or fails.
*/
private class ConnectThread extends Thread {
private final BluetoothSocket mmSocket;
private final BluetoothDevice mmDevice;
public ConnectThread(BluetoothDevice device) {
mmDevice = device;
BluetoothSocket tmp = null;
// Get a BluetoothSocket for a connection with the
// given BluetoothDevice
try {
tmp = device.createRfcommSocketToServiceRecord(MY_UUID);
} catch (IOException e) {
Log.e(TAG, "create() failed", e);
}
mmSocket = tmp;
}
public void run() {
Log.i(TAG, "BEGIN mConnectThread");
setName("ConnectThread");
// Always cancel discovery because it will slow down a connection
mAdapter.cancelDiscovery();
// Make a connection to the BluetoothSocket
try {
// This is a blocking call and will only return on a
// successful connection or an exception
Log.i(TAG, "mmSocket.connect() is initiaiting in the ConnectThread");
mmSocket.connect();
Log.i(TAG, "mmSocket.connect() complete...");
} catch (IOException e) {
Log.e(TAG, "Connection attempt failed, closing the socket");
connectionFailed();
// Close the socket
try {
mmSocket.close();
} catch (IOException e2) {
Log.e(TAG, "unable to close() socket during connection failure", e2);
}
// Start the service over to restart listening mode
BluetoothServer.this.start();
return;
}
// Reset the ConnectThread because we're done
synchronized (BluetoothServer.this) {
mConnectThread = null;
}
// Start the connected thread
connected(mmSocket, mmDevice);
}
public void cancel() {
try {
mmSocket.close();
} catch (IOException e) {
Log.e(TAG, "close() of connect socket failed", e);
}
}
}
/**
* This thread runs during a connection with a remote device.
* It handles all incoming and outgoing transmissions.
*/
private class ConnectedThread extends Thread {
private final BluetoothSocket mmSocket;
private final InputStream mmInStream;
private final OutputStream mmOutStream;
public ConnectedThread(BluetoothSocket socket) {
Log.d(TAG, "create ConnectedThread");
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);
}
mmInStream = tmpIn;
mmOutStream = tmpOut;
}
public void run() {
Log.i(TAG, "BEGIN mConnectedThread");
byte[] buffer = new byte[1024];
int bytes;
// Keep listening to the InputStream while connected
while (true) {
try {
// Read from the InputStream
bytes = mmInStream.read(buffer);
// Send the obtained bytes to the UI Activity
mHandler.obtainMessage(Bluetooth.MESSAGE_READ, bytes, -1, buffer)
.sendToTarget();
} catch (IOException e) {
Log.e(TAG, "disconnected", e);
connectionLost();
break;
}
}
}
Android代码来自蓝牙聊天示例here
答案 0 :(得分:3)
您是否在Android设备上运行UUID {0,0,0,01ABCD}的任何服务(通常通过RFCOMM / SPP)?
您可能(以编程方式创建具有指定UUID的服务,并让它在设备上运行以便能够连接到它。
从Android文档引用:
**
public BluetoothServerSocket listenUsingRfcommWithServiceRecord (String name, UUID uuid)
Create a listening, secure RFCOMM Bluetooth socket with Service Record.
A remote device connecting to this socket will be authenticated and communication on this socket will be encrypted.
Use accept() to retrieve incoming connections from a listening BluetoothServerSocket.
The system will assign an unused RFCOMM channel to listen on.
The system will also register a Service Discovery Protocol (SDP) record with the local SDP server containing the specified UUID, service name, and auto-assigned channel. Remote Bluetooth devices can use the same UUID to query our SDP server and discover which channel to connect to. This SDP record will be removed when this socket is closed, or if this application closes unexpectedly.
Use createRfcommSocketToServiceRecord(UUID) to connect to this socket from another device using the same UUID.
**