基于SnapDragonBoard蓝牙通信(二)

咋们接着上次的blog接着说一下Android 蓝牙的调用流程,如不清楚上节我们说的内容请小伙伴移步到基于SnapDragonBoard410c的蓝牙控制

(1)开启搜索
如果想要使自己的蓝牙设备可见,使用ACTION_REQUEST_DISCOVERABLE的Intent,调用startActivityForResult(Intent, int)方法即可。这将会通过系统设置请求开启搜索模式。默认情况下,设备将在120秒内可见。你可以定义不同的时间长度,通过添加Intent的extra: EXTRA_DISCOVERABLE_DURATION即可。该时长最大为3600秒,最小为0,超出该范围的值都会被设为120秒。其中,0表示设备始终处于可见状态。例如:

Intent discoverableIntent = new
Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE);
discoverableIntent.putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, 300);
startActivity(discoverableIntent);

一个请求蓝牙可见的对话框将会被显示出来。如果用户选择“是”,那么该设备将会在指定时间内可见,你的Activity将会在onActiviyResult()中返回和时限相同的result code。如果用户选择“否”,那么result code将为ESULT_CANCELED。

设备将在指定时间内保持可见。如果你想要检查状态的变化,可以通过使用ACTION_SCAN_MODE_CHANGED的Intent注册广播进行监听。该广播onReceive()的Intent包含两个额外域:EXTRA_SCAN_MODE 和 EXTRA_PREVIOUS_SCAN_MODE,分别表示新旧状态。可能的值有:SCAN_MODE_CONNECTABLE_DISCOVERABLE(可连接可见),SCAN_MODE_CONNECTABLE(可连接但不可见) 或 SCAN_MODE_NONE(不可连接不可见)。

如果仅仅是连接到远程蓝牙设备的话,你并不需要开启可见性。开启可见性仅仅在你的应用中作为服务端时才是必要的。因为其他蓝牙设备必须找到你的设备之后才能建立连接。

(2)连接设备

为了在你的应用中让双方设备建立连接,你必须同时实现服务器端和客户端的机制。因为其中一个设备一定会开启服务器Socket,而另一个进行连接(使用作为服务器端的MAC地址进行连接)。当客户端和服务器端彼此拥有一个在同一个RFCOMM通道已连接的BluetoothSocket时便可以进行数据的交换。在每一端,都可以获得输入和输出流,从而可以开始数据的传输。该部分将在后文描述,本部分只描述如何初始化设备间的连接。

服务器端和客户端通过不同的方式获得BluetoothSocket。当一个连接接受(accept)的时候服务器端接收BluetoothSocket。而客户端则通过打开服务器端的RFCOMM通道得到BluetoothSocket。

一种实现技术是,应用程序同时实现客户端和服务器端。因此,每一个服务器端的程序拥有一个server socket并监听连接。当然,也可以在一个应用中实现服务器端的功能,而另一个应用中实现客户端的部分。

如果两个设备之前并没有配对过,那么Android的框架将会自动进行配对的请求通知。因此当尝试进行连接时,你的应用并不需要关心两台设备是否已经配对。你的RFCOMM连接将会被阻塞,直到用户成功配对,或因为用户拒绝配对而取消,或者配对失败以及超时等。

(3)服务器端

两个设备进行连接时,必须有一个设备通过BluetoothServerSocket作为服务器。该server socket的目的是监听未来的连接请求,并当该请求被接受时,提供一个已经连接的BluetoothSocket。当从BluetoothServerSocket获得BluetoothSocket时,BluetoothServerSocket必须被抛弃,除非你想要连接多个设备。

步骤如下:

通过调用listenUsingRfcommWithServiceRecord(String, UUID)获取BluetoothServerSocket。
String是你服务的可辨别名称。系统将会自动写入一个新的“服务发现协议(Service Discovery Protocol 简称SDP)”数据库入口至你的设备,该名称可随意命名,通常情况下是应用名称。UUID也包括SDP的入口,并作为和客户端连接基础。当客户端尝试连接至服务端设备时,将会带有想要连接设备的独一无二的UUID。这些UUID必须匹配,目的是为了能够使连接被接受。

可通过网络上的诸多UUID生成器来获得UUID的字符串,然后通过fromString(String)方法获得。

通过调用accept(),开始监听连接请求。
这是一个阻塞的调用,将会在抛出异常或者连接被接受时返回。连接只有在远程设备发送一个带有和服务器端已注册的UUID相匹配的连接请求时才会被接受。当连接成功时,accept()将会返回一个已经连接的BluetoothSocket。

除非你想要接受多个连接,否则的话,调用close()进行关闭。
这将会释放server socket以及相关的资源,但是并不会关闭从accept()中返回的,已经连接的BluetoothSocket。和TCP/IP不同,RFCOMM仅仅允许在一个通道中同时存在一个客户端。因此大多数情况下,在获得BluetoothSocket后立即调用close()是很有必要的。

accept()方法不应当在主线程(UI线程)中执行,因为这是一个阻塞的调用,能够租住任何和程序的交互。通常情况下和BluetoothServerSocket以及BluetoothSocket有关的任何操作都应该在新的线程中进行。在另外的线程中调用close()方法将会撤销该阻塞方法调用并立即返回。请注意,BluetoothServerSocket和BluetoothSokcet中的任何方法都是线程安全的。`private class AcceptThread extends Thread {
private final BluetoothServerSocket mmServerSocket;

public AcceptThread() {
    // Use a temporary object that is later assigned to mmServerSocket,
    // because mmServerSocket is final
    BluetoothServerSocket tmp = null;
    try {
        // MY_UUID is the app's UUID string, also used by the client code
        tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, MY_UUID);
    } catch (IOException e) { }
    mmServerSocket = tmp;
}

public void run() {
    BluetoothSocket socket = null;
    // Keep listening until exception occurs or a socket is returned
    while (true) {
        try {
            socket = mmServerSocket.accept();
        } catch (IOException e) {
            break;
        }
        // If a connection was accepted
        if (socket != null) {
            // Do work to manage the connection (in a separate thread)
            manageConnectedSocket(socket);
            mmServerSocket.close();
            break;
        }
    }
}

/** Will cancel the listening socket, and cause the thread to finish */
public void cancel() {
    try {
        mmServerSocket.close();
    } catch (IOException e) { }
}

在例子中,一旦连接被接受并获得BluetoothSocket后,应用立即将该BluetoothSocket发送至独立的线程并关闭BluetoothSocket,挑出循环。

注意到,当accept()返回BluetoothSocket时,socket已经连接了,因此不应该调用connect方法。
manageConnectedSocket()是一个虚构的方法,用来初始化数据传输的线程,将在后文介绍数据传输的部分。

一旦监听到连接并获得BluetoothSocket时,应当立即调用close()关闭BluetoothServerSocket。cancel()则为此提供了一个公共的方法。

阅读更多
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/u013763766/article/details/79226142
文章标签: android
个人分类: android
想对作者说点什么? 我来说一句

基于Android的蓝牙通信接口

2013年12月27日 112KB 下载

安卓手机蓝牙通信聊天程序

2018年03月09日 20.8MB 下载

matlab蓝牙调频通信系统

2011年03月09日 37KB 下载

基于stm32f103的蓝牙通信模块

2015年03月03日 5.15MB 下载

没有更多推荐了,返回首页

不良信息举报

基于SnapDragonBoard蓝牙通信(二)

最多只允许输入30个字

加入CSDN,享受更精准的内容推荐,与500万程序员共同成长!
关闭
关闭