服务器之家:专注于VPS、云服务器配置技术及软件下载分享
分类导航

PHP教程|ASP.NET教程|Java教程|ASP教程|编程技术|正则表达式|C/C++|IOS|C#|Swift|Android|VB|R语言|JavaScript|易语言|vb.net|

服务器之家 - 编程语言 - Android - android获取ibeacon列表的方法

android获取ibeacon列表的方法

2022-08-15 10:23fulushan的技术专栏 Android

这篇文章主要为大家详细介绍了android获取ibeacon列表的方法,具有一定的参考价值,感兴趣的小伙伴们可以参考一下

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

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

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

核心代码如下:

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
/**
 *
 * <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);
  }
 
}

调用方式:

?
1
2
3
4
5
6
7
8
9
10
/**
* 开启蓝牙服务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类

 

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
/**
 * 代码改自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;
    }
  }
}

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

?
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
{
  "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

延伸 · 阅读

精彩推荐