android蓝牙开发——基本概念

               

http://blog.csdn.net/luojianbing1/article/details/6776318

蓝牙测试

1.检查是否有蓝牙设备

在插入蓝牙到到USB口前后,用lsusb命令可以发现输出内容不一样。即插入蓝牙设备后lsusb输出多了一行。然后,运行hciconfig可以看到:

#hciconfig

hci0:       Type: BR/EDR  Bus: USB

       BD Address: 00:00:00:00:00:00  ACL MTU: 0:0  SCO MTU: 0:0

       DOWN

       RX bytes:0 acl:0 sco:0 events:0 errors:0

       TX bytes:0 acl:0 sco:0 commands:0 errors:0

上面的信息说明检测到了蓝牙设备hci0。

2.激活蓝牙设备

#hciconfig hci0 up

可以激活借口(这一步不做,hcitool scan无法运行) 。这时候如果再次执行hciconfg命令,可以发现蓝牙以及激活(UP RUNNING):

hci0:       Type: BR/EDR  Bus: USB

       BD Address: 00:1F:81:00:02:DD  ACL MTU: 1021:4  SCO MTU: 180:1

       UP RUNNING

       RX bytes:342 acl:0 sco:0 events:10 errors:0

       TX bytes:33 acl:0 sco:0 commands:11 errors:1

3.扫描设备

#hcitool scan

可以得到:

Scanning ...

       00:23:7A:F3:66:8D     BlackBerry 9000                这就是搜索到的设备(提前打开哦)

4.修改配置文件:

修改/etc/bluetooth/rfcomm.conf

将里面的:device 11:22:33:44:55:66;

修改成hcitool scan的结果,也就是:

device 00:23:7A:F3:66:8D

保存退出。

rfcomm_create_dev。

5.创建蓝牙设备

运行:

#rfcomm_create_dev。

 

3,配置bluez

默认的配置文件放在/etc/bluetooth目录

hcid.conf和pin不需要修改,安全方式已经被设置成auto,这是为了方便连接,用户可以自己修改,推荐不做修改,以防止有些设备连接不上。

4,重启bluetooth服务。

  /etc/rc.d/init.d/bluetooth stop

  /etc/rc.d/init.d/bluetooth start

7,创建设备:

#rfcomm

cat /dev/rfcomm0

8,添加通道:

#sdptool add --channel=1 DID SP DUN LAN FAX OPUSH FTP HS HF SAP NAP GN PANU HID CIP CTP A2SRC A2SNK SYNCML NOKID PCSUITE SR1

后面的参数不一定被支持,但是以防有些服务没有被打开,所以,干脆全部打开了。

rfcomm bind /dev/rfcomm0 电话的地址通道(在rfcomm.conf中配置)

这里的命令应该写成:

#rfcomm bind /dev/rfcomm0 00:23:7A:F3:66:8D 1

9,连接手机

  hcitool cc 电话的地址

也就是

  hcitool cc 00:23:7A:F3:66:8D

这时候,可以看到手机上的蓝牙连接呈联通状态。

10,从计算机发送文件:

  obex-send abc.jpg

操作系统会弹出提示框,让你选择要发送的目标。

同时可以看到手机会弹出提示框,询问是否接受文件。

11,手机的配置:

需要在手机上进行一下配置:

连接->蓝牙->匹配装置->添加装置。

会自动扫描到PC上的适配器。

如果需要填入识别码就填写123。上面已经设置了。

这时候,可以看到手机已经成功的添加蓝牙装置。

12,从手机发送文件。

在PC机上启动obex-server,会看到系统托盘出现一个小图标。

完成上面的工作后,可以进入手机的:

多媒体->我的影集

选择一张图片。

然后,“发送”->“通过蓝牙”

看到有刚才扫描到的蓝牙适配器。

然后,就可以发送文件了。

13,使用软件管理手机信息。

参考gnokii软件的文档

二、蓝牙耳机。

