android获取ibeacon列表的方法

 更新时间:2018年10月31日 08:32:32   转载 作者:fulushan的技术专栏  
这篇文章主要为大家详细介绍了android获取ibeacon列表的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

android获取ibeacon列表,供大家参考,具体内容如下

最近公司有需要做ibeacon需求。

因为涉及扫码的时间。特意写一个service实现获取列表 可以根据扫描时间扫描出ibeacon列表
包含 uuid,设备名称,单位(米),电量等。
请根据自己的项目进行改造代码。

核心代码如下:

/**
 *
 * <ibeaon服务>
 *
 * @author fulushan
 * @date 创建时间:2018年4月5日 下午11:34:04
 */
public class IbeaconService extends Service {

  private static final String TAG = IbeaconService.class.getName();

  ArrayList<IBeaconClass.iBeacon> mLeDevices;

  private boolean mScanning;
  private final static int DATA_COMPLETE = 0;
  private final static int DATA_FAIL = 1;

  /**搜索BLE终端*/
  private BluetoothAdapter mBluetoothAdapter;

  // Stops scanning after 10 seconds.
  private static long SCAN_PERIOD = 10000;

  ResponseResult responseResult = new ResponseResult();
  public class IbeaconBinder extends Binder{
    public ResponseResult getResponseResult(){
      return responseResult;
    }
  }

  @Override
  public IBinder onBind(Intent arg0) {
    // TODO Auto-generated method stub
    return null;
  }


  @Override
  public void onStart(Intent intent, int startId) {
    super.onStart(intent, startId);
    if (intent != null) {
      SCAN_PERIOD = intent.getIntExtra("time",10)*1000;
      mLeDevices = new ArrayList<>();
      //开启一个新的线程,如果使用Service,会导致ANR问题,Service本身也会阻塞
      new Thread(new IbeaconRunnable()).start();
    }

  }

  @Override
  public void onDestroy() {
    super.onDestroy();
    stopUpdateService();
    scanLeDevice(false);
  }


  class IbeaconRunnable implements Runnable {
    Message message = handler.obtainMessage();

