android - 如何从 Linux 连接到 Android 蓝牙 socket

标签 android linux sockets bluetooth

我正在尝试创建从 Raspberry Pi 3B (Debian Linux) 到 Android 应用程序的蓝牙连接。我的问题是 Android 框架 (AFAIK) 需要使用 UUID,例如创建 RfcommSocketToServiceRecord(UUID)。代码摘录:

// CREATE SPP SOCKET
mSock = device.createRfcommSocketToServiceRecord( uuid );
if( mSock == null ) {
    return( -1 );
}
// TRY TO CONNECT
mSock.connect();

上面的代码在 Android 到 Android 之间运行良好。

另一方面,Linux 只需要一个“rc channel 号”(整数)。以下是麻省理工学院的一些示例代码:

#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <bluetooth/bluetooth.h>
#include <bluetooth/rfcomm.h>

int main(int argc, char **argv)
{
    struct sockaddr_rc addr = { 0 };
    int s, status;
    char dest[18] = "XX:XX:XX:XX:XX:XX"; // android address here

    // allocate a socket
    s = socket(AF_BLUETOOTH, SOCK_STREAM, BTPROTO_RFCOMM);

    // set the connection parameters (who to connect to)
    addr.rc_family = AF_BLUETOOTH;
    addr.rc_channel = (uint8_t) 1;
    str2ba( dest, &addr.rc_bdaddr );

    // connect to server
    status = connect(s, (struct sockaddr *)&addr, sizeof(addr));

    // send a message
    if( status == 0 ) {
        status = write(s, "hello!", 6);
    }

    if( status < 0 ) perror("uh oh");

    close(s);
    return 0;
}

我不知道如何连接这两个世界。
帮助!

最佳答案

我费了好大劲才让 SDP 开始工作。代码如下。它是根据 https://people.csail.mit.edu/albert/bluez-intro/x604.html 上的示例设计的

这对我来说似乎不必要地复杂。 “疯狂的计算机科学家!”的案例。对于像这样常见和简单的东西,他们应该包含一个方便的包装器。

//  getchan - get channel for specified service

// CONVENIENCE DEFINITIONS TO (IMHO) MAKE CODE MORE READABLE
#define BYTE    uint8_t
#define UUID    uuid_t
#define LIST    sdp_list_t
#define SESSION sdp_session_t
#define RECORD  sdp_record_t
#define DATA    sdp_data_t

#include "stdio.h"
#include "string.h"
#include "ctype.h"
#include "unistd.h"
#include "stdlib.h"
#include "bluetooth/bluetooth.h"
#include "bluetooth/sdp.h"
#include "bluetooth/sdp_lib.h"

#define DEV_ADDR "E4:12:1D:96:10:EF"    // MAC address of service device

main(
  int argc,
  char **argv)
{
    // Server UUID: "d8308c4e-9469-4051-8adc-7a2663e415e2"
    static BYTE uuid[16] = {    // UUID as byte array
      0xd8, 0x30, 0x8c, 0x4e, 0x94, 0x69, 0x40, 0x51,
      0x8a, 0xdc, 0x7a, 0x26, 0x63, 0xe4, 0x15, 0xe2
    };
    int chan;

    chan = GetServiceChannel( uuid );
    if( chan > 0 ) {
      printf( "specified service is on channel %d\n", chan );
    }
    else {
      fprintf( stderr, "  can't find channel\n" );
    }
    exit( 0 );
}

int
GetServiceChannel(
  BYTE *uuid)   // uuid of service as 16 bytes
{
    SESSION *s;
    UUID svc_uuid;
    LIST *response_list,*search_list,*attrid_list,*r;
    RECORD *rec;
    int range;
    int n;
    BYTE addr[6];   // define my own addr type
    int chan=0;

    // CONNECT TO SDP SERVER
    // (Note: device must be ON but server need not be running)
    str2ba( DEV_ADDR, (bdaddr_t *)&addr );
    s = sdp_connect( BDADDR_ANY, (bdaddr_t *)&addr, SDP_RETRY_IF_BUSY );
    if( !s ) {
      fprintf( stderr, "can't connect to sdp server\n" );
      return( 0 );
    }

    // CREATE QUERY LISTS
    sdp_uuid128_create( &svc_uuid, uuid );
    search_list = sdp_list_append( NULL, &svc_uuid );

    range = 0x0000ffff;     // start at 0000, end at ffff
    attrid_list = sdp_list_append( NULL, &range );

    // SEARCH FOR RECORDS
    // (Note: Server must be running)
    n = sdp_service_search_attr_req(
      s, search_list, SDP_ATTR_REQ_RANGE, attrid_list, &response_list );
    if( n ) {
      fprintf( stderr, "search failed.\n" );
      return( 0 );;
    }

    // CHECK IF ANY RESPONSES
    n = sdp_list_len( response_list );
    if( n <= 0 ) {
      fprintf( stderr, "no responses.\n" );
      return( 0 );;
    }

    // PROCESS RESPONSES
    r = response_list;
    while( r ) {            // loop thru all responses
      sdp_record_t *rec;
      LIST *proto_list,*p;
      rec = (RECORD *)r->data;
      n = sdp_get_access_protos( rec, &proto_list );
      if( n ) {
        fprintf( stderr, "can't get access protocols.\n" );
        return( 0 );
      }
      p = proto_list;
      while( p ) {          // loop thru all protocols
        LIST *pds;
        int proto=0;
        pds = (LIST *)p->data;
        while( pds ) {      // loop thru all pds
          DATA *d;
          int dtd;
          d = pds->data;        // get data ptr of pds
          while( d ) {      // loop over all data
            dtd = d->dtd;       // get dtd of data
            switch( dtd ) {     // which dtd?
              case SDP_UUID16:
              case SDP_UUID32:
              case SDP_UUID128:
            proto = sdp_uuid_to_proto( &d->val.uuid ); // get proto #
            break;
              case SDP_UINT8:
            if( proto == RFCOMM_UUID ) { // proto is rfcomm?
              chan = d->val.uint8;   // save chan num
            }
            break;
            }
        d = d->next;        // advance to next data unit
          }

          pds = pds->next;      // advance to next pds
        }
        sdp_list_free( (LIST *)p->data, 0 );

        p = p->next;        // advance to next protocol
      }
      sdp_list_free( proto_list, 0 );

      r = r->next;          // advance to next response
    }

    return( chan );
    // Return chan number [1-30] or 0 if not found
}

制作:

gcc getchan.c -o getchan -l bluetooth

关于android - 如何从 Linux 连接到 Android 蓝牙 socket ,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41130180/

相关文章:

android - 什么是基本 Intent ?

linux - 具有自动更新功能的 Linux 十六进制编辑器

linux - 从 Linux 设备驱动程序打开设备文件

python - 关闭后直接在代码中再次启动带有 ThreadingMixIn 的 TCPServer。 (给出 `Address already in use` )

android - 如何处理错误信息 "FontFamily bestFont == NULL, so return vacant FakedFont"

android - 使用AlertDialog时捕获异常?

android - 在 android 中显示来自 arrayList 的字符串

Linux 默认文件权限

sockets - 增加 CentOS 上的最大出站连接数

java - 关闭 Input/OutputStream 和直接关闭 Socket 有什么区别?