android获取ibeacon列表的方法

作者:fulushan的技术专栏 时间:2023-01-18 00:57:54 

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
}

来源:https://blog.csdn.net/fulushan/article/details/80227649

标签:android,ibeacon,列表
0
投稿

猜你喜欢

  • Android 关机弹出选择菜单的深入解析

    2023-03-19 20:56:09
  • Java 编程中十个处理异常的建议

    2022-10-27 11:34:41
  • Java多线程之Worker Thread模式

    2021-06-11 12:11:51
  • 浅谈Java中注解Annotation的定义、使用、解析

    2021-07-29 04:07:52
  • C#客户端程序调用外部程序的3种实现方法

    2023-06-02 11:39:10
  • Mybatis表的关联查询详情

    2023-11-23 12:15:03
  • IDEA集成JProfiler11可视化工具的详细流程(安装、集成、测试)

    2021-12-12 04:05:35
  • Android开发:微信授权登录与微信分享完全解析

    2023-03-20 14:08:10
  • Linux下执行java程序的方法

    2023-01-25 07:22:23
  • 简单了解SpringCloud运行原理

    2023-06-09 17:07:15
  • SpringBoot异步任务使用方法详解

    2021-08-07 07:57:02
  • Android仿百度福袋红包界面

    2023-11-01 04:53:01
  • Java并发问题之乐观锁与悲观锁

    2022-07-13 19:59:05
  • 在C#中使用Channels的完整教程

    2021-11-03 15:41:28
  • 关于ConditionalOnMissingBean失效问题的追踪

    2021-08-19 17:42:04
  • C# 使用Microsoft Edge WebView2的相关总结

    2023-02-09 16:51:12
  • springboot页面国际化配置指南

    2022-06-16 14:26:25
  • 通过Java查看程序资源占用情况

    2023-11-10 02:01:19
  • Java8函数式接口的基础学习教程

    2023-12-16 12:57:59
  • 创建Android守护进程实例(底层服务)

    2021-11-12 01:37:09
  • asp之家 软件编程 m.aspxhome.com