上周某杰同学遇到了蓝牙连接打印机的问题,来请教笔者,于是乎便各种百度终于解决了问题。本文对于这个问题做详细说明与记录来帮助各位看官解决类似问题,也方便以后用到的时候查询。
       如标题描述,分为以下两个问题:
       1.  蓝牙连接打印机(本文)
       2.  实现格式化打印(下一篇文章介绍)

    对于蓝牙想来大家应该都比较熟悉,基础知识便不再赘述,如有不懂的可以留言或者自行百度,本文重点介绍android实现蓝牙连接的流程和相关代码。

    1.判断设备是否支持并打开蓝牙

<span style="font-size:18px;"> //判断设备是否支持蓝牙
      BlueToothAdapter adapter=BlueToothAdapter.getDefaultAdapter();
      if(adapter==null){
        //设备不支持蓝牙
    	Toast.makeText(this, "本机没有找到蓝牙硬件或驱动!", Toast.LENGTH_SHORT).show();
    	return;
      }
      //比较暴力的方式(静默打开蓝牙),需要BlueTooth_Admin权限
      if(!adapter.isEnabled){//蓝牙没有开启
    	adapter.enable();
      }
      //关闭蓝牙
      adapter.disable();
      //弹出对话框提示后开启蓝牙,用户点击了允许会收到RESULT_OK 否则RESULT_CANCELED
      Intent mIntent = new Intent(BluetoothAdapter.ACTION_REQUEST_ENABLE); 
      startActivityForResult(mIntent, 1); 
      //在onActivityResult中做相关处理
      @Override 
      protected void onActivityResult(int requestCode, int resultCode, Intent data) { 
          // TODO Auto-generated method stub  
          super.onActivityResult(requestCode, resultCode, data); 
          if (requestCode == 1) { 
              if (resultCode == RESULT_OK) { 
                  Toast.makeText(this, "蓝牙已经开启", Toast.LENGTH_SHORT).show(); 
              } else if (resultCode == RESULT_CANCELED) { 
                  Toast.makeText(this, "不允许蓝牙开启", Toast.LENGTH_SHORT).show(); 
                  finish(); 
              } 
          } 
      } </span>



    2.获取已配对过的设备,返回结果是Set<BluetoothDevice>

<span style="font-size:18px;">Set<BluetoothDevice> devices = adapter.getBondedDevices();
      if(devices.size()>0) {
          for(BluetoothDevice bluetoothDevice:devices) {
              bondDevices.add(bluetoothDevice);
          }
      }</span>



    3.检索周围的设备

<span style="font-size:18px;">//开启检索:
      adapter.startDiscovery();</span>



设备检索是通过广播的方式接收的,分为注册intentFilter和处理广播两部分

     

//注册intentFilter
       IntentFilter intentFilter = new IntentFilter();
       intentFilter.addAction(BluetoothDevice.ACTION_FOUND);
       registerReceiver(receiver,intentFilter);


     

这里的action选项看源码(限于篇幅,列出部分):


      

<span style="font-size:18px;">@SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_FOUND = "android.bluetooth.device.action.FOUND";//发现新设备
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_DISAPPEARED = "android.bluetooth.device.action.DISAPPEARED";//设备变为不可见
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_CLASS_CHANGED = "android.bluetooth.device.action.CLASS_CHANGED";
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_ACL_CONNECTED = "android.bluetooth.device.action.ACL_CONNECTED";//连接完成
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_ACL_DISCONNECT_REQUESTED = "android.bluetooth.device.action.ACL_DISCONNECT_REQUESTED";//断开连接请求
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_ACL_DISCONNECTED ="android.bluetooth.device.action.ACL_DISCONNECTED";//断开连接
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_NAME_CHANGED = "android.bluetooth.device.action.NAME_CHANGED";//蓝牙设备名称变化
      @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
      public static final String ACTION_BOND_STATE_CHANGED = "android.bluetooth.device.action.BOND_STATE_CHANGED";//绑定状态发生变化的广播
      public static final String EXTRA_DEVICE = "android.bluetooth.device.extra.DEVICE";//接收到发现新设备的广播的时候从intent中获取数据的key
      public static final String EXTRA_NAME = "android.bluetooth.device.extra.NAME";//获取设备名字的key
      public static final String EXTRA_BOND_STATE = "android.bluetooth.device.extra.BOND_STATE";//获取配对状态的key</span>
</pre><pre name="code" class="java"><span style="font-size:18px;">      //在receiver中的处理,本文只列出了发现新设备的广播的接收处理
      private BroadcastReceiver receiver = new BroadcastReceiver() {


        @Override
        public void onReceive(Context context,Intent intent){
            String action = intent.getAction();
            BluetoothDevice device = intent.getParcelableExtra(BluetoothDevice.EXTRA_DEVICE);
            if(device.getBondState()==BluetoothDevice.BOND_BONDED) {
                //已配对设备
                addBondDevicesToListView(device);
            } else {
                //未配对设备
                addUnbondDevicesToListView(device);
            }
        }
     };</span>



    4.设备配对

<span style="font-size:18px;"> //设备的配对是通过反射实现的,调用的是createBond方法,返回值可以判断是否配对成功
      try {
          Method createBondMethod = BluetoothDevice.class.getMethod("createBond");
          boolean result = createBondMethod.invoke(unbondDevices.get(arg2));
      } catch (Exception e) {
          Toast.makeText(BluetoothActivity.this,e.getMessage(),Toast.LENGTH_SHORT).show();
      }</span>



    5.配对完成后开始正常通信

      蓝牙通信的本质是蓝牙套接字,即BluetoothSocket,除了以下代码就是一些关于流的操作。


      

<span style="font-size:18px;">public void connect(){
        if(!isConnection) {
          try {
            bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
            bluetoothSocket.connect();
            if(device.getBondState()==BluetoothDevice.BOND_BONDED) {
              outputStream = bluetoothSocket.getOutputStream();
              isConnection = true;
              if(bluetoothAdapter.isDiscovering()) {
                System.out.println("关闭适配器!");
                bluetoothAdapter.isDiscovering();
              }
            }
          } catch (Exception e) {
            Toast.makeText(PrintDataActivity.this,"连接失败!",1).show();
          }
          Toast.makeText(PrintDataActivity.this,device.getName()+"连接成功!",Toast.LENGTH_SHORT).show();
        } else {
          Toast.makeText(PrintDataActivity.this,"设备已连接",Toast.LENGTH_SHORT).show();
        }
      }</span>

     关键代码就两句话:

<span style="font-size: 18px;">     </span><span style="font-size:18px;">bluetoothSocket = device.createRfcommSocketToServiceRecord(uuid);
      bluetoothSocket.connect();</span>



      通过device.getBondState()==BluetoothDevice.BOND_BONDED判断是否连接成功


      补充uuid的定义,固定的不用改:


    

private static final UUID uuid = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");




      6.权限的注册

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

如果使用adapter.enable()需要注册另外一个权限

另外别忘记了广播的注册和反注册。


      至此关于android中蓝牙的基本使用介绍完毕,如有疑问可自行百度或者留言。

      打印相关的知识和代码将在下篇文章中介绍,敬请期待。