    public void run() {

      try {
        //获取蓝牙数据
        //开始判断
        // Use this check to determine whether BLE is supported on the device. Then you can
        // selectively disable BLE-related features.
        if (!getPackageManager().hasSystemFeature(PackageManager.FEATURE_BLUETOOTH_LE)) {
          message.what = DATA_FAIL;
          responseResult.setStatus(BlueToothEnum.BLU_SERVICE_UNAVAI.getCode());
          responseResult.setMsg(BlueToothEnum.BLU_SERVICE_UNAVAI.getMsg());
          message.obj = responseResult;
          handler.sendMessage(message);
          return;
        }


        if(Build.VERSION.SDK_INT<JELLY_BEAN_MR2){
          responseResult.setStatus(BlueToothEnum.BLU_SERVICE_UNAVAI.getCode());
          responseResult.setMsg(BlueToothEnum.BLU_SERVICE_UNAVAI.getMsg());
          message.obj = responseResult;
          handler.sendMessage(message);
          return;
        }
        // Initializes a Bluetooth adapter. For API level 18 and above, get a reference to
        // BluetoothAdapter through BluetoothManager.
        final BluetoothManager bluetoothManager =
            (BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE);
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.JELLY_BEAN_MR2) {
          mBluetoothAdapter = bluetoothManager.getAdapter();
        }

        if(!mBluetoothAdapter.isEnabled()){
          responseResult.setStatus(BlueToothEnum.BLU_SERVICE_UNAVAI.getCode());
          responseResult.setMsg(BlueToothEnum.BLU_SERVICE_UNAVAI.getMsg());
          message.obj = responseResult;
          handler.sendMessage(message);
          return;
        }

        // Checks if Bluetooth is supported on the device.
        if (mBluetoothAdapter == null) {
          responseResult.setStatus(BlueToothEnum.BLU_SERVICE_UNAVAI.getCode());
          responseResult.setMsg(BlueToothEnum.BLU_SERVICE_UNAVAI.getMsg());
          message.obj = responseResult;
          handler.sendMessage(message);
          return;
        }
        //开启蓝牙
        mBluetoothAdapter.enable();

        scanLeDevice(true);


      } catch (Exception ex) {
        ex.printStackTrace();
        message.what = DATA_FAIL;
        //下载失败
        handler.sendMessage(message);

      }
    }
  }


  @TargetApi(Build.VERSION_CODES.JELLY_BEAN_MR2)
  private void scanLeDevice(final boolean enable) {
    if (enable) {
      // Stops scanning after a pre-defined scan period.
      handler.postDelayed(new Runnable() {
        @RequiresApi(api = Build.VERSION_CODES.JELLY_BEAN_MR2)
        @Override
        public void run() {
          LogUtil.e(TAG,"scanLeDeviceStop");
          mScanning = false;
          mBluetoothAdapter.stopLeScan(mLeScanCallback);


          Message message = handler.obtainMessage();
          message.what = DATA_COMPLETE;
          responseResult.setStatus(BlueToothEnum.SUCCESS.getCode());
          responseResult.setMsg(BlueToothEnum.SUCCESS.getMsg());
          responseResult.setData(mLeDevices);
          message.obj = responseResult;
          //数据数据完毕 更新数据列表
          handler.sendMessage(message);


        }
      }, SCAN_PERIOD);

      mScanning = true;
      mBluetoothAdapter.startLeScan(mLeScanCallback);
    } else {
      mScanning = false;
      mBluetoothAdapter.stopLeScan(mLeScanCallback);
    }
  }
  public void addDevice(IBeaconClass.iBeacon device) {
    if(device==null)
      return;

    for(int i=0;i<mLeDevices.size();i++){
      String btAddress = mLeDevices.get(i).bluetoothAddress;
      if(btAddress.equals(device.bluetoothAddress)){
        mLeDevices.add(i+1, device);
        mLeDevices.remove(i);
        return;
      }
    }
    mLeDevices.add(device);

  }
  // Device scan callback.
  private BluetoothAdapter.LeScanCallback mLeScanCallback =
      new BluetoothAdapter.LeScanCallback() {

        @Override
        public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {

          final IBeaconClass.iBeacon ibeacon = IBeaconClass.fromScanData(device,rssi,scanRecord);
           LogUtil.e(TAG,"onLeScan");
           addDevice(ibeacon);
           if(!mScanning){
             LogUtil.e(TAG,"!mScanning");

           }
        }
      };


  private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
      switch (msg.what) {
        case DATA_COMPLETE:
          EventBus.getDefault().post(new BlueTeethEvent(responseResult));
          //停止服务
          stopUpdateService();

          break;
        case DATA_FAIL:
          responseResult.setStatus(BlueToothEnum.OTHER_ERROR.getCode());
          responseResult.setMsg(BlueToothEnum.OTHER_ERROR.getMsg());

          EventBus.getDefault().post(new BlueTeethEvent(responseResult));
          stopUpdateService();
          break;
        default:
          // stopService(updateIntent);
          // stopService(updateIntent);
          // stopService(new Intent(UpdateService.this,UpdateService.class));
          break;
      }
    }
  };

  private void stopUpdateService() {
    Intent updateIntent = new Intent(getBaseContext(),IbeaconService.class);
    updateIntent.setAction(ServiceHelper.IBEACON_SERVICE);
    updateIntent.setPackage(getBaseContext().getPackageName());//这里你需要设置你应用的包名
    stopService(updateIntent);
  }

}

调用方式:

/**
* 开启蓝牙服务UpdateService
*/
  public static void startIbeacon(Context context,int time) {
    Intent intent = new Intent(context,IbeaconService.class);
    intent.putExtra("time", time);//扫描ibeacon时间
    intent.setAction(IBEACON_SERVICE);
    intent.setPackage(context.getPackageName());//这里你需要设置你应用的包名
    context.startService(intent);
  }

其中IBeacon类

/**
 * 代码改自https://github.com/RadiusNetworks/android-ibeacon-service/blob/master/src/main/java/com/radiusnetworks/ibeacon/IBeacon.java
 * @author gvzhang
 *
 */
public class IBeaconClass {

