Android无线蓝牙开发总结

Android无线蓝牙开发总结

2016年12月25日 17:06:21 峥嵘life 阅读数:4091 标签: android蓝牙通信 更多

个人分类: android

版权声明:本文为博主原创文章。只要评论中留言就可以转载。 https://blog.csdn.net/wenzhi20102321/article/details/53870789

一.蓝牙基础知识

      蓝牙(Bluetooth)是一种短距离的无线通信技术标准。这个名子来源于10世纪丹麦国王Harald Blatand,英文名子是Harold Bluetooth。

(一)蓝牙的四层协议

      蓝牙协议分为4层,即核心协议层、电缆替代协议层、电话控制协议层和采纳的其它协议层。这4种协议中最重要的是核心协议。蓝牙的核心协议包括基带、链路管理、逻辑链路控制和适应协议四部分。其中链路管理(LMP)负责蓝牙组件间连接的建立。逻辑链路控制与适应协议(L2CAP)位于基带协议层上,属于数据链路层,是一个为高层传输和应用层协议屏蔽基带协议的适配协议。

(二)蓝牙的操作

Android提供蓝牙API来执行这些不同的操作。 
1. 开关蓝牙 
2. 扫描其他蓝牙设备 
3. 获取配对设备列表 
4. 连接到通过服务发现其他设备

(三)蓝牙权限

1. android.permission.BLUETOOTH:

      允许程序连接到已配对的蓝牙设备,请求连接/接收连接/传输数据需要改权限, 主要用于对配对后进行操作;

2. android.permission.BLUETOOTH_ADMIN :

      允许程序发现和配对蓝牙设备, 该权限用来管理蓝牙设备, 有了这个权限, 应用才能使用本机的蓝牙设备, 主要用于对配对前的操作;

(四)BluetoothAdapter

      BluetoothAdapter代表了移动设备的本地的蓝牙适配器, 通过该蓝牙适配器可以对蓝牙进行基本操作 
BluetoothAdapter.getDefaultAdapter()该静态方法可以获取该适配器对象.

(五)蓝牙的BluetoothAdapter .STATE 状态值 , 即开关状态

1.蓝牙关闭 int STATE_OFF //值为10, 蓝牙模块处于关闭状态; 
2.蓝牙打开中 int STATE_TURNING_ON //值为11, 蓝牙模块正在打开; 
3.蓝牙开启 int STATE_ON //值为12, 蓝牙模块处于开启状态; 
4. 蓝牙开启中 int STATE_TURNING_OFF //值为13, 蓝牙模块正在关闭; 
蓝牙开关状态顺序 : STATE_OFF –> STATE_TURNING_ON –> STATE_ON –>STATE_TURNING_OFF –> STATE_OFF;

(六)BluetoothAdapter SCAN_MOD状态值 ,即扫描状态

  1. 无功能状态 : int SCAN_MODE_NONE //值为20, 查询扫描和页面扫描都失效, 
    该状态下蓝牙模块既不能扫描其它设备, 也不可见;
  2. 扫描状态 : int SCAN_MODE_CONNECTABLE //值为21, 查询扫描失效, 页面扫描有效, 
    该状态下蓝牙模块可以扫描其它设备, 从可见性来说只对已配对的蓝牙设备可见, 只有配对的设备才能主动连接本设备;
  3. 可见状态 : int SCAN_MODE_CONNECTABLE_DISCOVERABLE //值为23, 查询扫描和页 
    面扫描都有效;

(七)打开/关闭蓝牙的两种方法:

1.直接调用函数enable()去打开蓝牙设备 ;

2.系统API去打开蓝牙设备,该方式会弹出一个对话框样式的Activity供用户选择是否打开蓝牙设备。

代码示例:

<span style="color:#000000"><code><span style="color:#880000">//第一种启动蓝牙的方法,不推荐</span>
<span style="color:#880000">//bluetoothAdapter.enable();</span>
<span style="color:#880000">//第二种启动蓝牙的方法,推荐</span>
startActivityForResult(<span style="color:#000088">new</span> Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), REQUEST_ENABLE);
<span style="color:#880000">//第二种方法要写数据回调方法</span>
<span style="color:#880000">/**
 * 数据回调方法
 */</span>
<span style="color:#9b859d">@Override</span>
<span style="color:#000088">protected</span> <span style="color:#000088">void</span> <span style="color:#009900">onActivityResult</span>(<span style="color:#000088">int</span> requestCode, <span style="color:#000088">int</span> resultCode, Intent data) {
    <span style="color:#000088">super</span>.onActivityResult(requestCode, resultCode, data);
    <span style="color:#000088">if</span> (requestCode == REQUEST_ENABLE) {
        <span style="color:#000088">if</span> (resultCode == RESULT_OK) {
            Toast.makeText(<span style="color:#000088">this</span>, <span style="color:#009900">"蓝牙已开启"</span>, Toast.LENGTH_SHORT).show();
           <span style="color:#880000">// getMyBondedDevices();//获取绑定的蓝牙设备</span>
            adapter.notifyDataSetChanged();<span style="color:#880000">//刷新适配器</span>
        } <span style="color:#000088">else</span> {
            Toast.makeText(<span style="color:#000088">this</span>, <span style="color:#009900">"蓝牙未开启"</span>, Toast.LENGTH_SHORT).show();
        }
    } 
}</code></span>
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21

(八)关闭蓝牙,直接调用API 函数即disable()即可。

public boolean disable () 
返回值:该函数会立即返回。 
1.true 表示关闭操作成功 
2. false 表示蓝牙操作失败 , ①、当前蓝牙已经关闭 ; ②、其他一些异常情况

(九)扫描蓝牙设备

