android Method for Getting ibeacon List

  • 2021-10-24 23:40:56
  • OfStack

android Get the list of ibeacon for your reference. The details are as follows

Recently, the company needs to do ibeacon.

Because it involves the time of scanning code. Specially write an service implementation to obtain the list, which can scan out the ibeacon list according to the scanning time
Contains uuid, equipment name, unit (m), electricity quantity, etc.
Please modify the code according to your own project.

The core code is as follows:


/**
 *
 * <ibeaon Services >
 *
 * @author fulushan
 * @date  Creation time: 2018 Year 4 Month 5 Day   Afternoon 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;

  /** Search BLE Terminal */
  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<>();
      // Open 1 A new thread, if you use the Service , will cause ANR Problem, Service It will block itself 
      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 {
        // Get Bluetooth data 
        // Begin to judge 
        // 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;
        }
        // Turn on Bluetooth 
        mBluetoothAdapter.enable();

        scanLeDevice(true);


      } catch (Exception ex) {
        ex.printStackTrace();
        message.what = DATA_FAIL;
        // Download failed 
        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;
          // Data data complete   Update data list 
          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));
          // Stop service 
          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());// Here you need to set the package name of your application 
    stopService(updateIntent);
  }

}

Call mode:


/**
*  Turn on Bluetooth service UpdateService
*/
  public static void startIbeacon(Context context,int time) {
    Intent intent = new Intent(context,IbeaconService.class);
    intent.putExtra("time", time);// Scanning ibeacon Time 
    intent.setAction(IBEACON_SERVICE);
    intent.setPackage(context.getPackageName());// Here you need to set the package name of your application 
    context.startService(intent);
  }

Where IBeacon class


/**
 *  Code modification from 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(); 
  }


  /**
   *  Estimating user equipment to ibeacon The distance of 
   *
   * @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;
    }
  }
}

Please complete the missing classes by yourself. Please modify the code according to your own project.


{
  "msg": " Getting data successfully ",
  "data": [{
      "uuid": "11111",
      "beaconName": " Equipment A",
      "distance": 0.56
    },
    {
      "uuid": "2222",
      "beaconName": " Equipment B",
      "distance": 1.56
    }
  ],
  "status": 100
}

Related articles: