第一步:声明Bluetooth Permissions

    <!-- 设置蓝牙访问权限 -->
<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />

第二步:获取BluetoothAdapter,判断该设备是否支持蓝牙

        BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
if (mBluetoothAdapter == null) {
// Device does not support Bluetooth
// 说明该设备不支持蓝牙
}

第三步:检查当前的蓝牙是否开启

if (!mBluetoothAdapter.isEnabled()) {
Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
// 不做提示,强行打开
// mAdapter.enable();
}

如果是第一种方式:会出现提示弹窗

A dialog will appear requesting user permission to enable Bluetooth, as shown in Figure 1. If the user responds "Yes," the system will begin to enable Bluetooth and focus will return to your application once the process completes (or fails).

If enabling Bluetooth succeeds, your Activity will receive the RESULT_OK result code in the onActivityResult() callback. If Bluetooth was not enabled due to an error (or the user responded "No") then the result code will be RESULT_CANCELED.

    @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == REQUEST_ENABLE_BT) {
if (resultCode == RESULT_OK) {
// 蓝牙已经开启
Log.d("h_bl", "蓝牙已经开启完毕");
String bluetoothName = bluetoothAdapter.getName(); // 获取本地蓝牙名称
String bluetoothAddress = bluetoothAdapter.getAddress(); // 获取本地蓝牙地址
tv_bluetoothName.append(bluetoothName);
tv_bluetoothAddress.append(bluetoothAddress);
} else {
Log.d("h_bl", "蓝牙开启失败");
}
}
super.onActivityResult(requestCode, resultCode, data);
}

其中,

private int REQUEST_ENABLE_BT = 1; // 蓝牙打开的请求码

Optionally, your application can also listen for the ACTION_STATE_CHANGED broadcast Intent, which the system will broadcast whenever the Bluetooth state has changed. This broadcast contains the extra fields EXTRA_STATE and EXTRA_PREVIOUS_STATE, containing the new and old Bluetooth states, respectively. Possible values for these extra fields areSTATE_TURNING_ONSTATE_ONSTATE_TURNING_OFF, and STATE_OFF. Listening for this broadcast can be useful to detect changes made to the Bluetooth state while your app is running.

可选的,你的应用可以监听ACTION_STATE_CHANGED广播intent,当系统蓝牙状态改变将会发起这个广播,这个广播包含了EXTRA_STATE和EXTRA_PREVIOUS_STATE额外的字段,包含了新的和旧的蓝牙状态分别的,可能 有STATE_TURNING_ON,STATE_ON,STATE_TURNING_OFF和STATE_OFF可能的值,监听广播能够 对于检测蓝牙状态改变是有用的。  --- 用来判断蓝牙是否开启完毕

第3.1步:检查当前的蓝牙是否开启完毕

// 蓝牙状态改变的广播
private final BroadcastReceiver bluetoothState = new BroadcastReceiver() { @Override
public void onReceive(Context context, Intent intent) {
String stateExtra = BluetoothAdapter.EXTRA_STATE;
int state = intent.getIntExtra(stateExtra, -1);
switch (state) {
case BluetoothAdapter.STATE_TURNING_ON: // 蓝牙打开中 break;
case BluetoothAdapter.STATE_ON: // 蓝牙打开完成 break;
case BluetoothAdapter.STATE_TURNING_OFF: // 蓝牙关闭中 break;
case BluetoothAdapter.STATE_OFF: // 蓝牙关闭完成 break;
} }
};
// 蓝牙状态改变的广播
IntentFilter filter2 = new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED);
registerReceiver(bluetoothState,new IntentFilter(BluetoothAdapter.ACTION_STATE_CHANGED)); // 蓝牙状态改变的广播

Tip: Enabling discoverability will automatically enable Bluetooth. If you plan to consistently enable device discoverability before performing Bluetooth activity, you can skip step 2 above. Read about enabling discoverability, below.

提示:启用程序会自动启用蓝牙。如果你打算开启设备的可见性,可以跳过上面的2步。阅读关于启用可发现,下面。   --- 设置蓝牙的可见性,就把Intent添加值,看第五步

第四步:寻找其他设备

Using the BluetoothAdapter, you can find remote Bluetooth devices either through device discovery or by querying the list of paired (bonded) devices.

