6.30工作日志——安卓蓝牙2.0学习报告

                                    6.30工作日志——安卓蓝牙2.0学习报告


今天是入职第一天,不得不说国企确实很无趣。定时打卡上下班,时间和工作性质也都不灵活。不过我的同事大哥们倒是非常有趣。

工作第一天就记录一下今天完成的工作好了。今天帅哥导师给我安排的任务是

1.更新AS;

2.熟悉安卓蓝牙编程。


依靠着公司神速的网络,第一项任务倒是很快完成了。之前一直不想更新AS,就怕打开之前的项目会出一大堆莫名其妙的问题,然后今天是出于工作需要硬着头皮更新了一波,没想到迅速的就完成了跟之前项目的对接。我猜想应该是这边的网络访问Google不会被墙,真不愧是做管道的公司,这方面都没什么限制。


然后开始进行第二项工作,熟悉安卓蓝牙编程。之前学校里面的项目做过一些蓝牙的项目,还是有一定记忆的,然后这次就正好系统的再学习一下。然后主要是分为两个版本来学习,分别是蓝牙2.0和蓝牙4.0。然后因为国企的企业氛围嘛,第一天就学习学习Android 蓝牙 2.0的使用方法,然后之后再学习BLE。


首先介绍一下Android 蓝牙 2.0 常用到的几个类。

BluetoothAdapter:这个类表示本地的蓝牙适配器,也就是你手机上的蓝牙装置的控制类,可以说是本地蓝牙功能的一个入口吧。使用这个类,能够发现其他的蓝牙设备,查询已配对的设备的列表,使用已知的MAC地址来实例化一个BlueTooth Device对象,并且创建一个BluetoothServerSocket对象来监听与其他设备的通信。这些都是在本地需要做的一些蓝牙的基本功能,都是由BlueTooth Adapter来完成的。


BluetoothDevice:代表一个远程的蓝牙设备。使用这个类通过BluetoothSocket或查询诸如名称、地址、类和配对状态等设备信息来请求跟远程设备的连接。


BluetoothSocket:代表蓝牙socket的接口(类似TCP的Socket)。这是允许一个应用程序跟另一个蓝牙设备通过输入流和输出流进行数据交换的连接点。可以理解为是Socket的蓝牙版吧,也可以从中得到输入输出流。
BluetoothServerSocket:代表一个打开的监听传入请求的服务接口(类似于TCP的ServerSocket)。为了连接两个Android设备,一个设备必须用这个类打开一个服务接口。当远程蓝牙设备请求跟本设备建立连接请求时,BluetoothServerSocket会在连接被接收时返回一个被连接的BluetoothSocket对象。


BluetoothClass:描述了蓝牙设备的一般性特征和功能。这个类是一个只读的属性集,这些属性定义了设备的主要和次要设备类和服务。但是,这个类并不保证描述了设备所支持的所有的蓝牙配置和服务,但是这种对设备类型的提示是有益的。


-----------------------------------------------------------------------------------------------------------------------------------------

BluetoothProfile
代表一个蓝牙配置的接口。蓝牙配置是基于蓝牙通信的设备间的无线接口规范。一个例子是免提的配置。更多的配置讨论,请看下文的用配置来工作。
BluetoothHeadset
提供对使用蓝牙耳机的移动电话的支持。它同时包含了Bluetooth Headset和Hands-Free(v1.5)的配置。
BluetoothA2dp
定义如何把高品质的音频通过蓝牙连接从一个设备流向另一个设备。“A2DP”是Advanced Audio Distribution Profile的缩写。
BluetoothHealth
代表一个健康保健设备配置的控制蓝牙服务的代理。
BluetoothHealthCallback
用于实现BluetoothHealth回调的抽象类。你必须继承这个类,并实现它的回调方法,来接收应用程序的注册状态和蓝牙通道状态变化的更新。
BluetoothHealthAppConfiguration
代表蓝牙相关的第三方健康保健应用程序所注册的与远程蓝牙健康保健设备进行通信的配置。
BluetoothProfile.ServiceListener
BluetoothProfile IPC客户端连接或断开服务的通知接口(它是运行特俗配置的内部服务)。


-----------------------------------------------------------------------------------------------------------------------------------------


配对前的准备工作:

要通过蓝牙跟对方通信,那么我们就必须要首先开启本地的蓝牙。

Step1:开启蓝牙权限:BLUETOOTH权限和BLUETOOTHADMIN权限的区别在于:为了执行任何蓝牙通信(如请求连接、接收连接和传输数据),你必须申请BLUETOOTH权限。为了启动设备发现或维护蓝牙设置,你必须申请BLUETOOTH_ADMIN权限。

注意:申请了BLUETOOTH_ADMIN权限就必须申请BLUETOOTH权限。

<uses-permission android:name="android.permission.BLUETOOTH" />
<uses-permission android:name="android.permission.BLUETOOTH_ADMIN" />    



Step2:判断蓝牙是否可用。如果不可用则无法使用,如果蓝牙可用而没有开启,则请求用户开启蓝牙。具体方法是先定义一个BlueTooth Adapter然后初始化为BlueTooth Default Adapter,如果成功的话就表示设备支持蓝牙,否则返回null表示不支持。

BluetoothAdapter mBluetoothAdapter =BluetoothAdapter.getDefaultAdapter();
if(mBluetoothAdapter ==null)<pre code_snippet_id="1738710" snippet_file_name="blog_20160701_2_1867085" name="code" class="java">{
// Device does not support Bluetooth
}
 
 


Step3:开启蓝牙。接下来,你需要确保蓝牙是开启的。调用isEnabled()方法来检查当前蓝牙是否开启。如果这个方法返回false,那么蓝牙是被禁用的。要申请启用蓝牙功能,就要调用带有ACTION_REQUEST_ENABLE操作意图的startActivityForResult()方法。它会给系统设置发一个启用蓝牙功能的请求(不终止你的应用程序)。


if(!mBluetoothAdapter.isEnabled()){
Intent enableBtIntent =newIntent(BluetoothAdapter.ACTION_REQUEST_ENABLE);
startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);
}


这时会显示一个请求用户启用蓝牙功能的对话框:



如果用户响应“Yes”,那么系统会开始启用蓝牙功能,完成启动过程(有可能失败),焦点会返回给你的应用程序。
传递给startActivityForResult()方法的REQUEST_ENABLE_BT常量,是一个你的应用程序中定义的整数(它必须大于0),系统会把它作为requestCode参数返回到你的onActivityResult()回调实现中。
如果蓝牙功能启用成功,你的Activity会在onActivityResult()回调中接收到RESULT_OK结果,如果蓝牙没有被启动(或者用户响应了“No”),那么该结果编码是RESULT_CANCELED。

注意:onActivityResult()可以自己实现,覆盖Activity类中的实现。具体用法参见http://blog.csdn.net/liu_qiqi/article/details/38304033


可选地,你的应用程序还可以监听ACTION_STATE_CHANGED广播Intent,无论蓝牙状态何时改变,系统都会广播这个Intent。这个广播包含的附加字段EXTRA_STATE和EXTRA_PREVIOUS_STATE中分别指明了新的和旧的蓝牙状态。这些附加字段中可能的值是:STATE_TURNING_ON、STATE_ON、STATE_TURNING_OFF和STATE_OFF。

具体用法参见:http://ask.csdn.net/questions/12305


Step4:蓝牙开启之后,就可以进行设备的搜索、配对。

查找设备:

使用BluetoothAdapter对象,能够通过设备发现或查询已配对的设备列表来找到远程的蓝牙设备。
设备发现是一个扫描过程,该过程搜索本地区域内可用的蓝牙设备,然后请求一些彼此相关的一些信息(这个过程被叫做“发现”、“查询”或“扫描”)。但是,本地区域内的蓝牙设备只有在它们也启用了可发现功能时,才会响应发现请求。如果一个设备是可发现的,那么它会通过共享某些信息(如设备名称、类别和唯一的MAC地址)来响应发现请求。使用这些信息,执行发现处理的设备能够有选择的初始化跟被发现设备的连接。


一旦跟远程的设备建立的首次连接,配对请求就会自动的被展现给用户。当设备完成配对,相关设备的基本信息(如设备名称、类别和MAC地址)就会被保存,并能够使用蓝牙API来读取。使用已知的远程设备的MAC地址,在任何时候都能够初始化一个连接,而不需要执行发现处理(假设设备在可连接的范围内)。


要记住配对和连接之间的差异。配对意味着两个设备对彼此存在性的感知,它们之间有一个共享的用于验证的连接密钥,用这个密钥两个设备之间建立被加密的连接。连接意味着当前设备间共享一个RFCOMM通道,并且能够被用于设备间的数据传输。当前Android蓝牙API在RFCOMM连接被建立之前,要求设备之间配对。(在使用蓝牙API初始化加密连接时,配对是自动被执行的。)


在执行设备发现之前,应该先查询已配对的设备集合,来看期望的设备是否是已知的。调用getBondedDevices()方法来完成这件工作。这个方法会返回一个代表已配对设备的BluetoothDevice对象的集合。例如,你能够查询所有的配对设备,然后使用一个ArrayAdapter对象把每个已配对设备的名称显示给用户。

Set 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());
}
}