<span style="color:#000000"><code>  1.public boolean startDiscovery () 
      功能: 扫描蓝牙设备的开启
      注意: 如果蓝牙没有开启,该方法会返回false ,即不会开始扫描过程。

  2.public  boolean cancelDiscovery ()
     功能: 取消扫描过程。
     注意: 如果蓝牙没有开启,该方法会返回false。

 3.public boolean isDiscovering ()
    功能: 是否正在处于扫描过程中。
    注意: 如果蓝牙没有开启,该方法会返回false。
</code></span>


      这里要特别注意,蓝牙扫描的时候,它会发出系统的广播,这是我们就要创建广播接收者来接收数据,数据里面就有蓝牙的设备对象和名称等等,广播也是蓝牙知识的重中之重。 

(十)蓝牙的广播

Action值 说明
ACTION_STATE_CHANGED 蓝牙状态值发生改变
*ACTION_SCAN_MODE_CHANGED 蓝牙扫描状态(SCAN_MODE)发生改变*
ACTION_DISCOVERY_STARTED 蓝牙扫描过程开始
ACTION_DISCOVERY_FINISHED 蓝牙扫描过程结束
ACTION_LOCAL_NAME_CHANGED 蓝牙设备Name发生改变
ACTION_REQUEST_DISCOVERABLE 请求用户选择是否使该蓝牙能被扫描

      PS:如果蓝牙没有开启,用户点击确定后,会首先开启蓝牙,继而设置蓝牙能被扫描。 
Action值: ACTION_REQUEST_ENABLE // 请求用户选择是否打开蓝牙 
示例: 
创建广播接收者:

<span style="color:#000000"><code><span style="color:#880000">/**
 * 广播接收者的创建
 */</span>
<span style="color:#000088">private</span> BroadcastReceiver receiver = <span style="color:#000088">new</span> BroadcastReceiver() {
    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">onReceive</span>(Context context, Intent intent) {
        <span style="color:#880000">//获取设备的发送的广播</span>
        <span style="color:#880000">//做数据处理</span>
     }
};</code></span>

注册广播接收者

<span style="color:#000000"><code><span style="color:#880000">/**
 * 广播的注册,注意这里Action可以添加多个
 */</span>
<span style="color:#9b859d">@Override</span>
<span style="color:#000088">protected</span> <span style="color:#000088">void</span> <span style="color:#009900">onResume</span>() {
    <span style="color:#000088">super</span>.onResume();
<span style="color:#880000">//添加蓝牙广播的Action,发现蓝牙设备时的Action</span>
    IntentFilter intentFilter = <span style="color:#000088">new</span> 
IntentFilter(BluetoothDevice.ACTION_FOUND);
<span style="color:#880000">//添加蓝牙广播的Action,蓝牙设备扫描完毕时的Action </span>
intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
    registerReceiver(receiver, intentFilter);<span style="color:#880000">//注册广播接收者</span>
}</code></span>

广播的注销

<span style="color:#000000"><code><span style="color:#880000">/**
 * 广播的停止
 */</span>
<span style="color:#9b859d">@Override</span>
<span style="color:#000088">protected</span> <span style="color:#000088">void</span> <span style="color:#009900">onPause</span>() {
    <span style="color:#000088">super</span>.onPause();
    unregisterReceiver(receiver);<span style="color:#880000">//取消广播</span>
}</code></span>

      一般监听发现蓝牙和蓝牙扫描完成的广播就可以了。 
      通过广播接收数据后,再对数据进行处理。就可以看到我们手机上显示的蓝牙设设备名称和其他信息。

(十一)获取蓝牙的相关信息的方法

1.public String getName ()

功能:获取蓝牙设备Name

2.public String getAddress ()

功能:获取蓝牙设备的硬件地址(MAC地址),例如:00:11:22:AA:BB:CC

3.public boolean setName (String name)

功能:设置蓝牙设备的Name。

4.public SetgetBondedDevices ()

功能:获取与本机蓝牙所有绑定的远程蓝牙信息,以BluetoothDevice类实例(稍后讲到)返回。 
注意:如果蓝牙未开启,该函数会返回一个空集合 。

5.public static boolean checkBluetoothAddress (String address)

<span style="color:#000000"><code> 功能: 验证蓝牙设备MAC地址是否有效。所有设备地址的英文字母必须大写,48位,形如:00:43:A8:23:10:F1 。
</code></span>
  • 1

返回值: true 设备地址有效,false 设备地址无效

6.public BluetoothDevice getRemoteDevice (String address)

功能:以给定的MAC地址去创建一个 BluetoothDevice 类实例(代表远程蓝牙实例)。即使该蓝牙地址不可见,也会产生 一个BluetoothDevice 类实例。 
返回:BluetoothDevice 类实例 。注意,如果该蓝牙设备MAC地址不能被识别,其蓝牙Name为null。 
异常:如果MAC address无效,抛出IllegalArgumentException。

      使用上面的方法就可以对蓝牙进行扫描显示。但是要使用蓝牙通信就要使用到Socket编程了。

二.蓝牙Socket通信

      关于Socket编程,之前有一篇java的简介和使用示例: 
http://blog.csdn.net/wenzhi20102321/article/details/52620323

(一)UUID

      在蓝牙中,每个服务和服务属性都唯一地由 全局唯一标识符 ,Universally Unique Identifier(UUID)来校验。正如它的名字所暗示的,每一个这样的标识符都要在时空上保证唯一。UUID类可表现为短整形(16或32位)和长整形(128 位)UUID。他提供了分别利用String和16位或32位数值来创建类的构造函数,提供了一个可以比较两个UUID(如果两个都是128位)的方法,还有一个可以转换一个UUID为一个字符串的方法。UUID实例是不可改变的(immutable),只有被UUID标示的服务可以被发现。 
      UUID的格式被分成5段,其中中间3段的字符数相同,都是4个,第1段是8个字符,最后一段是12个字符。所以UUID实际上是8个-4个-4个-4个-12个的字符串。 

      UUID相当于Socket的端口,而蓝牙地址相当于Socket的IP。两个蓝牙设备进行连接时需要使用同一个UUID, 这是一个服务的唯一标识,而且这个UUID的值必须是 