Device discovery is a scanning procedure that searches the local area for Bluetooth enabled devices and then requesting some information about each one (this is sometimes referred to as "discovering," "inquiring" or "scanning"). However, a Bluetooth device within the local area will respond to a discovery request only if it is currently enabled to be discoverable. If a device is discoverable, it will respond to the discovery request by sharing some information, such as the device name, class, and its unique MAC address. Using this information, the device performing discovery can then choose to initiate a connection to the discovered device.

Once a connection is made with a remote device for the first time, a pairing request is automatically presented to the user. When a device is paired, the basic information about that device (such as the device name, class, and MAC address) is saved and can be read using the Bluetooth APIs. Using the known MAC address for a remote device, a connection can be initiated with it at any time without performing discovery (assuming the device is within range).

Remember there is a difference between being paired and being connected. To be paired means that two devices are aware of each other's existence, have a shared link-key that can be used for authentication, and are capable of establishing an encrypted connection with each other. To be connected means that the devices currently share an RFCOMM channel and are able to transmit data with each other. The current Android Bluetooth API's require devices to be paired before an RFCOMM connection can be established. (Pairing is automatically performed when you initiate an encrypted connection with the Bluetooth APIs.)

The following sections describe how to find devices that have been paired, or discover new devices using device discovery.

Note: Android-powered devices are not discoverable by default. A user can make the device discoverable for a limited time through the system settings, or an application can request that the user enable discoverability without leaving the application. How to enable discoverability is discussed below.

使用BluetoothAdapter,你能够打开可见性的设备(搜索到的蓝牙设备)和已经配对的的设备列表。

设备发现是一个扫描程序,搜索本地区具有蓝牙功能的设备,然后请求一些信息(这是有时被称为“发现中”,“查询中”或“扫描中”)。然而,只有局域网内的蓝牙设备处于能够被发现的状态中,才能响应别的设备发送的发现请求。如果一个设备是可以被发现的,它会响应发现请求并共享一些信息,比如设备名称、类别,并以唯一的MAC地址。使用此信息,该设备执行发现,然后选择启动一个初始化连接到设备。

当第一次去连接远程设备的时候,会提交一个配对请求给用户确认。当设备配对时,一些基本的信息会被保存,并可以通过APIs去读取这些信息(such as the device name, class, and MAC address)。使用一个已知的MAC地址去连接设备的时候,无论该设备是否处于发现状态,都可以去连接。(但设备是在范围内)。

记住配对和连接之间的区别。已经配对的意味着两个设备是互相认识对方的存在,已经有了一个用来认证的共享的key,然后可以建立一个加密的连接。而连接是说设备已经建立了RFCOMM通道,并可以交换数据。现在的Android Bluetooth APIs 需要在建立RFCOMM通道之前,需要先配对。(使用Bluetooth APIs初始化加密连接的时候,会自动匹配。)

下面的章节将介绍如何找到已配对的设备,或者使用设备发现发现新设备。
Note: Android设备默认是不可发现的。用户可以通过系统设置使设备能在有限的时间内被发现,或 应用程序可以要求用户在没有离开该应用的时候使蓝牙可见。

4.1 找到已经配对的设备

Before performing device discovery, its worth querying the set of paired devices to see if the desired device is already known. To do so, call getBondedDevices(). This will return a Set of BluetoothDevices representing paired devices. For example, you can query all paired devices and then show the name of each device to the user, using an ArrayAdapter:

在执行“发现设备”之前,先获取到已经配对设备的set是很有值得的。调用getBondedDevices()即可,会返回一组已配对的set。例如,你可以查询已配对的设备,并利用ArrayAdapter去显示它们的名字。

        Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