从BluetoothDevice对象来初始化一个连接所需要的所有信息就是MAC地址。 在这个例子中,MAC地址被作为ArrayAdapter的一部分来保存,并显示给用户。随后,该MAC地址能够被提取用于初始化连接。

发现设备:

简单的调用startDiscovery()方法就可以开始发现设备。该过程是异步的,并且该方法会立即返回一个布尔值来指明发现处理是否被成功的启动(而不表示是是否发现了设备)。通常发现过程会查询扫描大约12秒,接下来获取扫描发现的每个设备的蓝牙名称。


为了接收每个被发现设备的的信息,你的应用程序必须注册一个ACTION_FOUND类型的广播接收器。对应每个蓝牙设备,系统都会广播ACTION_FOUND类型的Intent。这个Intent会携带EXTRA_DEVICE和EXTRA_CLASS附加字段,这个两个字段分别包含了BluetoothDevice和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

注意:执行设备发现,对于蓝牙适配器来说是一个沉重的过程,它会消耗大量的资源。 一旦发现要连接设备,在尝试连接之前一定要确认用cancelDiscovery()方法来终止发现操作。 另外,如果已经有一个跟设备的连接,那么执行发现会明显的减少连接的可用带宽, 因此在有连接的时候不应该执行发现处理。


启用设备的可发现性:

如果要让本地设备可以被其他设备发现,那么就要调用ACTION_REQUEST_DISCOVERABLE操作意图的startActivityForResult(Intent, int)方法。这个方法会向系统设置发出一个启用可发现模式的请求(不终止应用程序),这部分参照之前开启蓝牙的那部分讲解。默认情况下,设备的可发现模式会持续120秒。通过给Intent对象添加EXTRA_DISCOVERABLE_DURATION附加字段,可以定义不同持续时间。应用程序能够设置的最大持续时间是3600秒,0意味着设备始终是可发现的。任何小于0或大于3600秒的值都会自动的被设为120秒。例如,以下代码把持续时间设置为300秒:

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

申请用户启用设备的可发现模式时,会显示这样一个对话框。如果响应“Yes”,那么设备的可发现模式会持续指定的时间,而且你的Activity会接收带有结果代码等于可发现设备持续时间的onActivityResult()回调方法的调用。如果用户响应“No”或有错误发生,则结果代码等于RESULT_CANCELED。

注意:如果设备没有开启蓝牙功能,那么开启设备的可发现模式会自动开启蓝牙。


在可发现模式下,设备会静静的把这种模式保持到指定的时长。如果你想要在可发现模式被改变时获得通知,那么你可以注册一个ACTION_SCAN_MODE_CHANGED类型的Intent广播。这个Intent对象中包含了EXTRA_SCAN_MODE和XTRA_PREVIOUS_SCAN_MODE附加字段,它们会分别告诉你新旧扫描模式。它们每个可能的值是:SCAN_MODE_CONNECTABLE_DISCOVERABLE,SCAN_MODE_CONNECTABLE或SCAN_MODE_NONE,它们分别指明设备是在可发现模式下,还是在可发现模式下但依然可接收连接,或者是在可发现模式下并不能接收连接。


Step5:连接设备。

为了让两个设备上的两个应用程序之间建立连接,你必须同时实现服务端和客户端机制,因为一个设备必须打开服务端口,同时另一个设备必须初始化跟服务端设备的连接(使用服务端的MAC地址来初始化一个连接)。当服务端和客户端在相同的RFCOMM通道上有一个BluetoothSocket连接时,才能够被认为是服务端和客户端之间建立了连接。这时,每个设备能够获得输入和输出流,并且能够彼此开始传输数据。


服务端设备和客户端设备彼此获取所需的BluetoothSocket的方法是不同的。服务端会在接收输入连接的时候接收到一个BluetoothSocket对象。客户端会在打开跟服务端的RFCOMM通道时接收到一个BluetoothSocket对象。(类似TCP套接口中的Server和Client端)。


注意:如果两个设备之前没有配对,那么Android框架会在连接过程期间,自动的显示一个配对请求通知或对话框给用户,如图3所示。因此在试图连接设备时,你的应用程序不需要关心设备是否被配对。FRCOMM的尝试性连接会一直阻塞,一直到用户成功的配对,或者是因用户拒绝配对或配对超时而失败。


服务器端:

当你想要连接两个设备时,一个必须通过持有一个打开的BluetoothServerSocket对象来作为服务端。服务套接字的用途是监听输入的连接请求,并且在一个连接请求被接收时,提供一个BluetoothSocket连接对象。在从BluetoothServerSocket对象中获取BluetoothSocket时,BluetoothServerSocket能够(并且也应该)被废弃,除非你想要接收更多的连接。



猜你喜欢

转载自blog.csdn.net/maxichu/article/details/51798710