00001101-0000-1000-8000-00805F9B34FB 


      上面这个UUID,直接复制使用就可以了。

下面是蓝牙Socket使用示例:

三.蓝牙Socket通信示例

      程序实现两台手机的蓝牙发送消息,并接受消息。这里的蓝牙是不需要网络支持的。 
程序运行后,扫描蓝牙后的界面: 
Android无线蓝牙开发总结 
程序进行通信后的界面,要两个手机哦! 
Android无线蓝牙开发总结 
      两个手机,其中一个设置为服务器,然后点击连接的手机,就可以进行消息发送和接收了。 
上面只是实现文本通信,文本也只是进行简单处理。

程序设计代码:

(一)添加权限

<span style="color:#000000"><code><span style="color:#006666"><<span style="color:#4f4f4f">uses-permission</span> <span style="color:#4f4f4f">android:name</span>=<span style="color:#009900">"android.permission.BLUETOOTH_ADMIN"</span> /></span>
<span style="color:#006666"><<span style="color:#4f4f4f">uses-permission</span> <span style="color:#4f4f4f">android:name</span>=<span style="color:#009900">"android.permission.BLUETOOTH"</span> /></span>
<span style="color:#880000"><!--6.0以上才要加的额外权限 --></span>
<span style="color:#006666"><<span style="color:#4f4f4f">uses-permission</span> <span style="color:#4f4f4f">android:name</span>=<span style="color:#009900">"android.permission.ACCESS_COARSE_LOCATION"</span> /></span></code></span>

(二)布局文件的设计

<span style="color:#000000"><code><span style="color:#006666"><?xml version="1.0" encoding="utf-8"?></span>
<span style="color:#006666"><<span style="color:#4f4f4f">LinearLayout</span> <span style="color:#4f4f4f">xmlns:android</span>=<span style="color:#009900">"http://schemas.android.com/apk/res/android"</span>
    <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
    <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"match_parent"</span>
    <span style="color:#4f4f4f">android:orientation</span>=<span style="color:#009900">"vertical"</span>></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">Button
</span>        <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
        <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
        <span style="color:#4f4f4f">android:onClick</span>=<span style="color:#009900">"open"</span>
        <span style="color:#4f4f4f">android:text</span>=<span style="color:#009900">"开启蓝牙"</span> /></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">Button
</span>        <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
        <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
        <span style="color:#4f4f4f">android:onClick</span>=<span style="color:#009900">"close"</span>
        <span style="color:#4f4f4f">android:text</span>=<span style="color:#009900">"关闭蓝牙"</span> /></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">Button
</span>        <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
        <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
        <span style="color:#4f4f4f">android:onClick</span>=<span style="color:#009900">"found"</span>
        <span style="color:#4f4f4f">android:text</span>=<span style="color:#009900">"暴露自己的设备名称"</span> /></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">Button
</span>        <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
        <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
        <span style="color:#4f4f4f">android:onClick</span>=<span style="color:#009900">"scan"</span>
        <span style="color:#4f4f4f">android:text</span>=<span style="color:#009900">"扫描蓝牙设备"</span> /></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">Button
</span>        <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
        <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
        <span style="color:#4f4f4f">android:onClick</span>=<span style="color:#009900">"createServer"</span>
        <span style="color:#4f4f4f">android:text</span>=<span style="color:#009900">"设置为蓝牙服务端"</span> /></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">Button
</span>        <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
        <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
        <span style="color:#4f4f4f">android:onClick</span>=<span style="color:#009900">"listen"</span>
        <span style="color:#4f4f4f">android:text</span>=<span style="color:#009900">"监听数据的接收"</span> /></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">LinearLayout
</span>        <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
        <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
        <span style="color:#4f4f4f">android:orientation</span>=<span style="color:#009900">"horizontal"</span>></span>

        <span style="color:#006666"><<span style="color:#4f4f4f">EditText
</span>            <span style="color:#4f4f4f">android:id</span>=<span style="color:#009900">"@+id/et_send"</span>
            <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"0dp"</span>
            <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
            <span style="color:#4f4f4f">android:layout_weight</span>=<span style="color:#009900">"2"</span>
            <span style="color:#4f4f4f">android:singleLine</span>=<span style="color:#009900">"true"</span> /></span>

        <span style="color:#006666"><<span style="color:#4f4f4f">Button
</span>            <span style="color:#4f4f4f">android:id</span>=<span style="color:#009900">"@+id/btn_send"</span>
            <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"0dp"</span>
            <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
            <span style="color:#4f4f4f">android:layout_weight</span>=<span style="color:#009900">"1"</span>
            <span style="color:#4f4f4f">android:onClick</span>=<span style="color:#009900">"send"</span>
            <span style="color:#4f4f4f">android:text</span>=<span style="color:#009900">"send"</span> /></span>
    <span style="color:#006666"></<span style="color:#4f4f4f">LinearLayout</span>></span>

    <span style="color:#006666"><<span style="color:#4f4f4f">ScrollView
</span>        <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
        <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"match_parent"</span>></span>

        <span style="color:#006666"><<span style="color:#4f4f4f">LinearLayout
</span>            <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
            <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"match_parent"</span>
            <span style="color:#4f4f4f">android:orientation</span>=<span style="color:#009900">"vertical"</span>></span>

            <span style="color:#006666"><<span style="color:#4f4f4f">TextView
</span>                <span style="color:#4f4f4f">android:id</span>=<span style="color:#009900">"@+id/tv_show"</span>
                <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
                <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span> /></span>

            <span style="color:#006666"><<span style="color:#4f4f4f">TextView