// If there are paired devices
if (pairedDevices.size() > 0) {
// Loop through paired devices
for (BluetoothDevice device : pairedDevices) {
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
} else {
Toast.makeText(getApplicationContext(), "没有找到已匹对的设备!", Toast.LENGTH_SHORT).show();
}

All that's needed from the BluetoothDevice object in order to initiate a connection is the MAC address. In this example, it's saved as a part of an ArrayAdapter that's shown to the user. The MAC address can later be extracted in order to initiate the connection. You can learn more about creating a connection in the section about Connecting Devices.

通过BluetoothDevice的MAC地址去初始化连接,这里只是显示给用户看。MAC可以被提取,然后去初始化连接。你可以在 Connecting Devices章节学习到更多创建连接。

4.2 发现设备

调用startDiscovery()函数后,系统将扫描12秒,返回找到的蓝牙设备。我们需用广播来接收。

For each device, the system will broadcast the ACTION_FOUND Intent. This Intent carries the extra fields EXTRA_DEVICE and EXTRA_CLASS, containing a BluetoothDevice and a BluetoothClass, respectively. For example, here's how you can register to handle the broadcast when devices are discovered:

每发现一个设备,系统就会发送ACTION_FOUND Intent.的广播,这个Intent携带额外的字段EXTRA_DEVICE and EXTRA_CLASS,包含a BluetoothDevice and a BluetoothClass

// Create a BroadcastReceiver for ACTION_FOUND
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
// When discovery finds a device
if (BluetoothDevice.ACTION_FOUND.equals(action)) {
// Get the BluetoothDevice object from the Intent
BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
// Add the name and address to an array adapter to show in a ListView
mArrayAdapter.add(device.getName() + "\n" + device.getAddress());
}
}
};
// Register the BroadcastReceiver
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND);
registerReceiver(mReceiver, filter); // Don't forget to unregister during onDestroy

其中,需要调用

// 扫描蓝牙设备
btAdapter.startDiscovery();

警告:Once you have found a device to connect, be certain that you always stop discovery with cancelDiscovery() before attempting a connection。

Caution: Performing device discovery is a heavy procedure for the Bluetooth adapter and will consume a lot of its resources. Once you have found a device to connect, be certain that you always stop discovery with cancelDiscovery() before attempting a connection. Also, if you already hold a connection with a device, then performing discovery can significantly reduce the bandwidth available for the connection, so you should not perform discovery while connected.

连接设备之前,要调用cancelDiscovery(),以便节约资源。并且不要执行连接的时候,去执行发现操作。

另外,需要取消广播:

    @Override
protected void onDestroy() {
unregisterReceiver(mReceiver);
super.onDestroy();
}

第五步:设备的可发现时间设定,默认是120S。

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

The maximum duration an app can set is 3600 seconds, and a value of 0 means the device is always discoverable. Any value below 0 or above 3600 is automatically set to 120 secs)

一个应用程序可以设置最大持续时间为3600秒,填写 0 的值表示设备总是发现。任何值低于0或高于3600自动设置为120秒。

会提示弹窗

Note: If Bluetooth has not been enabled on the device, then enabling device discoverability will automatically enable Bluetooth.

如果蓝牙尚未启用的设备,并使设备可发现将自动启用蓝牙。

The device will silently remain in discoverable mode for the allotted time. If you would like to be notified when the discoverable mode has changed, you can register a BroadcastReceiver for the ACTION_SCAN_MODE_CHANGED Intent. This will contain the extra fields EXTRA_SCAN_MODE andEXTRA_PREVIOUS_SCAN_MODE, which tell you the new and old scan mode, respectively. Possible values for each areSCAN_MODE_CONNECTABLE_DISCOVERABLESCAN_MODE_CONNECTABLE, or SCAN_MODE_NONE, which indicate that the device is either in discoverable mode, not in discoverable mode but still able to receive connections, or not in discoverable mode and unable to receive connections, respectively.

You do not need to enable device discoverability if you will be initiating the connection to a remote device. Enabling discoverability is only necessary when you want your application to host a server socket that will accept incoming connections, because the remote devices must be able to discover the device before it can initiate the connection.

可以接受“发现模式”的改变的广播,会接收到ACTION_SCAN_MODE_CHANGED Intent,包含额外的字段EXTRA_SCAN_MODE andEXTRA_PREVIOUS_SCAN_MODE,描述了新的和旧的扫描模式。其值可能是SCAN_MODE_CONNECTABLE_DISCOVERABLESCAN_MODE_CONNECTABLE, or SCAN_MODE_NONE。分别代表设备处于在发现模式;不可发现模式但仍能接收连接;不可发现模式和无法接收连接。

你不需要非得使设备可见,如果你初始化去连接到远程设备的时候。当你作为主机 host a server socket,让别的设备连接进来的时候,就必须是处于可见模式!因为远程设备要发现主机,才可以初始化连接。

