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
}

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

时间: 2018-10-29

分享Android 蓝牙4.0(ble)开发的解决方案

最近,随着智能穿戴式设备.智能医疗以及智能家居的普及,蓝牙开发在移动开中显得非常的重要.由于公司需要,研究了一下,蓝牙4.0在Android中的应用. 以下是我的一些总结. 1.先介绍一下关于蓝牙4.0中的一些名词吧:    (1).GATT(Gneric Attibute  Profile) 通过ble连接,读写属性类小数据Profile通用的规范.现在所有的ble应用Profile  都是基于GATT (2).ATT(Attribute Protocal) GATT是基于ATT Potoca

Android检测IBeacon热点的方法

IBeacon是BLE的一种,搜索iBeacon基站关键在于设备扫描到的scanRecord数组,识别是否有下面加粗斜体的02 15这两个数字.如果有,搜索到的蓝牙设备就是IBeacon. // 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

详解Android——蓝牙技术 带你实现终端间数据传输

蓝牙技术在智能硬件方面有很多用武之地,今天我就为大家分享一下蓝牙在Android系统下的使用方法技巧,并实现一下两个终端间数据的传输. 蓝牙(Bluetooth)是一种短距离的无线通信技术标准,蓝牙协议分为4层,即核心协议层.电缆替代协议层.电话控制协议层和采纳的其它协议层. 这4种协议中最重要的是核心协议.蓝牙的核心协议包括基带.链路管理.逻辑链路控制和适应协议四部分.其中链路管理(LMP)负责蓝牙组件间连接的建立.逻辑链路控制与适应协议(L2CAP)位于基带协议层上,属于数据链路层,是一个为

Android蓝牙开发深入解析

1. 使用蓝牙的响应权限 复制代码 代码如下: <uses-permission android:name="android.permission.BLUETOOTH" /><uses-permission android:name="android.permission.BLUETOOTH_ADMIN" /> 2. 配置本机蓝牙模块 在这里首先要了解对蓝牙操作一个核心类BluetoothAdapter 复制代码 代码如下: Bluetoot

Android基于ibeacon实现蓝牙考勤功能

说明: ibeacon设备会主动发射蓝牙信号,当手机打开蓝牙靠近ibeacon设备时,就会收到设备发送的蓝牙信号,这时只需要根据ibeacon设备的uuid.major.minor.mac这四个值,就可以确认是哪一台ibeacon设备,然后调用服务端考勤接口(ibeacon设备只为了确认手机在考勤机边上,不需要发送考勤数据到ibeacon设备上),即可实现蓝牙考勤. 一.添加静态权限(在AndroidManifest.xml文件中添加,需要蓝牙和定位权限) <uses-permission an

Android单片机与蓝牙模块通信实例代码

啦啦毕业了,毕业前要写毕业设计,需要写一个简单的蓝牙APP进行交互,通过参考网上资料,问题顺利搞定,下面小编把具体实现思路分享给大家,供大家参考. 1.Android蓝牙编程 蓝牙3.0及以下版本编程需要使用UUID,UUID是通用唯一识别码(Universally Unique Identifier),这是一个软件构建的标准,也是被开源基金会组织应用在分布式计算环境领域的一部分.在蓝牙3.0及下一版本中,UUID被用于唯一标识一个服务,比如文件传输服务,串口服务.打印机服务等,如下: #蓝牙串

Android Bluetooth蓝牙技术使用流程详解

在上篇文章给大家介绍了Android Bluetooth蓝牙技术初体验相关内容,感兴趣的朋友可以点击了解详情. 一:蓝牙设备之间的通信主要包括了四个步骤 设置蓝牙设备 寻找局域网内可能或者匹配的设备 连接设备 设备之间的数据传输 二:具体编程实现 1. 启动蓝牙功能 首先通过调用静态方法getDefaultAdapter()获取蓝牙适配器BluetoothAdapter,如果返回为空,则无法继续执行了.例如: BluetoothAdapter mBluetoothAdapter = Blueto

android实现蓝牙文件发送的实例代码,支持多种机型

最近项目上需要实现蓝牙传输apk的一个功能,能够搜索周围的蓝牙手机并分享文件.从需求上讲android手机自带的蓝牙传输模块就可以满足需要了,实现也很简单.不过让人头疼的是,虽然说一般的主流机型都配置有蓝牙模块,但是android机型碎片化太严重,不同android版本手机蓝牙功能也不一样.4.0.3以下版本和以上版本使用的蓝牙包是不同的,分别是"com.android.bluetooth"和"com.mediatek.bluetooth".还有一些厂商对蓝牙模块进

Android提高之BLE开发Android手机搜索iBeacon基站

前面文章讲述了Android手机与BLE终端之间的通信,而最常见的BLE终端应该是苹果公司倡导的iBeacon基站.iBeacon技术基于BLE,它的特点是通过广播对外发送消息,手机不需要连上iBeacon基站也能获取它的信息,目前主要用来做室内定位和营销信息推送,在BLE发出的广播里带上带上特定的信息从而被识别为iBeacon.在iOS里面使用iBeacon要经过passbook注册iBeacon的UUID和对应的文字简介,而在Android上则无类似passbook这种系统级的后台蓝牙搜索服