</span>                <span style="color:#4f4f4f">android:id</span>=<span style="color:#009900">"@+id/tv_show_service"</span>
                <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
                <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"wrap_content"</span>
                <span style="color:#4f4f4f">android:gravity</span>=<span style="color:#009900">"right"</span> /></span>

            <span style="color:#006666"><<span style="color:#4f4f4f">ListView
</span>                <span style="color:#4f4f4f">android:id</span>=<span style="color:#009900">"@+id/lv"</span>
                <span style="color:#4f4f4f">android:layout_width</span>=<span style="color:#009900">"match_parent"</span>
                <span style="color:#4f4f4f">android:layout_height</span>=<span style="color:#009900">"200dp"</span> /></span>
        <span style="color:#006666"></<span style="color:#4f4f4f">LinearLayout</span>></span>
    <span style="color:#006666"></<span style="color:#4f4f4f">ScrollView</span>></span>
<span style="color:#006666"></<span style="color:#4f4f4f">LinearLayout</span>></span></code></span>

(三)可读写流的类

<span style="color:#000000"><code><span style="color:#000088">package</span> fuxi.bluetooth20;

<span style="color:#000088">import</span> android.bluetooth.BluetoothSocket;
<span style="color:#000088">import</span> android.util.Log;

<span style="color:#000088">import</span> java.io.InputStream;
<span style="color:#000088">import</span> java.io.OutputStream;

<span style="color:#880000">/**
 * 在子线程中进行读写操作
 */</span>
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">RWStream</span> <span style="color:#000088">extends</span> <span style="color:#4f4f4f">Thread</span> {

    InputStream is;<span style="color:#880000">//输入流</span>
    OutputStream os;<span style="color:#880000">//输出流</span>

    <span style="color:#880000">//蓝牙的Socket对象</span>
    <span style="color:#000088">private</span> <span style="color:#000088">final</span> BluetoothSocket socket;

    <span style="color:#880000">//通过构造方法传入Socket对象</span>
    <span style="color:#000088">public</span> <span style="color:#009900">RWStream</span>(BluetoothSocket socket) {
        <span style="color:#000088">this</span>.socket = socket;
    }

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">run</span>() {
        <span style="color:#000088">super</span>.run();
        <span style="color:#000088">try</span> {
            is = socket.getInputStream();<span style="color:#880000">//获取Socket的输入流</span>
            os = socket.getOutputStream();<span style="color:#880000">//获取Socket的输出流</span>

            <span style="color:#000088">byte</span>[] buf = <span style="color:#000088">new</span> <span style="color:#000088">byte</span>[<span style="color:#006666">1024</span>];
            <span style="color:#000088">int</span> len = <span style="color:#006666">0</span>;
            Log.e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"-----------开始读取----(is==null)   "</span> + (is == <span style="color:#000088">null</span>));
            <span style="color:#000088">while</span> (socket.isConnected()) {<span style="color:#880000">//当Socket是连接状态时,就一直进行数据的读取</span>
                <span style="color:#000088">while</span> ((len = is.read(buf)) != -<span style="color:#006666">1</span>) {
                    String message = <span style="color:#000088">new</span> String(buf, <span style="color:#006666">0</span>, len);
                    <span style="color:#880000">//获取流里面的数据</span>
                    Log.e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"----------"</span> + message);
                    <span style="color:#880000">//如果在另一端设置的接口对象,那么就传递数据</span>
                    <span style="color:#000088">if</span> (dateShow != <span style="color:#000088">null</span>) {
                        dateShow.getMessager(message);
                    }
                }
            }
        } <span style="color:#000088">catch</span> (Exception e) {
            Log.e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"-----------线程异常"</span>);
        }
    }

    <span style="color:#880000">/**
     * 数据的写入
     */</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">write</span>(String msg) {
        Log.e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"--------os!=null   "</span> + (os != <span style="color:#000088">null</span>));
        <span style="color:#000088">if</span> (os != <span style="color:#000088">null</span>) {
            <span style="color:#000088">try</span> {
                <span style="color:#880000">//Socket数据的写入</span>
                os.write(msg.getBytes());
                <span style="color:#880000">//刷新输出流数据</span>
                os.flush();
            } <span style="color:#000088">catch</span> (Exception e) {
                Log.e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"---写入--------异常"</span> + e.getMessage());
            }
        }
    }

    <span style="color:#880000">/**
     * 定义接口实现数据回调
     */</span>
    interface DataShow {
        <span style="color:#880000">//返回数据,读取到的字符串,传递过去</span>
        <span style="color:#000088">void</span> getMessager(String message);

    }

    <span style="color:#880000">//定义接口对象</span>
    DataShow dateShow;

    <span style="color:#880000">//接口的对象的设置方法</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">setDataShow</span>(DataShow dateShow) {
        <span style="color:#000088">this</span>.dateShow = dateShow;
    }
}</code></span>

(四)蓝牙服务器端(Socket服务端)的设计

<span style="color:#000000"><code><span style="color:#000088">package</span> fuxi.bluetooth20;

<span style="color:#000088">import</span> android.bluetooth.BluetoothAdapter;
<span style="color:#000088">import</span> android.bluetooth.BluetoothServerSocket;
<span style="color:#000088">import</span> android.bluetooth.BluetoothSocket;
<span style="color:#000088">import</span> android.util.Log;

<span style="color:#000088">import</span> java.io.IOException;

<span style="color:#880000">/**
 * 蓝牙设置的服务器端
 */</span>