  static public class iBeacon implements Serializable{
    public String beaconName;
    public int major;
    public int minor;
    public String uuid;
    public String bluetoothAddress;
    public int txPower;
    public int rssi;
    public double distance;
  }
  public static iBeacon fromScanData(BluetoothDevice device, int rssi,byte[] scanData) {

    int startByte = 2;
    boolean patternFound = false;
    while (startByte <= 5) {
      if (((int)scanData[startByte+2] & 0xff) == 0x02 &&
        ((int)scanData[startByte+3] & 0xff) == 0x15) {     
        // yes! This is an iBeacon 
        patternFound = true;
        break;
      }
      else if (((int)scanData[startByte] & 0xff) == 0x2d &&
          ((int)scanData[startByte+1] & 0xff) == 0x24 &&
          ((int)scanData[startByte+2] & 0xff) == 0xbf &&
          ((int)scanData[startByte+3] & 0xff) == 0x16) {
        iBeacon iBeacon = new iBeacon();
        iBeacon.major = 0;
        iBeacon.minor = 0;
        iBeacon.uuid = "00000000-0000-0000-0000-000000000000";
        iBeacon.txPower = -55;
        return iBeacon;
      }
      else if (((int)scanData[startByte] & 0xff) == 0xad &&
           ((int)scanData[startByte+1] & 0xff) == 0x77 &&
           ((int)scanData[startByte+2] & 0xff) == 0x00 &&
           ((int)scanData[startByte+3] & 0xff) == 0xc6) {

          iBeacon iBeacon = new iBeacon();
          iBeacon.major = 0;
          iBeacon.minor = 0;
          iBeacon.uuid = "00000000-0000-0000-0000-000000000000";
          iBeacon.txPower = -55;
          return iBeacon;
      }
      startByte++;
    }


    if (patternFound == false) {
      // This is not an iBeacon
      return null;
    }

    iBeacon iBeacon = new iBeacon();

    iBeacon.major = (scanData[startByte+20] & 0xff) * 0x100 + (scanData[startByte+21] & 0xff);
    iBeacon.minor = (scanData[startByte+22] & 0xff) * 0x100 + (scanData[startByte+23] & 0xff);
    iBeacon.txPower = (int)scanData[startByte+24]; // this one is signed
    iBeacon.rssi = rssi;

    iBeacon.distance = calculateAccuracy(iBeacon.txPower,iBeacon.rssi);

    // AirLocate:
    // 02 01 1a 1a ff 4c 00 02 15 # Apple's fixed iBeacon advertising prefix
    // e2 c5 6d b5 df fb 48 d2 b0 60 d0 f5 a7 10 96 e0 # iBeacon profile uuid
    // 00 00 # major 
    // 00 00 # minor 
    // c5 # The 2's complement of the calibrated Tx Power

    // Estimote:    
    // 02 01 1a 11 07 2d 24 bf 16 
    // 394b31ba3f486415ab376e5c0f09457374696d6f7465426561636f6e00000000000000000000000000000000000000000000000000

    byte[] proximityUuidBytes = new byte[16];
    System.arraycopy(scanData, startByte+4, proximityUuidBytes, 0, 16); 
    String hexString = bytesToHexString(proximityUuidBytes);
    StringBuilder sb = new StringBuilder();
    sb.append(hexString.substring(0,8));
    sb.append("-");
    sb.append(hexString.substring(8,12));
    sb.append("-");
    sb.append(hexString.substring(12,16));
    sb.append("-");
    sb.append(hexString.substring(16,20));
    sb.append("-");
    sb.append(hexString.substring(20,32));
    iBeacon.uuid = sb.toString();

    if (device != null) {
      iBeacon.bluetoothAddress = device.getAddress();
      iBeacon.beaconName = device.getName();
    }

    return iBeacon;
  }

  private static String bytesToHexString(byte[] src){ 
    StringBuilder stringBuilder = new StringBuilder(""); 
    if (src == null || src.length <= 0) { 
      return null; 
    } 
    for (int i = 0; i < src.length; i++) { 
      int v = src[i] & 0xFF; 
      String hv = Integer.toHexString(v); 
      if (hv.length() < 2) { 
        stringBuilder.append(0); 
      } 
      stringBuilder.append(hv); 
    } 
    return stringBuilder.toString(); 
  }


  /**
   * 估算用户设备到ibeacon的距离
   *
   * @param txPower
   * @param rssi
   * @return
   */
  public static double calculateAccuracy(int txPower, double rssi) {
    if (rssi == 0) {
      return -1.0; // if we cannot determine accuracy, return -1.
    }

    double ratio = rssi * 1.0 / txPower;
    if (ratio < 1.0) {
      return Math.pow(ratio, 10);
    } else {
      double accuracy = (0.89976) * Math.pow(ratio, 7.7095) + 0.111;
      return accuracy;
    }
  }
}

缺少的类请自己补全。请根据自己的项目进行改造代码。

{
  "msg": "获取数据成功",
  "data": [{
      "uuid": "11111",
      "beaconName": "设备A",
      "distance": 0.56
    },
    {
      "uuid": "2222",
      "beaconName": "设备B",
      "distance": 1.56
    }
  ],
  "status": 100
}

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

相关文章

最新评论