Android手机通过蓝牙连接佳博打印机的实例代码

所使用的打印机为佳博打印机,支持蓝牙.wifi.usb我所使用的是通过蓝牙来连接. 在网上找到一个佳博官方针对安卓开发的App源码,但是各种的跳转,没有看太懂,所以又去问度娘,找到了一个不错的文章 Android对于蓝牙开发从2.0版本的sdk才开始支持,而且模拟器不支持,测试至少需要两部手机,所以制约了很多技术人员的开发. 1. 首先,要操作蓝牙,先要在AndroidManifest.xml里加入权限 // 管理蓝牙设备的权限 <uses-permissionandroid:name="

Android连接指定Wifi的方法实例代码

本篇文章主要记录一下Android中打开Wifi.获取Wifi接入点信息及连接指接入点的方法. 自己写的demo主要用于测试接口的基本功能,因此界面及底层逻辑比较粗糙. demo的整体界面如下所示: 上图中的OPEN按键负责开启Wifi: GET按键负责获取扫描到的接入点信息. 当获取到接入点信息后,我选取了其中的名称及信号强度,以列表的形式显示在主界面下方,如下图: 当点击列表中的Item时,就会去连接对应的接入点. 自己的逻辑比较简单,测试时的代码,假定连接的是不许要密码或密码已知的接入点.

Android连接服务器端的Socket的实例代码

废话不多说了,直接给大家贴代码了,具体代码如下所述: package com.exa mple.esp8266; import java.io.IOException; import java.io.InputStream; import java.io.OutputStream; import java.io.PrintStream; import java.net.Socket; import android.app.Activity; import android.os.Bundle; i

Android快速开发系列 10个常用工具类实例代码详解

打开大家手上的项目,基本都会有一大批的辅助类,今天特此整理出10个基本每个项目中都会使用的工具类,用于快速开发~~在此感谢群里给我发项目中工具类的兄弟/姐妹~ 1.日志工具类L.java package com.zhy.utils; import android.util.Log; /** * Log统一管理类 * * * */ public class L { private L() { /* cannot be instantiated */ throw new UnsupportedOpe

Android实现桌面悬浮窗、蒙板效果实例代码

现在很多安全类的软件,比如360手机助手,百度手机助手等等,都有一个悬浮窗,可以飘浮在桌面上,方便用户使用一些常用的操作. 今天这篇文章,就是介绍如何实现桌面悬浮窗效果的. 首先,看一下效果图. 悬浮窗一共分为两个部分,一个是平常显示的小窗口,另外一个是点击小窗口显示出来的二级悬浮窗口. 首先,先看一下这个项目的目录结构. 最关键的就是红框内的四个类. 首先,FloatWindowService是一个后台的服务类,主要负责在后台不断的刷新桌面上的小悬浮窗口,否则会导致更换界面之后,悬浮窗口也会随

Android 通过httppost上传文本文件到服务器的实例代码

废话不多说了,直接给大家贴关键代码了. /** * 往服务器上上传文本 比如log日志 * @param urlstr 请求的url * @param uploadFile log日志的路径 * /mnt/shell/emulated/0/LOG/LOG.log * @param newName log日志的名字 LOG.log * @return */ public static void httpPost(Activity activity,String urlstr,String uplo

jquery手机触屏滑动拼音字母城市选择器的实例代码

今天用到城市选择,直接用拼音滑动方式来选择,用的时候引入jquery(个别样式需要自己修改) <div class="yp_indz"><img src="images/dizhi.png" alt=""><em>北京</em></div> <!--省份列表--> <div class="dzhc_xs"> <nav> <di

Android开发Popwindow仿微信右上角下拉菜单实例代码

先给大家看下效果图: MenuPopwindow: package com.cloudeye.android.cloudeye.view; import android.app.Activity; import android.content.Context; import android.graphics.drawable.ColorDrawable; import android.view.LayoutInflater; import android.view.View; import an

Android第三方登录之腾讯QQ登录的实例代码

布局文件 <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="登录成功" android:textSize="25sp" android:layout_marginTop="100dp" /> 清单文件中的配置 <activity android:n

Android程序开发之Fragment实现底部导航栏实例代码

流行的应用的导航一般分为两种,一种是底部导航,一种是侧边栏. 说明 IDE:AS,Android studio; 模拟器:genymotion; 实现的效果,见下图. 具体实现 为了讲明白这个实现过程,我们贴出来的代码多一写,这样更方便理解 [最后还会放出完整的代码实现] .看上图的界面做的比较粗糙,但实现过程的骨架都具有了,想要更完美的设计,之后自行完善吧 ^0^. 布局 通过观察上述效果图,发现任意一个选项页面都有三部分组成: 顶部去除ActionBar后的标题栏: 中间一个Fragment