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

android获取ibeacon列表的方法

程序员文章站 2022-06-04 12:12:06
android获取ibeacon列表,供大家参考,具体内容如下 最近公司有需要做ibeacon需求。 因为涉及扫码的时间。特意写一个service实现获取列表 可以根据...

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
}

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