1,同时按住jabra 250上面的“电话键”和“音量增大键”,大约8秒,看到蓝灯常亮

2,扫描耳机,得到bdaddress

  hcitool scan

3,配置工作:

  modprobe snd_bt_sco

  hciconfig hci0 void 0x0060

  btsco bdaddress (这里的bdaddress就是扫描出来的结果)

  btsco运行后,会弹出对话框,要求输入耳机的pin,jabra 250为0000,可以在说明书上找到。

4,建立联接后,设备被映射成/dev/dsp1。

以beep为例,

插件->输出,选择使用alsa驱动,点开“首选项”,音频设置部分就可以看到btsco:hw0,1之类的信息,选择这个即可。

然后播放一首歌,尝试一下无线的快乐吧。

然后适当的配置你所要使用的播放器之类的就可以了

 

一、Bluez编译配置支持
    
    在BoardConfig.mk中添加:
    BOARD_HAVE_BLUETOOTH := true。
    
二、启动hciattach

 
    BlueZ核心子系统使用hciattach守护进程添加指定的硬件串口驱动。
    修改init.rc来启动hciattach:
    service hciattach /system/bin/hciattch -n -s 115200 /dev/ttyS2 bcm2035 115200
            user bluetooth
            group bluetooth net_bt_admin
            disabled
     
     同时也要启动dbus daemon,因为bluez需要dbus与其它进程通讯的。
 
三、Bluez控制流程
 
     class bluetoothsetting是UI的入口,通过按button scan进入搜索状态,
     applicaton层调用bluetoothdevice, 接着就是bluetoothservice的调用, 
     bluetoothservice调用native方法,到此全部的java程序结束了。
     下面的调用都是JNI, cpp实现的。android_server_bluetoothservice.cpp里面实现了native
     方法,最终通过dbus封装,调用 HCID deamon 的function DiscoverDevice。
     Bluetooth的启动流程是:
        1.  打开蓝牙电源,通过rfkill来enable;(system/bluetooth/bluedroid/bluetooth.c)
        2.  启动service hciattch -n -s 115200 /dev/ttyS2 bcm2035 115200;
        3.  检测HCI是否成功(接受HCIDEVUP socket来判断或hciconfig hci0 up);
        4.  hcid deamon start up。
 
 
