欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页  >  移动技术

Android 蓝牙自动匹配PIN码跳过用户交互示例

程序员文章站 2023-11-26 18:53:16
近期项目中需要连接蓝牙设备,起初只是设置蓝牙列表界面让用户点击然后输入默认pin码,后来改需求了 = = ,要求自动连接指定设备并不需要用户手动输入pin码,作为andro...

近期项目中需要连接蓝牙设备,起初只是设置蓝牙列表界面让用户点击然后输入默认pin码,后来改需求了 = = ,要求自动连接指定设备并不需要用户手动输入pin码,作为android 小白的我是拒绝的,但是拒绝有什么用~

首先说一下之后会用到的关于蓝牙方面的东西:

  1. 断开蓝牙已配对的设备
  2. 搜索附近蓝牙设备
  3. 拦截用户交互页面,使用代码输入
  4. 由于在最后连接的时候使用的是设备的sdk所以在这里就不介绍了

1.断开已配对设备

最后在项目中发现没有用。这里就先记录一下。

  //得到配对的设备列表,清除已配对的设备
  public void removepairdevice() {
    if (mbluetoothadapter != null) {
      //mbluetoothadapter初始化方式 mbluetoothadapter = bluetoothadapter.getdefaultadapter();
      //这个就是获取已配对蓝牙列表的方法
      set<bluetoothdevice> bondeddevices = mbluetoothadapter.getbondeddevices();
      for (bluetoothdevice device : bondeddevices) {
        //这里可以通过device.getname() device.getaddress()来判断是否是自己需要断开的设备
        unpairdevice(device);
      }
    }
  }

  //反射来调用bluetoothdevice.removebond取消设备的配对
  private void unpairdevice(bluetoothdevice device) {
    try {
      method m = device.getclass().getmethod("removebond", (class[]) null);
      m.invoke(device, (object[]) null);
    } catch (exception e) {
      log.e("mate", e.getmessage());
    }
  }

2.搜索附近蓝牙

首先我们需要注册两个广播,第一个为正在搜索时的,第二个为搜索完成的。

    // register for broadcasts when a device is discovered
    intentfilter filter = new intentfilter(bluetoothdevice.action_found);
    this.registerreceiver(mfindbluetoothreceiver, filter);
    // register for broadcasts when discovery has finished
    filter = new intentfilter(bluetoothadapter.action_discovery_finished);
    this.registerreceiver(mfindbluetoothreceiver, filter);

    //需要时开始搜索
    if (mbluetoothadapter.isdiscovering()) {
          mbluetoothadapter.canceldiscovery();
     }
    mbluetoothadapter.startdiscovery();

然后对广播进行处理。这里要说明一下clsutils.createbond()这个方法如果连接设备sdk中有配对的方法,建议把这个方法去掉,我这里是去掉的,加上的话偶尔会toast出无法配对。

 private final broadcastreceiver mfindbluetoothreceiver = new broadcastreceiver() {
    @override
    public void onreceive(context context, intent intent) {
      string action = intent.getaction();
      // when discovery finds a device
      if (bluetoothdevice.action_found.equals(action)) {
        //todo 开始搜索
        bluetoothdevice device = intent.getparcelableextra(bluetoothdevice.extra_device);
       //  if (device.getbondstate() != bluetoothdevice.bond_bonded) {//判断蓝牙状态,是否是已配对
          //todo 可以在这判断名字 如果搜索结束后没有,再到已配对中寻找
          string btname[] = device.getname().split("-");
          if (btname[0].equals("xxx")) {
             //在这连接设备 一般需要蓝牙地址 device.getaddress();
             try {
               clsutils.createbond(device.getclass(), device);
             } catch (exception e) {
               // todo auto-generated catch block
               e.printstacktrace();
             }
          }
       // }
      } else if (bluetoothadapter.action_discovery_finished.equals(action)) {
        //todo 搜索结束
        toast.maketext(context, "搜索结束",toast.length_short).show();
      }
    }
  };

这里在activity结束时记得取消注册和取消搜索

unregisterreceiver(mfindbluetoothreceiver);
 if (mbluetoothadapter != null) {
     mbluetoothadapter.canceldiscovery();
 }

3.拦截用户交互页面

通过广播可以监听到输入pin码的那个页面将要弹出

    <receiver android:name=".bluetoothconnectactivityreceiver" >
      <intent-filter android:priority="1000">
        <action android:name="android.bluetooth.device.action.pairing_request" />
      </intent-filter>
    </receiver>

广播中需要做的事情,注意一定要调用abortbroadcast(),不然交互页面还是会出现一下然后消失。就是这个方法找了一天(╯‵□′)╯︵┴─┴。。。

public class bluetoothconnectactivityreceiver extends broadcastreceiver {

