Android蓝牙2.0—SppUtils开发

前言:

从事Android开发两年多了,一直在搞蓝牙2.0、4.0、UsbHost等硬件方面通信,每次给生产做的工具老是出Bug,换一个蓝牙厂家的模块,感觉就有点问题,老是在想API都是一样的,为什么不能兼容所有厂家的蓝牙模块?其实是自己一直没去看源码,有时候源码一句话就觉得问题,百度了半天,或者在技术群里面问半天,还没人回复,终于下定决心自己做一个通用的蓝牙通信框架。一切都从源码开始:

由于生产线检测蓝牙设备次数比较平凡,所以他们不想输入配对码,嫌弃这样太浪费时间了,最开始百度很多,搜索到ClsUtils的工具类,通过反射拿到BlueToothDevice.java类的方法通过设置pin码,确实能够解决自动配对的问题,但是问题来了,我的7.0Android手机就不行,最后通过Debug发现反射去拿setPairingConfirmation(boolean confirm)的时候出错了,原因是 @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)这个权限只能系统应用拥有,第三方应用没有这个权限,所有在我的7.0系统手机上任然会出现输入配对码的Dialog。解决方式:参见下文

    /**
     * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing.
     * 

Requires {@link android.Manifest.permission#BLUETOOTH_PRIVILEGED}. * * @return true confirmation has been sent out * false for error */ @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED) public boolean setPairingConfirmation(boolean confirm) { if (sService == null) { Log.e(TAG, "BT not enabled. Cannot set pairing confirmation"); return false; } try { return sService.setPairingConfirmation(this, confirm); } catch (RemoteException e) {Log.e(TAG, "", e);} return false; }

EmpsunSppUtils

使用集成:

allprojects {
    repositories {
        google()
        jcenter()
        //在Project的grade文件中添加
        maven { url 'https://jitpack.io' }
    }
}
//在Module添加依赖
implementation 'com.github.CHENDUEMPSUN:EmpsunSppUtils:v1.0.0'

Step1:onCreat()

//获得工具操作对象
SppUtils sppUtils = new SppUtils(this);
//开启蓝牙服务
mSppUtils.setupService();
mSppUtils.startService();

Step2:onStart()

public void onStart() {
     super.onStart();
     if(!mSppUtils.isBluetoothEnabled()) {
        //开启蓝牙
        mSppUtils.enable();
     } else {
        //开启服务
        if(!mSppUtils.isServiceAvailable()) {
            mSppUtils.setupService();
            mSppUtils.startService();
         }
    }
}

Step3:onDestroy()

public void onDestroy() {
    super.onDestroy();
    //断开蓝牙连接
    if(mSppUtils.getServiceState() == SppState.STATE_CONNECTED) {
       mSppUtils.disconnect();
    }
    //停止服务
    mSppUtils.stopService();
}

搜索

//开启搜索
sppUtils.startDiscovery();
//搜索的回调
sppUtils.setOnDeviceCallBack(new SppUtils.OnDeviceCallBack() {
      @Override
      public void onDeviceCallBack(BluetoothDevice bluetoothDevice) {
            //search some BluetoothDevice
            
            }
        });

连接

mSppUtils.connect("蓝牙地址");
mSppUtils.setBluetoothConnectionListener(new SppUtils.BluetoothConnectionListener() {
           public void onDeviceConnected(String name, String address) {
               Toast.makeText(getApplicationContext(), "连接成功 " + name, Toast.LENGTH_SHORT).show();
           }

           public void onDeviceDisconnected() {
               Toast.makeText(getApplicationContext(), "断开连接", Toast.LENGTH_SHORT).show();
           }

           public void onDeviceConnectionFailed() {
               Toast.makeText(getApplicationContext(), "连接失败", Toast.LENGTH_SHORT).show();
           }
       });

发送数据

mSppUtils.send("byte数组", false);

接收数据

mSppUtils.setOnDataReceivedListener(new SppUtils.OnDataReceivedListener() {
         @Override
         public void onDataReceived(final byte[] data, String message) {
             runOnUiThread(new Runnable() {
                 @Override
                 public void run() {
                     mReciveData.setText(mReciveData.getText()+ SppStringUtils.bytesToHexString(data));
                 }
             });

         }
     });

断开连接

//断开蓝牙连接
if(mSppUtils.getServiceState() == SppState.STATE_CONNECTED) {
     mSppUtils.disconnect();
  }

清除已配对的设备

mSppUtils.unPairDevices();

16进制字符串与byte数组的转换

mSppUtils.bytesToHexString();
mSppUtils.hexStringToBytes();

备注:

1、在Library中加入定位权限,不然在Android6.0以上系统上使用,搜索不到蓝牙

2、本Module采用通信方式为非安全模式 不需要通过输入pin码进行配对

private class ConnectThread extends Thread {
      private final BluetoothSocket mmSocket;
      private final BluetoothDevice mmDevice;
      private String mSocketType;

      public ConnectThread(BluetoothDevice device) {
          mmDevice = device;
          BluetoothSocket tmp = null;
          try {
              //Android2.3以下的API 这种方式会需要pin码 安全通信
              //tmp = device.createRfcommSocketToServiceRecord(UUID_DEVICE);
              //这种方式会不需要pin码 非安全通信
              tmp = device.createInsecureRfcommSocketToServiceRecord(UUID_DEVICE);

          } catch (IOException e) {

          }
          mmSocket = tmp;
      }

      public void run() {
          //总是取消搜索,因为它会减慢连接速度
          mAdapter.cancelDiscovery();
          try {
              //这是一个阻塞调用,只会在连接成功或异常时返回
              mmSocket.connect();
          } catch (IOException e) {
              try {
                  mmSocket.close();
              } catch (IOException e2) {

              }
              connectionFailed();
              return;
          }

          // Reset the ConnectThread because we're done
          synchronized (SppService.this) {
              mConnectThread = null;
          }
          connected(mmSocket, mmDevice, mSocketType);
      }

      public void cancel() {
          try {
              mmSocket.close();
              Log.e(TAG,"ConnectThread: mmSocket.close()");
          } catch (IOException e) {

          }
      }
  }

3、市面上有很多通过反射拿到BlueDevice的方法设置pin码,进行自动配对。但是这种只适用于Androidx.x以下系统,x.x以上系统同样会弹出输入pin码的Dialog,因为x.x之后:@RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)这个是系统应用权限,第三方应用根本没有这个权限,在x.x上反射是拿不到这个方法的,所以x.x以上系统实现不了自动配对,依然是弹出对话框输入pin码。(具体是哪个系统版本暂未查证)
除非:采用非安全通信方式就不需要输入pin码

    /**
   * Confirm passkey for {@link #PAIRING_VARIANT_PASSKEY_CONFIRMATION} pairing.
   *
   * @return true confirmation has been sent out
   *         false for error
   */
  @RequiresPermission(Manifest.permission.BLUETOOTH_PRIVILEGED)
  public boolean setPairingConfirmation(boolean confirm) {
      if (sService == null) {
          Log.e(TAG, "BT not enabled. Cannot set pairing confirmation");
          return false;
      }
      try {
          return sService.setPairingConfirmation(this, confirm);
      } catch (RemoteException e) {Log.e(TAG, "", e);}
      return false;
  }

Demo参见:https://github.com/CHENDUEMPSUN/EmpsunSppUtils

你可能感兴趣的:(Android蓝牙2.0—SppUtils开发)