Linux蓝牙找不到带有UUID的Android服务

Posted

技术标签:

【中文标题】Linux蓝牙找不到带有UUID的Android服务【英文标题】:Linux Bluetooth not finding Android Service with UUID 【发布时间】:2011-05-02 11:49:17 【问题描述】:

我正在尝试在运行 GUMSTIX(Linux) 的嵌入式系统上编写一个程序,以通过蓝牙连接 android 2.x 设备并与之对话。 GUMSTIX 是客户端,Android 是服务器。我正在尝试查找我的 Android 服务使用的频道号,以便 GUMSTIX 可以连接到它,但由于某种原因,我的例程没有返回频道号,因为它似乎没有找到具有匹配 UUID 的服务。

我怀疑提供给 GUMSTIX 例程的 UUID 和 Android 设备上的 UUID 实际上不是同一个数字。 Android 需要 128 位 UUID:

来自Android Documentation:

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(接受连接)、ConnectThread(完成连接)和ConnectedThread(维护连接,建立处理程序)的Android代码

/**
 * 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

【问题讨论】:

【参考方案1】:

您是否有任何 UUID 0 , 0 , 0 , 0xABCD 在 Android 设备上运行的服务(通常通过 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.

**

【讨论】:

据我所知,我已经这样做了。如果你想看看,我在上面添加了一些 Android 代码。谢谢你的回答。 您是否已将默认聊天应用程序中 MY_UUID 的值更改为 // 此应用程序的唯一 UUID private static final UUID MY_UUID = UUID.fromString("fa87c0d0-afac-11de-8a39-0800200c9a66") ; to UUID MY_UUID = UUID.fromString("0-0-0-abcd") 不,我没有尝试过像 UUID.fromString("0-0-0-abcd") 那样做。我什至没有想过要尝试。我没有设备,但当我拿到它时,我可以试试。感谢您尝试帮助顺便说一句。

以上是关于Linux蓝牙找不到带有UUID的Android服务的主要内容,如果未能解决你的问题,请参考以下文章

求助,求大神,android与串口通信

Android 市场 - 在没有蓝牙的特定设备上找不到应用程序

Android:蓝牙 UUID 如何工作?

Android 6.0 上的低功耗蓝牙 startScan 找不到设备

Linux mysql 找不到 uuid ,急急急

Android:获取蓝牙设备的uuid