<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">BlueServer</span> <span style="color:#000088">extends</span> <span style="color:#4f4f4f">Thread</span> {
    <span style="color:#880000">//可读写数据的对象</span>
    RWStream rwStream;

    <span style="color:#000088">public</span> RWStream <span style="color:#009900">getRwStream</span>() {
        <span style="color:#000088">return</span> rwStream;
    }

    <span style="color:#880000">//蓝牙设备管理器</span>
    <span style="color:#000088">private</span> <span style="color:#000088">final</span> BluetoothAdapter adapter;

    <span style="color:#880000">//通过构造方法传入设置管理器</span>
    <span style="color:#000088">public</span> <span style="color:#009900">BlueServer</span>(BluetoothAdapter adapter) {
        <span style="color:#000088">this</span>.adapter = adapter;
    }

    <span style="color:#880000">//线程内的任务</span>
    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">run</span>() {
        <span style="color:#000088">super</span>.run();
        <span style="color:#000088">try</span> {
            <span style="color:#880000">//创建蓝牙服务端的Socket,这里第一个参数是服务器的名称,第二个参数是UUID的字符串的值</span>
            BluetoothServerSocket socket = adapter.listenUsingRfcommWithServiceRecord(<span style="color:#009900">"server"</span>, MainActivity.uuid);
            Log.e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"--------------->>开始监听客户端连接"</span>);
            <span style="color:#880000">//获取蓝牙客户端对象,这是一个同步方法,用客户端接入才有后面的操作</span>
            BluetoothSocket client = socket.accept();
            Log.e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"--------------->>有客户端接入"</span>);
            <span style="color:#880000">//获取可读可写对象</span>
            rwStream = <span style="color:#000088">new</span> RWStream(client);
            <span style="color:#880000">//开始可读可写线程的操作,这里是一直在读取数据的状态</span>
            rwStream.start();
        } <span style="color:#000088">catch</span> (IOException e) {
            e.printStackTrace();
        }

    }
}</code></span>

(五)主方法类的设计

<span style="color:#000000"><code><span style="color:#000088">package</span> fuxi.bluetooth20;

<span style="color:#000088">import</span> android.Manifest;
<span style="color:#000088">import</span> android.bluetooth.BluetoothAdapter;
<span style="color:#000088">import</span> android.bluetooth.BluetoothDevice;
<span style="color:#000088">import</span> android.bluetooth.BluetoothSocket;
<span style="color:#000088">import</span> android.content.BroadcastReceiver;
<span style="color:#000088">import</span> android.content.Context;
<span style="color:#000088">import</span> android.content.Intent;
<span style="color:#000088">import</span> android.content.IntentFilter;
<span style="color:#000088">import</span> android.content.pm.PackageManager;
<span style="color:#000088">import</span> android.graphics.Color;
<span style="color:#000088">import</span> android.os.Build;
<span style="color:#000088">import</span> android.os.Bundle;
<span style="color:#000088">import</span> android.os.Handler;
<span style="color:#000088">import</span> android.os.Message;
<span style="color:#000088">import</span> android.support.annotation.NonNull;
<span style="color:#000088">import</span> android.support.v7.app.AppCompatActivity;
<span style="color:#000088">import</span> android.text.TextUtils;
<span style="color:#000088">import</span> android.util.Log;
<span style="color:#000088">import</span> android.view.View;
<span style="color:#000088">import</span> android.widget.AdapterView;
<span style="color:#000088">import</span> android.widget.ArrayAdapter;
<span style="color:#000088">import</span> android.widget.Button;
<span style="color:#000088">import</span> android.widget.EditText;
<span style="color:#000088">import</span> android.widget.ListView;
<span style="color:#000088">import</span> android.widget.TextView;
<span style="color:#000088">import</span> android.widget.Toast;

<span style="color:#000088">import</span> java.io.IOException;
<span style="color:#000088">import</span> java.util.ArrayList;
<span style="color:#000088">import</span> java.util.List;
<span style="color:#000088">import</span> java.util.UUID;

<span style="color:#000088">import</span> <span style="color:#000088">static</span> android.util.Log.e;

<span style="color:#880000">/**
 * 蓝牙的使用示例
 */</span>