  @override
  public void onreceive(context context, intent intent) {
    if (intent.getaction().equals("android.bluetooth.device.action.pairing_request")) {
      bluetoothdevice mbluetoothdevice = intent.getparcelableextra(bluetoothdevice.extra_device);
      try {
        //(三星)4.3版本测试手机还是会弹出用户交互页面(闪一下),如果不注释掉下面这句页面不会取消但可以配对成功。(中兴,魅族4(flyme 6))5.1版本手机两中情况下都正常
        //clsutils.setpairingconfirmation(mbluetoothdevice.getclass(), mbluetoothdevice, true);
        abortbroadcast();//如果没有将广播终止,则会出现一个一闪而过的配对框。
        //3.调用setpin方法进行配对...
        boolean ret = clsutils.setpin(mbluetoothdevice.getclass(), mbluetoothdevice, "你需要设置的pin码");
      } catch (exception e) {
        e.printstacktrace();
      }
    }
  }
}

然后只要在搜索到自己需要的设备后连接进行操作就可以了!!!一定要记得加权限~

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

在android6.0之后还需要一个模糊定位的权限

复制代码 代码如下:

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

最后把clsutils类奉上,网上有很多的。

/**************** 蓝牙配对函数 ***************/

import java.lang.reflect.field;
import java.lang.reflect.method;

import android.bluetooth.bluetoothdevice;
import android.util.log;

public class clsutils {
  /**
   * 与设备配对 参考源码:platform/packages/apps/settings.git
   * /settings/src/com/android/settings/bluetooth/cachedbluetoothdevice.java
   */
  static public boolean createbond(class btclass, bluetoothdevice btdevice) throws exception {
    method createbondmethod = btclass.getmethod("createbond");
    boolean returnvalue = (boolean) createbondmethod.invoke(btdevice);
    return returnvalue.booleanvalue();
  }

  /**
   * 与设备解除配对 参考源码:platform/packages/apps/settings.git
   * /settings/src/com/android/settings/bluetooth/cachedbluetoothdevice.java
   */
  static public boolean removebond(class<?> btclass, bluetoothdevice btdevice) throws exception {
    method removebondmethod = btclass.getmethod("removebond");
    boolean returnvalue = (boolean) removebondmethod.invoke(btdevice);
    return returnvalue.booleanvalue();
  }

  static public boolean setpin(class<? extends bluetoothdevice> btclass, bluetoothdevice btdevice, string str) throws exception {
    try {
      method removebondmethod = btclass.getdeclaredmethod("setpin", new class[]{byte[].class});
      boolean returnvalue = (boolean) removebondmethod.invoke(btdevice,
          new object[]
              {str.getbytes()});
      log.e("returnvalue", "" + returnvalue);
    } catch (securityexception e) {
      // throw new runtimeexception(e.getmessage());
      e.printstacktrace();
    } catch (illegalargumentexception e) {
      // throw new runtimeexception(e.getmessage());
      e.printstacktrace();
    } catch (exception e) {
      // todo auto-generated catch block
      e.printstacktrace();
    }
    return true;

  }

  // 取消用户输入
  static public boolean cancelpairinguserinput(class<?> btclass, bluetoothdevice device) throws exception {
    method createbondmethod = btclass.getmethod("cancelpairinguserinput");
//    cancelbondprocess(btclass, device);
    boolean returnvalue = (boolean) createbondmethod.invoke(device);
    return returnvalue.booleanvalue();
  }

  // 取消配对
  static public boolean cancelbondprocess(class<?> btclass, bluetoothdevice device) throws exception {
    method createbondmethod = btclass.getmethod("cancelbondprocess");
    boolean returnvalue = (boolean) createbondmethod.invoke(device);
    return returnvalue.booleanvalue();
  }

  //确认配对

  static public void setpairingconfirmation(class<?> btclass, bluetoothdevice device, boolean isconfirm) throws exception {
    method setpairingconfirmation = btclass.getdeclaredmethod("setpairingconfirmation", boolean.class);
    setpairingconfirmation.invoke(device, isconfirm);
  }


  /**
   *
   * @param clsshow
   */
  static public void printallinform(class clsshow) {
    try {
      // 取得所有方法
      method[] hidemethod = clsshow.getmethods();
      int i = 0;
      for (; i < hidemethod.length; i++) {
        log.e("method name", hidemethod[i].getname() + ";and the i is:"+ i);
      }
      // 取得所有常量
      field[] allfields = clsshow.getfields();
      for (i = 0; i < allfields.length; i++) {
        log.e("field name", allfields[i].getname());
      }
    } catch (securityexception e) {
      // throw new runtimeexception(e.getmessage());
      e.printstacktrace();
    } catch (illegalargumentexception e) {
      // throw new runtimeexception(e.getmessage());
      e.printstacktrace();
    } catch (exception e) {
      // todo auto-generated catch block
      e.printstacktrace();
    }
  }
}

以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。