Android开发之蓝牙详解(三)

一.概述

这是蓝牙开发的第三篇文章,同时也是最后一篇文章,因为内容有点多,所以分为了三篇来介绍。

二.基础

1.管理连接
当你成功的连接了两个(或更多)设备时,每一个设备都有一个被连接的BluetoothSocket对象。这是良好的开始,因为你能够在设备之间共享数据。使用BluetoothSocket对象来传输任意数据的过程是简单的:

  1. 分别通过getInputStream()和getOutputStream()方法来获得通过套接字来处理传输任务的InputStream和OutputStream对象;
  2. 用read(byte[])和write(byte[])方法来读写流中的数据。
    当然,有更多实现细节要考虑。首先和前提,对于所有数据流的读写应该使用专用的线程。这是重要的,因为read(byte[])和write(byte[])方法是阻塞式调用。Read(byte[])方法在从数据流中读取某些数据之前一直是阻塞的。write(byte[])方法通常是不阻塞的,但是对于流的控制,如果远程设备不是足够快的调用read(byte[])方法,并且中间缓存被填满,那么write(byte[])方法也会被阻塞。因此,你的线程中的主循环应该是专用于从InputStream对象中读取数据。在线程类中有一个独立的公共方法用于初始化对OutputStream对象的写入操作。