Android Developer -- Bluetooth篇 开发实例之一 扫描设备的更多相关文章

  1. Android Developer -- Bluetooth篇 开发实例之四 API详解

    http://www.open-open.com/lib/view/open1390879771695.html 这篇文章将会详细解析BluetoothAdapter的详细api, 包括隐藏方法, 每 ...

  2. Android Developer -- Bluetooth篇 开发实例之三 管理连接

    Managing a Connection When you have successfully connected two (or more) devices, each one will have ...

  3. Android Developer -- Bluetooth篇 开发实例之二 连接设备

    连接设备 In order to create a connection between your application on two devices, you must implement bot ...

  4. Bluetooth篇 开发实例之九 和蓝牙模块通信

    首先,我们要去连接蓝牙模块,那么,我们只要写客户端的程序就好了,蓝牙模块就相当于服务端. 连接就需要UUID. #蓝牙串口服务SerialPortServiceClass_UUID = ‘{00001 ...

  5. Bluetooth篇 开发实例之八 匹配

    自己写的App匹配蓝牙设备,不需要通过系统设置去连接. 匹配和通信是两回事. 用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK ...

  6. Bluetooth篇 开发实例之七 匹配&UUID

    匹配和通信是两回事. 1.用过Android系统设置(Setting)的人都知道蓝牙搜索之后可以建立配对和解除配对,但是这两项功能的函数没有在SDK中给出.但是可以通过反射来获取. 知道这两个API的 ...

  7. Bluetooth篇 开发实例之十 官网的Bluetooth Chat sample app.

    运行的时候,会报错: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.Action ...

  8. Android Developer -- Bluetooth篇 概述

    Bluetooth 安卓平台支持蓝牙网络协议栈,它允许设备与其他蓝牙设备进行无线交换数据.应用程序框架通过安卓蓝牙APIs提供访问蓝牙功能.这些APIs使应用程序通过无线连接到其他蓝牙设备,使点对点和 ...

  9. Bluetooth篇 开发实例之十一 官网的Bluetooth Chat sample的bug

    当没有匹配的设备和没有找到可用设备的时候. // If there are paired devices, add each one to the ArrayAdapter if (pairedDev ...

随机推荐

  1. 【志银】#define lowbit(x) ((x)&(-x))原理详解

    分析下列语句 #define lowbit(x) ((x)&(-x)) 可写成下列形式: int Lowbit(x) { return x&(-x); } 例1:x = 1 十进制转二 ...

  2. django之HTTPResponse和JsonResponse详解

    HttpResponse对象 Django服务器接收到客户端发送过来的请求后,会将提交上来的这些数据封装成一个HttpRequest对象传给视图函数.那么视图函数在处理完相关的逻辑后,也需要返回一个响 ...

  3. Flex学习笔记

    Flex —— Flexible Box 弹性布局 用来为盒子模型提供灵活性 /* 块级元素 */ .box{ display: flex; } /* 行内元素 */ .box{ display: i ...

  4. Android记事本07

    昨天: activity横竖屏切换的生命周期 今天: Anr异常的原因和解决方案 遇到的问题: 无.

  5. 第十三篇:HTML

    本篇内容 选择器 属性 一. 选择器 1.id 选择器 id 选择器可以为标有特定 id 的 HTML 元素指定特定的样式. id 选择器以 "#" 来定义. <!DOCTY ...

  6. 在Ignite中使用k-最近邻(k-NN)分类算法

    在本系列前面的文章中,简单介绍了一下Ignite的线性回归算法,下面会尝试另一个机器学习算法,即k-最近邻(k-NN)分类.该算法基于对象k个最近邻中最常见的类来对对象进行分类,可用于确定类成员的关系 ...

  7. 2017 多校2 hdu 6053 TrickGCD

    2017 多校2 hdu 6053 TrickGCD 题目: You are given an array \(A\) , and Zhu wants to know there are how ma ...

  8. C++/C---字符串

    其他类型转字符串 itoa 功 能:把一整数转换为字符串用 法:char *itoa(int value, char *string, int radix);详细解释:itoa是英文integer t ...

  9. go环境安装

    选择想要安装的版本: http://golangtc.com/download tar -zxf go1.8.linux-amd64.tar.gz cp -R go/ /usr/local/ vi / ...

  10. 生成一个空白BMP的简单代码【转】

    转自:http://blog.chinaunix.net/uid-15063109-id-4275395.html 做图像处理时,有时需要临时生成图使用.以下是生成320x240 24位图的一个简单的 ...