<span style="color:#000088">public</span> <span style="color:#000088">class</span> <span style="color:#4f4f4f">MainActivity</span> <span style="color:#000088">extends</span> <span style="color:#4f4f4f">AppCompatActivity</span> {

    <span style="color:#880000">//控制蓝牙设备的对象</span>
    BluetoothAdapter bluetoothAdapter;
    <span style="color:#880000">//布局内的ListView控件</span>
    ListView listView;
    TextView tv_show;
    TextView tv_show_service;
    EditText et_send;
    Button btn_send;
    ArrayAdapter adapter;<span style="color:#880000">//适配器对象的定义</span>
    <span style="color:#880000">//蓝牙设备的对象的集合</span>
    ArrayList<BluetoothDevice> devices = <span style="color:#000088">new</span> ArrayList<>();
    <span style="color:#880000">//设备的名称集合</span>
    ArrayList<String> deviceNames = <span style="color:#000088">new</span> ArrayList<>();
    <span style="color:#880000">//手机蓝牙的UUID固定值</span>
    <span style="color:#000088">public</span> <span style="color:#000088">static</span> <span style="color:#000088">final</span> UUID uuid = UUID.fromString(<span style="color:#009900">"00001101-0000-1000-8000-00805F9B34FB"</span>);
    <span style="color:#000088">private</span> <span style="color:#000088">static</span> <span style="color:#000088">final</span> <span style="color:#000088">int</span> REQUEST_LOCATION = <span style="color:#006666">1000</span>;<span style="color:#880000">//手机动态请求权限的请求码</span>
    <span style="color:#000088">private</span> <span style="color:#000088">static</span> <span style="color:#000088">final</span> <span style="color:#000088">int</span> REQUEST_ENABLE = <span style="color:#006666">1001</span>;<span style="color:#880000">//启动蓝牙设备的请求码</span>
    <span style="color:#000088">private</span> <span style="color:#000088">static</span> <span style="color:#000088">final</span> <span style="color:#000088">int</span> REQUEST_DISCOVER_MYSELF = <span style="color:#006666">1002</span>;<span style="color:#880000">//设置自身蓝牙设备可被发现的请求码</span>

    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">protected</span> <span style="color:#000088">void</span> <span style="color:#009900">onCreate</span>(Bundle savedInstanceState) {
        <span style="color:#000088">super</span>.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        <span style="color:#880000">//实例化</span>
        bluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
        listView = (ListView) findViewById(R.id.lv);
        tv_show = (TextView) findViewById(R.id.tv_show);
        tv_show_service = (TextView) findViewById(R.id.tv_show_service);
        et_send = (EditText) findViewById(R.id.et_send);
        btn_send = (Button) findViewById(R.id.btn_send);
        <span style="color:#880000">//创建适配器,使用系统布局</span>
        adapter = <span style="color:#000088">new</span> ArrayAdapter(<span style="color:#000088">this</span>, android.R.layout.simple_list_item_1, deviceNames);
        <span style="color:#880000">//给ListView设置适配器</span>
        listView.setAdapter(adapter);
        <span style="color:#880000">//判断是否有了权限</span>
        checkPermission();
        <span style="color:#880000">//给ListView设置点击事件,点击对应的条目就创建对应的客户端,并经行数据的读取和写入</span>
        listView.setOnItemClickListener(<span style="color:#000088">new</span> AdapterView.OnItemClickListener() {
            <span style="color:#9b859d">@Override</span>
            <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">onItemClick</span>(AdapterView<?> parent, View view, <span style="color:#000088">int</span> position, <span style="color:#000088">long</span> id) {
                <span style="color:#880000">//连接服务器</span>
                connServer(devices.get(position));
            }
        });


    }

    <span style="color:#880000">/**
     * 打开蓝牙设备
     */</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">open</span>(View view) {
        <span style="color:#880000">//不推荐</span>
        <span style="color:#880000">//bluetoothAdapter.enable();</span>
        <span style="color:#880000">//推荐</span>
        startActivityForResult(<span style="color:#000088">new</span> Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE), REQUEST_ENABLE);
    }

    <span style="color:#880000">/**
     * 关闭蓝牙设备
     */</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">close</span>(View view) {
        bluetoothAdapter.disable();<span style="color:#880000">//关闭</span>
        <span style="color:#880000">//擦除页面数据</span>
        deviceNames.clear();
        adapter.notifyDataSetChanged();
    }

    <span style="color:#880000">/**
     * 扫描蓝牙设备
     */</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">scan</span>(View view) {

        <span style="color:#000088">if</span> (bluetoothAdapter.isEnabled()) {
            <span style="color:#880000">//先清除页面数据!</span>
            devices.clear();
            deviceNames.clear();

            <span style="color:#880000">//使用广播的方法去获取设备,这里就要动态创建广播,并进行接听了</span>
            <span style="color:#880000">//定义一个系统规定action的广播,</span>
            <span style="color:#880000">//当系统没扫描到一个蓝牙设备就会发送一条广播</span>
            <span style="color:#880000">// 当系统做完扫描后,系统会发送广播,你只需在广播接收者做好处理</span>
            bluetoothAdapter.startDiscovery();
        } <span style="color:#000088">else</span> {
            Toast.makeText(<span style="color:#000088">this</span>, <span style="color:#009900">"请先开启蓝牙"</span>, Toast.LENGTH_SHORT).show();
        }
    }

    <span style="color:#880000">/**
     * 让自身蓝牙设备可被发现
     */</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">found</span>(View view) {
        getMyBondedDevices();
        <span style="color:#000088">if</span> (bluetoothAdapter.isDiscovering()) {<span style="color:#880000">//如果蓝牙设置正在扫描</span>
            Toast.makeText(<span style="color:#000088">this</span>, <span style="color:#009900">"正在扫描,别急"</span>, Toast.LENGTH_SHORT).show();
        } <span style="color:#000088">else</span> {
            <span style="color:#880000">//这里可以设置显示自己蓝牙设备的时间,默认是300秒,也可以自定义单位是秒</span>
            Intent intent = <span style="color:#000088">new</span> Intent(BluetoothAdapter.ACTION_REQUEST_DISCOVERABLE).putExtra(BluetoothAdapter.EXTRA_DISCOVERABLE_DURATION, <span style="color:#006666">600</span>);
            startActivityForResult(intent, REQUEST_DISCOVER_MYSELF);
        }
    }

    <span style="color:#880000">/**
     * 开启蓝牙服务的服务端
     */</span>
    <span style="color:#000088">boolean</span> isServer = <span style="color:#000088">false</span>;<span style="color:#880000">//默认是普通客户端</span>
    BlueServer server;<span style="color:#880000">//创建蓝牙服务器的对象,在服务器做相关操作</span>

    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">createServer</span>(View view) {
        server = <span style="color:#000088">new</span> BlueServer(bluetoothAdapter);
        server.start();
        isServer = <span style="color:#000088">true</span>;<span style="color:#880000">//设置为服务端</span>
    }

    <span style="color:#880000">/**
     * 发送数据
     */</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">send</span>(View view) {
        String et = et_send.getText().toString();<span style="color:#880000">//获取输入框的数据</span>
        <span style="color:#880000">//给另一端写入数据</span>
        write(et);
    }

    <span style="color:#880000">/**
     * 数据的传递
     */</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">write</span>(String msg) {
        <span style="color:#000088">if</span> (isServer) {<span style="color:#880000">//服务器的写数据</span>
            btn_send.setText(<span style="color:#009900">"服务器"</span>);
            handlerSendMessager(<span style="color:#006666">1</span>, msg);
            e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"----------(server != null && server.getRwStream() != null)  "</span> + (server != <span style="color:#000088">null</span> && server.getRwStream() != <span style="color:#000088">null</span>));
            <span style="color:#000088">if</span> (server != <span style="color:#000088">null</span> && server.getRwStream() != <span style="color:#000088">null</span>) {
                server.getRwStream().write(msg);
            }
        } <span style="color:#000088">else</span> {<span style="color:#880000">//客户端的写数据</span>
            btn_send.setText(<span style="color:#009900">"客户端"</span>);
            handlerSendMessager(<span style="color:#006666">2</span>, msg);
            <span style="color:#000088">if</span> (client != <span style="color:#000088">null</span>) {
                client.write(msg);
            }
        }
    }

    <span style="color:#880000">/**
     * 监听数据的接收
     */</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">listen</span>(View view) {

        <span style="color:#880000">//服务器的监听数据</span>
        <span style="color:#000088">if</span> (server != <span style="color:#000088">null</span>) {
            server.getRwStream().setDataShow(<span style="color:#000088">new</span> RWStream.DataShow() {
                <span style="color:#9b859d">@Override</span>
                <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">getMessager</span>(<span style="color:#000088">final</span> String message) {
                    <span style="color:#880000">//要在主线程中改变UI</span>
                    Log.e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"-------listen---Service"</span> + message);
                    handlerSendMessager(<span style="color:#006666">2</span>, message);
                }
            });
            <span style="color:#880000">//客户端的监听数据</span>
        } <span style="color:#000088">else</span> <span style="color:#000088">if</span> (client != <span style="color:#000088">null</span>) {
            client.setDataShow(<span style="color:#000088">new</span> RWStream.DataShow() {
                <span style="color:#9b859d">@Override</span>
                <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">getMessager</span>(<span style="color:#000088">final</span> String message) {
                    <span style="color:#880000">//要在主线程中改变UI</span>
                    e(<span style="color:#009900">"TAG"</span>, <span style="color:#009900">"-------listen---client"</span> + message);
                    handlerSendMessager(<span style="color:#006666">1</span>, message);
                }
            });
        }
    }

    <span style="color:#880000">/**
     * Handler包装类
     */</span>
    <span style="color:#000088">private</span> <span style="color:#000088">void</span> <span style="color:#009900">handlerSendMessager</span>(<span style="color:#000088">int</span> what, String messge) {
        Message msg = Message.obtain();
        msg.what = what;
        msg.obj = messge;
        handler.sendMessage(msg);
    }

    <span style="color:#880000">/**
     * 创建Handler对象用于线程间通信
     */</span>
    Handler handler = <span style="color:#000088">new</span> Handler() {
        <span style="color:#9b859d">@Override</span>
        <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">handleMessage</span>(Message msg) {
            <span style="color:#000088">super</span>.handleMessage(msg);
            <span style="color:#880000">//显示数据在文本中</span>
            <span style="color:#000088">if</span> (msg.what == <span style="color:#006666">1</span>) {
                <span style="color:#880000">//服务器的数据在右边</span>
                tv_show_service.setTextColor(Color.RED);
                tv_show_service.setTextSize(<span style="color:#006666">20</span>);
                tv_show_service.append(msg.obj + <span style="color:#009900">"\n"</span>);
            } <span style="color:#000088">else</span> {
                <span style="color:#880000">//客户端的数据在左边</span>
                tv_show.setTextColor(Color.BLUE);
                tv_show.setTextSize(<span style="color:#006666">20</span>);
                tv_show.append(msg.obj + <span style="color:#009900">"\n"</span>);
            }

        }
    };


    <span style="color:#880000">/**
     * 客户端连接服务器
     */</span>
    RWStream client;

    <span style="color:#000088">private</span> <span style="color:#000088">void</span> <span style="color:#009900">connServer</span>(BluetoothDevice device) {
        <span style="color:#000088">try</span> {
            <span style="color:#880000">//创建蓝牙客户端的Socket对象,这里是类BluetoothSocket,服务端是BluetoothServerSocket</span>
            BluetoothSocket socket = device.createRfcommSocketToServiceRecord(uuid);
            socket.connect();<span style="color:#880000">//连接Socket</span>
            <span style="color:#880000">//创建可读写的客户对象,传入Socket对象</span>
            client = <span style="color:#000088">new</span> RWStream(socket);
            <span style="color:#880000">//开始客户端的线程</span>
            client.start();
        } <span style="color:#000088">catch</span> (IOException e) {
            e.printStackTrace();
        }

    }


    <span style="color:#880000">/**
     * 判断是否有蓝牙的权限,如果手机系统是6.0以上的就要动态创建权限
     */</span>
    <span style="color:#000088">private</span> <span style="color:#000088">void</span> <span style="color:#009900">checkPermission</span>() {
        <span style="color:#000088">if</span> (Build.VERSION.SDK_INT >= <span style="color:#006666">23</span>) {
            <span style="color:#880000">//23</span>
            <span style="color:#000088">int</span> check = checkSelfPermission(Manifest.permission.ACCESS_COARSE_LOCATION);
            <span style="color:#000088">if</span> (check != PackageManager.PERMISSION_GRANTED) {
                <span style="color:#880000">//请求权限</span>
                requestPermissions(<span style="color:#000088">new</span> String[]{Manifest.permission.ACCESS_COARSE_LOCATION}, REQUEST_LOCATION);
            }
        }
    }

    <span style="color:#880000">/**
     * 动态请求权限后,返回页面时的回调方法
     */</span>
    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">onRequestPermissionsResult</span>(<span style="color:#000088">int</span> requestCode, @NonNull String[] permissions, @NonNull <span style="color:#000088">int</span>[] grantResults) {
        <span style="color:#000088">super</span>.onRequestPermissionsResult(requestCode, permissions, grantResults);
        <span style="color:#000088">if</span> (requestCode == REQUEST_LOCATION && grantResults[<span style="color:#006666">0</span>] == PackageManager.PERMISSION_GRANTED) {
            Toast.makeText(<span style="color:#000088">this</span>, <span style="color:#009900">"权限已获取"</span>, Toast.LENGTH_SHORT).show();
        } <span style="color:#000088">else</span> {
            Toast.makeText(<span style="color:#000088">this</span>, <span style="color:#009900">"权限未获取"</span>, Toast.LENGTH_SHORT).show();
            finish();<span style="color:#880000">//关闭页面</span>
        }
    }

    <span style="color:#880000">/**
     * 数据回调方法
     */</span>
    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">protected</span> <span style="color:#000088">void</span> <span style="color:#009900">onActivityResult</span>(<span style="color:#000088">int</span> requestCode, <span style="color:#000088">int</span> resultCode, Intent data) {
        <span style="color:#000088">super</span>.onActivityResult(requestCode, resultCode, data);
        <span style="color:#000088">if</span> (requestCode == REQUEST_ENABLE) {
            <span style="color:#000088">if</span> (resultCode == RESULT_OK) {
                Toast.makeText(<span style="color:#000088">this</span>, <span style="color:#009900">"蓝牙已开启"</span>, Toast.LENGTH_SHORT).show();
                getMyBondedDevices();<span style="color:#880000">//获取绑定的蓝牙设备</span>
                adapter.notifyDataSetChanged();<span style="color:#880000">//刷新适配器</span>
            } <span style="color:#000088">else</span> {
                Toast.makeText(<span style="color:#000088">this</span>, <span style="color:#009900">"蓝牙未开启"</span>, Toast.LENGTH_SHORT).show();
            }
        } <span style="color:#000088">else</span> {

        }
    }

    <span style="color:#880000">/**
     * 获取已经绑定的蓝牙设置
     */</span>
    <span style="color:#000088">private</span> <span style="color:#000088">void</span> <span style="color:#009900">getMyBondedDevices</span>() {
        <span style="color:#880000">//获取所有已经绑定了的设备</span>
        deviceNames.clear();<span style="color:#880000">//清除设备名称的集合</span>
        devices.clear();<span style="color:#880000">//清除蓝牙设备对象的集合</span>
        <span style="color:#000088">if</span> (bluetoothAdapter.getBondedDevices() != <span style="color:#000088">null</span>) {<span style="color:#880000">//如果蓝牙适配器对象不为空时</span>
            <span style="color:#880000">//获取里面的数据的对象</span>
            List<BluetoothDevice> liset = <span style="color:#000088">new</span> ArrayList<>(bluetoothAdapter.getBondedDevices());
            devices.addAll(liset);
            <span style="color:#880000">//拿到适配器对象的名称数据</span>
            <span style="color:#000088">for</span> (BluetoothDevice device : liset) {
                deviceNames.add(device.getName());
            }
        }
    }

    <span style="color:#880000">/**
     * 广播的注册
     */</span>
    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">protected</span> <span style="color:#000088">void</span> <span style="color:#009900">onResume</span>() {
        <span style="color:#000088">super</span>.onResume();
        IntentFilter intentFilter = <span style="color:#000088">new</span> IntentFilter(BluetoothDevice.ACTION_FOUND);
        <span style="color:#880000">//添加蓝牙广播的Action</span>
        intentFilter.addAction(BluetoothAdapter.ACTION_DISCOVERY_FINISHED);
        registerReceiver(receiver, intentFilter);<span style="color:#880000">//注册广播接收者</span>
    }

    <span style="color:#880000">/**
     * 广播的停止
     */</span>
    <span style="color:#9b859d">@Override</span>
    <span style="color:#000088">protected</span> <span style="color:#000088">void</span> <span style="color:#009900">onPause</span>() {
        <span style="color:#000088">super</span>.onPause();
        unregisterReceiver(receiver);<span style="color:#880000">//取消广播</span>
    }

    <span style="color:#880000">/**
     * 广播接收者的创建
     */</span>
    <span style="color:#000088">private</span> BroadcastReceiver receiver = <span style="color:#000088">new</span> BroadcastReceiver() {
        <span style="color:#9b859d">@Override</span>
        <span style="color:#000088">public</span> <span style="color:#000088">void</span> <span style="color:#009900">onReceive</span>(Context context, Intent intent) {
            <span style="color:#880000">//获取设备的发送的广播</span>
            <span style="color:#000088">if</span> (intent.getAction().equals(BluetoothAdapter.ACTION_DISCOVERY_FINISHED)) {
                Toast.makeText(context, <span style="color:#009900">"蓝牙扫描完毕"</span>, Toast.LENGTH_SHORT).show();
            } <span style="color:#000088">else</span> {
                <span style="color:#880000">//获取蓝牙设置对象</span>
                BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
                <span style="color:#880000">//把对象和名称放到对应的集合中</span>
                devices.add(device);
                deviceNames.add(TextUtils.isEmpty(device.getName()) ? <span style="color:#009900">"未命名"</span> : device.getName());
                adapter.notifyDataSetChanged();
            }
        }
    };


}</code></span>

      上面程序运行后就可以完成蓝牙通信了,上面程序设计中显示多个按钮是为了蓝牙的使用示范,实际程序中,可以减少扫描按钮,比如程序运行就打开蓝牙,监听数据的按钮的方法也是可以嵌入到程序当中。 
      本程序虽然可以进行简单通信,但是也是有一些bug的,比如没有按照上面的步骤操作,直接点击后面的按钮是会空指针的!逻辑处理没有完善。 
      如果要传输文件,或其他数据都是可以的,那就要对输入流和输出流进行设置了。 
      这里对Socket编程简单做几句介绍,其实Socket编程并不是很难理解。Socket编程一般需要一个服务端SocketServie和一个或多个客户端Socket,通过SocketService或Socket对象获取它的输入流实现对数据的读取,获取输出流实现对数据的写入。其中数据如果要一直读取就要写一个一直执行的子线程,让它一直在跑。 
      而Tcp/Udp编程就要用到ip地址和端口号了。Socket编程可以结合Tcp使用网络。