public class MainActivity extends ActionBarActivity {
    private Handler mHandler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
        }
    };
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }
    public class ConnectThread extends Thread{
        public static final int MESSAGE_READ = 1;
        private BluetoothSocket mSocket;
        private InputStream mInputStream;
        private OutputStream mOutputSteam;
        public ConnectThread(BluetoothSocket socket){
            mSocket = socket;
            try {
                //获得输入输出流
                mInputStream = socket.getInputStream();
                mOutputSteam = socket.getOutputStream();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        @Override
        public void run() {
            super.run();
            byte[] buffer = new byte[2014];//存储流的缓存
            int bytes;//从read()返回的字节
            //不断监听输入流直到异常发生
            while(true){
                try {
                    bytes = mInputStream.read(buffer);//从输入流读
                    mHandler.obtainMessage(MESSAGE_READ,bytes,-1,buffer).sendToTarget();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        /**
         * 发送数据给远程设备
         * @param bytes
         */
        public void write(byte[] bytes){
            try {
                mOutputSteam.write(bytes);
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        /**
         * 关闭连接
         */
        public void cancel(){
            try {
                mSocket.close();
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

上例中,构造器用于获取必要的流对象,并且一旦被执行,线程就会等待通过InputStream对象传入的输入。当read(byte[])方法从数据流中返回指定字节的数据时,使用来自其父类的Handler把该数据会被发送给主Activity,然后返回继续等待流中的更多的字节。
发送输出数据就像在主Activity中调用线程的write()方法一样简单,并且给该方法传入要发送的字节。然后这个方法简单的调用write(byte[])方法把数据发送给远程设备。
线程的cancel()方法是至关重要的,以便该连接在任何时候能够通过关闭BluetoothSocket对象来终止。这个方法在使用完蓝牙连接时应该始终被调用。

使用配置来工作
从Android3.0开始,蓝牙API就包含了对用蓝牙配置来进行工作的支持。Bluetooth Profile是设备之间基于蓝牙进行通信的无线接口规范。其中一个示例是Hands-Free配置。对于一个连接到无线耳机的移动电话,移动电话和蓝牙耳机都必须支持Hands-Free配置。
你能够实现BluetoothProfile接口,来编写你自己的支持特殊蓝牙配置的类。Android蓝牙API提供了对以下蓝牙配置的实现:
· Headset(耳机):该配置提供了对用于移动电话的蓝牙耳机的支持。Android提供了BluetoothHeadset类,这个类是一个代理,它通过进程间通信(IPC)来控制蓝牙耳机服务。它包含了Bluetoot Headset和Hands-Free(v1.5)配置。BluetoothHeadset类包含了对AT命令的支持。关于AT命令的更多讨论,请看“Vendor-specific AT commands”。
· A2DP:Advanced Audio Distribution Profile的缩写。它定义如何流化高品质的音频,并让音频流在通过蓝牙连接在设备之间传输。Android提供了BluetoothA2dp类,它一个通过IPC来控制的蓝牙A2DP服务的代理。
· Health Device:Android4.0(API Level 14)中引入了对Bluetooth Health Device Profile(HDP)的支持。它能够让你创建一个跟支持蓝牙的健康保健设备进行蓝牙通信的应用程序,这些健康保健包括:心率监护仪、血压测量仪、体温计、体重秤等。对应它支持的设备的列表和它们相应的设备数据规范,蓝牙联盟的网站:www.bluetooth.org。注意,这些值也是参考了ISO/IEEE11073-20601[7]规范中命名编码规范附件中的名为MDC_DEV_SPEC_PROFILE_*规范。
以下是使用配置进行工作的基本步骤
1. 获取默认的适配器;
2.使用getProfileProxy()方法来建立一个与配置相匹配的配置代理对象的连接。在下面的示例中,配置代理对象是一个BluetoothHeadset对象实例;
3.创建一个BluetoothProfile.ServiceListener监听器,该监听器会在它们连接到服务器或中断与服务器的连接时,通知BluetoothProfile的IPC客户端。
4.在onServiceConnected()事件中,获得对配置代理对象的处理权;
5.一旦获得配置代理对象,就可以用它来监视连接的状态,并执行与配置有关的其他操作。
例如,以下代码片段显示如何连接一个BluetoothHeadset代理对象,以便控制Headset配置

public class MainActivity extends ActionBarActivity {
    private BluetoothHeadset headset;
    BluetoothAdapter adapter = BluetoothAdapter.getDefaultAdapter();
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        adapter.getProfileProxy(this,listener,BluetoothProfile.HEADSET);
    }
    BluetoothProfile.ServiceListener listener = new BluetoothProfile.ServiceListener() {
        @Override
        public void onServiceConnected(int profile, BluetoothProfile proxy) {
            if(profile == BluetoothProfile.HEADSET){
                headset = (BluetoothHeadset) proxy;
            }
        }
        @Override
        public void onServiceDisconnected(int profile) {
            headset = null;
        }
    };
    //调用headset的功能
    /**
     * 使用完毕关闭连接协议
     */
    public void cancel(){
        adapter.closeProfileProxy(headset);
    }
}

健康设备配置
Android4.0(APILevel 14)中引入了对Bluetooth Health Device Profile(HDP)支持,这回让你创建跟支持蓝牙的健康设备进行蓝牙通信的应用程序,如心率监护仪、血压测量仪、体温计、体重秤等。Bluetooth Health API包含了BluetoothHealth、BluetoothHealthCallbackhe和BluetoothHealthAppConfiguration等类。
在使用的Bluetooth Health API中,有助于理解以下关键的HDP概念:
概念
介绍
Source
HDP中定义的一个角色,一个Source是一个把医疗数据(如体重、血弹、体温等)传输给诸如Android手机或平板电脑等的设备,
Sink
HDP中定义的一个角色,在HDP中,一个Sink是一个接收医疗数据的小设备。在一个Android HDP应用程序中,Sink用BluetoothHealthAppConfiguration对象来代表。
Registration
指的是给特定的健康设备注册一个Sink。
Connection
指的是健康设备和Android手机或平板电脑之间打开的通信通道。
创建HDP应用程序
以下是创建Android HDP应用中所涉及到的基本步骤:
1. 获得BluetoothHealth代理对象的引用。
类似于常规的耳机和A2DP配置设备,必须调用带有BluetoothProfile.ServiceListener和HEALTH配置类型参数的getProfileProxy()方法来建立与配置代理对象的连接,
2. 创建BluetoothHealthCallback对象,并注册一个扮演Health Sink角色的应用程序配(BluetoothHealthAppConfiguration)。
3. 建立跟健康设备的连接。某些设备会初始化连接,在这样的设备中进行这一个步是没有必要的。
4. 当成功的连接到健康设备时,就可以使用文件描述来读写健康设备。所接收到的数据需要使用健康管理器来解释,这个管理器实现了IEEE 11073-xxxxx规范。
5. 完成以上步骤后,关闭健康通道,并注销应用程序。该通道在长期被闲置时,也会被关闭。

最后给出代码供大家下载学习
Android蓝牙开发客户端代码

蓝牙服务端代码

你可能感兴趣的:(蓝牙开发)