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 }
以上就是本文的全部内容,希望对大家的学习有所帮助,也希望大家多多支持。