四、Bluetooth结构
 
    1、JAVA层
       frameworks/base/core/java/android/bluetooth/
       包含了bluetooth的JAVA类。
 
    2、JNI层
       frameworks/base/core/jni/android_bluetooth_开头的文件
       定义了bluez通过JNI到上层的接口。
       frameworks/base/core/jni/android_server_bluetoothservice.cpp
       调用硬件适配层的接口system/bluetooth/bluedroid/bluetooth.c
 
    3、bluez库
       external/bluez/
       这是bluez用户空间的库,开源的bluetooth代码,包括很多协议,生成libbluetooth.so。
 
    4、硬件适配层
       system/bluetooth/bluedroid/bluetooth.c
       包含了对硬件操作的接口
       system/bluetooth/data/*
       一些配置文件,复制到/etc/bluetooth/。
       还有其他一些测试代码和工具。

首先,要操作蓝牙,先要在AndroidManifest.xml里加入权限<uses-permissionandroid:name="android.permission.BLUETOOTH_ADMIN" /> 
<uses-permissionandroid:name="android.permission.BLUETOOTH" /> 
然后,看下api,Android所有关于蓝牙开发的类都在android.bluetooth包下,如下图,只有8个类 
  Android蓝牙开发 - blackdoor - 黑门 
而我们需要用到了就只有几个而已: 
1.BluetoothAdapter 顾名思义,蓝牙适配器,直到我们建立bluetoothSocket连接之前,都要不断操作它 
BluetoothAdapter里的方法很多,常用的有以下几个: 
cancelDiscovery() 根据字面意思,是取消发现,也就是说当我们正在搜索设备的时候调用这个方法将不再继续搜索 
disable()关闭蓝牙 
enable()打开蓝牙,这个方法打开蓝牙不会弹出提示,更多的时候我们需要问下用户是否打开,一下这两行代码同样是打开蓝牙,不过会提示用户: 
Intent enabler=new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
startActivityForResult(enabler,reCode);//同startActivity(enabler); 
getAddress()获取本地蓝牙地址 
getDefaultAdapter()获取默认BluetoothAdapter,实际上,也只有这一种方法获取BluetoothAdapter 
getName()获取本地蓝牙名称 
getRemoteDevice(String address)根据蓝牙地址获取远程蓝牙设备 
getState()获取本地蓝牙适配器当前状态(感觉可能调试的时候更需要) 
isDiscovering()判断当前是否正在查找设备,是返回true 
isEnabled()判断蓝牙是否打开,已打开返回true,否则,返回false 
listenUsingRfcommWithServiceRecord(String name,UUID uuid)根据名称,UUID创建并返回BluetoothServerSocket,这是创建BluetoothSocket服务器端的第一步 
startDiscovery()开始搜索,这是搜索的第一步 
2.BluetoothDevice看名字就知道,这个类描述了一个蓝牙设备 
createRfcommSocketToServiceRecord(UUIDuuid)根据UUID创建并返回一个BluetoothSocket 
这个方法也是我们获取BluetoothDevice的目的——创建BluetoothSocket 
这个类其他的方法,如getAddress(),getName(),同BluetoothAdapter 
3.BluetoothServerSocket如果去除了Bluetooth相信大家一定再熟悉不过了,既然是Socket,方法就应该都差不多, 
这个类一种只有三个方法 
两个重载的accept(),accept(int timeout)两者的区别在于后面的方法指定了过时时间,需要注意的是,执行这两个方法的时候,直到接收到了客户端的请求(或是过期之后),都会阻塞线程,应该放在新线程里运行! 
还有一点需要注意的是,这两个方法都返回一个BluetoothSocket,最后的连接也是服务器端与客户端的两个BluetoothSocket的连接 
close()这个就不用说了吧,翻译一下——关闭! 
4.BluetoothSocket,跟BluetoothServerSocket相对,是客户端 
一共5个方法,不出意外,都会用到 
close(),关闭 
connect()连接 
getInptuStream()获取输入流 
getOutputStream()获取输出流 
getRemoteDevice()获取远程设备,这里指的是获取bluetoothSocket指定连接的那个远程蓝牙设备。 
1、获取本地蓝牙适配器 
BluetoothAdapter 
mAdapter= BluetoothAdapter.getDefaultAdapter(); 
2、打开蓝牙 
if(!mAdapter.isEnabled()){ 
//弹出对话框提示用户是后打开 
Intent enabler = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
startActivityForResult(enabler, REQUEST_ENABLE); 
//不做提示,强行打开 
// mAdapter.enable(); 

3、搜索设备 
1)刚才说过了mAdapter.startDiscovery() 
是第一步,可以你会发现没有返回的蓝牙设备,怎么知道查找到了呢?向下看,不要急 
2)定义BroadcastReceiver,关于BroadcastReceiver不多讲了,不是今天的讨论内容,代码如下 
BroadcastReceiver mReceiver = new BroadcastReceiver() { 
public void onReceive(Context context, Intent intent) { 
String action = intent.getAction(); 
    //找到设备 
if (BluetoothDevice.ACTION_FOUND.equals(action)) { 
BluetoothDevice device = intent 
.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE); 
if (device.getBondState() != BluetoothDevice.BOND_BONDED) { 
Log.v(TAG, "find device:" + device.getName() 
+ device.getAddress()); 


  //搜索完成 
else if (BluetoothAdapter.ACTION_DISCOVERY_FINISHED 
.equals(action)) { 
setTitle("搜索完成"); 
if (mNewDevicesAdapter.getCount() == 0) { 
Log.v(TAG,"find over"); 


//执行更新列表的代码 

}; 
这样,没当查找到新设备或是搜索完成,相应的操作都在上段代码的两个if里执行了,不过前提是你要先注册 
BroadcastReceiver,具体代码如下 
IntentFilter filter = new IntentFilter(BluetoothDevice.ACTION_FOUND); 
registerReceiver(mReceiver, filter); 
filter = new IntentFilter(BluetoothAdapter.ACTION_DISCOVERY_FINISHED); 
registerReceiver(mReceiver, filter); 
(这段代码,一般写在onCreate()里..) 
3建立连接,首先Android sdk(2.0以上版本)支持的蓝牙连接是通过BluetoothSocket建立连接(说的不对请高人指正),服务器端(BluetoothServerSocket)和客户端(BluetoothSocket)需指定同样的UUID,才能建立连接,因为建立连接的方法会阻塞线程,所以服务器端和客户端都应启动新线程连接 
  1)服务器端: 
//UUID格式一般是"xxxxxxxx-xxxx-xxxx-xxxx-xxxxxxxxxxxx"可到 
//http://www.uuidgenerator.com 申请 
BluetoothServerSocket serverSocket = mAdapter. listenUsingRfcommWithServiceRecord(serverSocketName,UUID); 
serverSocket.accept(); 
2)客户端: 
//还记得我们刚才在BroadcastReceiver获取了BLuetoothDevice么? 
BluetoothSocket clienSocket=dcvice. createRfcommSocketToServiceRecord(UUID); 
clienSocket.connect(); 
4、数据传递,通过以上操作,就已经建立的BluetoothSocket连接了,数据传递无非是通过流的形式 
1)获取流 
inputStream = socket.getInputStream(); 
outputStream = socket.getOutputStream(); 
2)写出、读入 
略 
android.bluetooth下有8个类,还有4个类没有用到,那4个类里定义的都是常量

Android SDK2.0版本才支持蓝牙Bluetooth接口的, SDK API接口支持蓝牙技术所有特征,而且和手机制造商无关,这给Android开发者带来了很大的方便,也使得Android更为完美了。

    Android蓝牙API接口支持下面特征:

  • 开启/关闭蓝牙;
  • 开启/关闭设备;
  • 发现蓝牙设备;
  • 发现蓝牙设备;
  • 传输数据;

Android SDK中对蓝牙的操作做了很高级的封转,类BluetoothAdapter就能完成蓝牙的基本操作,在开发中使用蓝牙变得很简单。下面介绍一个应用过程。

1、确保Android工程使用的是Android SDK2.0版本或者更高的。

2、在AndroidManifest.xml中增加使用蓝牙的权限:
<uses-permission android:name="android.permission.BLUETOOTH" />

3、开启蓝牙,代码如下:
import android.bluetooth.BluetoothAdapter;
...
public static void StartBluetooth(){
   BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
   btAdapter.enable();
}
类BluetoothAdapter就是代表蓝牙设备,调用enable()方法即可启动设备中的蓝牙;

4、关闭蓝牙,代码也是相当简单:
public static void StopBluetooth(){
   BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
   btAdapter.disable();
}
    BluetoothAdapter的disable()方法即可关闭蓝牙;

5、判断蓝牙的状态:
public static boolean isBluetoothEnabled(){
    BluetoothAdapter btAdapter = BluetoothAdapter.getDefaultAdapter();
    return btAdapter.isEnabled();
}

要进行蓝牙通信需要完成下面四个步骤:

  1. 设置蓝牙;
  2. 发现已经配对或者可用的附近的蓝牙设备;
  3. 连接设备;
  4. 在不同设备之间传输数据;

本文主要介绍如何使用Bluetooth APIs来完成上述四个步骤。

 

所有可用的Bluetooth APIs都包含在android.bluetooth包里。下面是创建蓝牙连接的类的总览:

BluetoothAdapter

代表本地的蓝牙适配器( local Bluetooth adapter) (Bluetooth radio). BluetoothAdapter是所有蓝牙通信的入口点。使用BluetoothAdapter,你能够探测其他蓝牙设备,获得一个bonded(已配对)的设备列表,使用一个知名的(know)MAC地址实例化一个BluetoothDevice,并创建一个BluetoothServerSocket来监听其他设备的通信。
BluetoothDevice
代表一个远程蓝牙设备,使用BluetoothSocket对另一个远程设备发出连接请求,或者查询该远程设备的名字、地址、类和连接状态。
BluetoothSocket
代表一个蓝牙socket的接口(类似于TCP socket)。这是应用程序通过InputStream或者OutputStream与其他蓝牙设备交换数据的连接点。
BluetoothServerSocket
表示一个开放的服务器socket,监听进入的连接请求(类似于TCP的ServerSocket)。为了连接两个Android设备,其中一个必须打开一个server socket。当一个远程蓝牙设备发出一个连接请求并被接受时,BluetoothServerSocket将返回一个已连接的BluetoothSocket。
 
BluetoothClass
描述了一个蓝牙设备的普通特性和能力,它提供了一系列描述一个设备的主要和次要设备类别和服务的只读属性。尽管这个类并不总是可靠地描述一个设备所有的蓝牙profile(配置)和所支持的服务,但它作为设备类型的一个提示是不错的

为了在应用程序中使用蓝牙功能,我们至少需要声明两方面的权限:BLUETOOTH和BLUETOOTH_ADMIN。

你必须请求BLUETOOTH权限才能够实现蓝牙通信,例如请求一个连接、接受一个连接和传输数据。

你必须请求BLUETOOTH_ADMIN权限,才能够初始化device discovery或者管理蓝牙设置(Bluetooth settings)。大多数应用程序必须具有这个权限才能够发现本地蓝牙设备,这个权限保护的其他能力(除了发现本地设备)不应该被使用,除非你的应用程序是在用户请求的时候能够修改蓝牙设置的管理者。

注意:如果你想要使用BLUETOOTH_ADMIN权限,那么你首先必须有BLUETOOTH权限。

你需要在应用程序的manifest文件中声明程序的蓝牙权限。例如:

  1. <manifest ... >  
  2.   <uses-permission android:name="android.permission.BLUETOOTH" />  
  3.   ...  
  4. </manifest>  

[xhtml:firstline[1]]  view plain copy
  1. <manifest ... >  
  2.   <uses-permission android:name="android.permission.BLUETOOTH" />  
  3.   ...  
  4. </manifest>  

关于声明应用程序权限的信息,请看<uses-permission>参考。

 

设置蓝牙

  Figure 1: The enabling Bluetooth dialog.

 

在你的应用程序使用蓝牙进行通信之前,你需要确认你的设备支持蓝牙,如果支持,那么确认它已被启动。

如果你的设备不支持蓝牙,那么你应该关闭任何蓝牙特性。如果蓝牙被支持,那么你可以在你的程序中要求用户启动蓝牙。这需要两个步骤,并且要使用BluetoothAdapter这个类。

如果你的设备不支持蓝牙,那么要关闭任何蓝牙功能。如果支持蓝牙但没有启动,则你可以在程序中要求用户启动蓝牙。启动蓝牙需要两个步骤,并且需要BluetoothAdapter类。

 

  1. 获得BluetoothAdapter类

    任何蓝牙activity都需要BluetoothAdapter类。使用静态方法getDefaultAdapter()获得一个BluetoothAdapter的实例,这代表了设备本身的蓝牙适配器(the Bluetooth radio)。整个系统只有一个蓝牙适配器,你的程序可以通过获取到BluetoothAdapter实例与之交互。如果getDefaultAdapter()方法返回null则说明你的设备不支持蓝牙。

           示例代码如下:

         

  1. BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) {    // Device does not support Bluetooth}  
[java:firstline[1]]  view plain copy
  1. BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();if (mBluetoothAdapter == null) {    // Device does not support Bluetooth}  

        

    2.启动蓝牙

       接下来,你必须确保用户启动了蓝牙。调用isEnabled()方法来检查当前蓝牙是否启动。如果该方法返回false,那么说明蓝牙没有启动。这时需要使用“ACTION_REQUEST_ENABLE”action Intent作为参数,调用startActivityForResult()方法来请求启动蓝牙。这将通过系统设备来发出启动蓝牙的请求(不会停止你的程序)。例如:

 

  1. if (!mBluetoothAdapter.isEnabled()) {    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}  
[java:firstline[1]]  view plain copy
  1. if (!mBluetoothAdapter.isEnabled()) {    Intent enableBtIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE);    startActivityForResult(enableBtIntent, REQUEST_ENABLE_BT);}  

执行如上的代码将会弹出一个对话框,请求启动蓝牙的用户权限,如Figure 1所示。如果用户点击“Yes”按钮,那么系统将开始启动蓝牙,启动蓝牙(有可能失败)之后你的程序将重新获得焦点。

如果启动蓝牙成功,你的Activity将在onActivityResult()回调函数中接收到一个RESULT_OK结果码。如果蓝牙启动失败或者用户不允许启动蓝牙,则会收到RESULT_CANCELED。

可选的,你的程序能够监听ACTION_STATE_CHANGED broadcast Intent,这个广播Intent是系统探测到蓝牙状态改变时发出的。这个广播Intent包含了EXTRA_STATE和EXTRA_PREVIOUS_STATE两个域,包含了蓝牙旧的和新的状态。这两个域的值可能是STATE_TURNING_ON,STATE_ON,STATE_TURNING_OFF和STATE_OFF。

 

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.

使用BluetoothAdapter,你能够通过设备发现(device discovery)或者通过查询配对设备的列表来发现远程蓝牙设备。

设备发现(Device discovery)是搜查本地启动蓝牙的设备,然后请求该设备一些信息的一个扫描过程(有时,这被称为“discovering”,“inquiring”或者“scannig”)。但是,本地蓝牙设备只有在启动蓝牙的时候才会对发现请求作出响应。如果一个设备被发现,它将通过共享一些信息,如设备名称、类别和唯一的MAC地址,来对发现请求作出响应。使用这些信息,执行设备发现请求动作的设备就能够初始化一个连接,对被发现的设备发出连接请求。

如果一个远程设备第一次请求连接,那么接收到连接请求的设备会自动发送一个配对请求。如果一个设备已经被配对,那么关于该设备的基本信息(设备名称、类别和MAC地址)将会被保存,并且能用Bluetooth APIs读取。知道了一个远程设备的MAC地址之后,就可以使用该MAC地址在任何时间初始化一个连接,无需再执行device discovery(假设该设备在距离范围之内)。

在被配对和被连接之间是有区别的。被配对意味着两个设备彼此知道对方的存在,有一个连接key被用于认证,能够建立一条加密的连接。被连接意味着设备当前共享一个RFCOMM渠道并且能够传输数据给对方。Android Bluetooth APIs要求设备在建立RFCOMM连接之前要先配对。配对是在你使用Bluetooth APIs建立一个加密连接的时候自动执行的。

下面的章节将描述发现已经配对的设备,或者,使用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.

查询配对设备

在执行device discovery之前,最好在已配对的设备列表中查看所要发现的设备是否已经存在。通过调用getBondedDevices()函数可以获得代表已经配对的设备的BluetoothDevice集合。 例如,你可以查询所有已经配对的设备,然后通过一个ArrayAdapter添加和显示每个设备的名字给用户:

  1. Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();  
  2. // If there are paired devices   
  3. if (pairedDevices.size() > 0) {     
  4.  // Loop through paired devices       
  5. for (BluetoothDevice device : pairedDevices) {          
  6. // Add the name and address to an array adapter to show in a ListView    
  7. mArrayAdapter.add(device.getName() + "/n" + device.getAddress());    }}  
[java:firstline[1]]  view plain
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值