从背景中的服务估计信标区域检测

我最近开始testingEstimote Beacons,而且我试图在进入一个灯塔区域时从后台服务中发出通知,但是不幸的是我的解决scheme不起作用。 它不会给出错误,但是当发现信标时通知不会被启动。 我不知道这是一些代码错误,或者干脆这样做是错误的。 我读过这个问题,但它似乎有点不同,因为我使用的是一个服务,而不是一个活动,但也许答案是类似的(应用程序上下文相关)…

这是我的服务代码

public class BeaconsMonitoringService extends Service{ private BeaconManager beaconManager; private String user; @Override public void onCreate() { // Configure BeaconManager. beaconManager = new BeaconManager(this); } @Override public int onStartCommand(Intent intent, int flags, int startId) { Toast.makeText(this, "Beacons monitoring service starting", Toast.LENGTH_SHORT).show(); user = intent.getStringExtra("user"); // Check if device supports Bluetooth Low Energy. if (!beaconManager.hasBluetooth()||!beaconManager.isBluetoothEnabled()) { Toast.makeText(this, "Device does not have Bluetooth Low Energy or it is not enabled", Toast.LENGTH_LONG).show(); this.stopSelf(); } connectToService(); // If we get killed, after returning from here, restart return START_STICKY; } @Override public IBinder onBind(Intent intent) { // We don't provide binding, so return null return null; } @Override public void onDestroy() { Toast.makeText(this, "Beacons monitoring service done", Toast.LENGTH_SHORT).show(); } private void connectToService() { beaconManager.connect(new BeaconManager.ServiceReadyCallback() { @Override public void onServiceReady() { notifyEnterRegion(0); // try { beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 0); Log.i("BEACOON ", "ANTES DE"); beaconManager.setMonitoringListener(new MonitoringListener() { @Override public void onEnteredRegion(Region region, List<Beacon> beacons) { Log.i("BEACOON ", String.valueOf(beacons.get(1).getMinor())); for (Beacon beacon: beacons){ Log.i("BEACOON ", String.valueOf(beacon.getMinor())); if (beacon.getMinor() == 64444) { notifyEnterRegion(6444); } else if (beacon.getMinor() == 36328) { notifyEnterRegion(36328); } else if (beacon.getMinor() == 31394) { notifyEnterRegion(31394); } } } @Override public void onExitedRegion(Region region) { notifyExitRegion(); } }); } }); } public void notifyEnterRegion(int code) { Toast.makeText(this, "Beacon "+code, Toast.LENGTH_SHORT).show(); Intent targetIntent = new Intent(this, MainActivity.class); PendingIntent contentIntent = PendingIntent.getActivity(this, 0, targetIntent, PendingIntent.FLAG_UPDATE_CURRENT); Notification noti = new Notification.Builder(this) .setContentTitle("Bienvenido "+user+"!") .setContentText("Sólo por estar aquí has ganado....") .setSmallIcon(com.smt.beaconssmt.R.drawable.beacon_gray) .setContentIntent(contentIntent) .getNotification(); NotificationManager nManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE); nManager.notify(1, noti); } public void notifyExitRegion(){ AlertDialog.Builder builder = new AlertDialog.Builder(this); builder.setMessage("Hasta pronto!") .setTitle(user+", estás abandonando la zona de beacons"); builder.setPositiveButton("Ver web", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User clicked OK button Intent i = new Intent(BeaconsMonitoringService.this, WebViewActivity.class); i.putExtra("web", "http://www.google.com/"); startActivity(i); } }); builder.setNegativeButton("Adios!", new DialogInterface.OnClickListener() { public void onClick(DialogInterface dialog, int id) { // User cancelled the dialog } }); AlertDialog dialog = builder.create(); dialog.show(); } } 

我将非常感谢任何forms的帮助,提前致谢!

Solutions Collecting From Web of "从背景中的服务估计信标区域检测"

此代码正在为我工​​作。 确保你正在放置正确的UUID,次要和主要号码。

 //Using something like that as global variable private static final Region[] BEACONS = new Region[] { new Region("beacon1", "uuid1", 1, 19227), //uuid without "-" new Region("beacon2", "uuid2", 1, 61690), new Region("beacon3", "uuid3", null, null) }; //Note: setting minor == null and major == null will detect every beacon with that uuid @Override public int onStartCommand(Intent intent, int flags, int startId) { startMonitoring(); return START_STICKY; } private void startMonitoring() { if (beaconManager == null) { beaconManager = new BeaconManager(this); // Configure verbose debug logging. L.enableDebugLogging(true); /** * Scanning */ beaconManager.setBackgroundScanPeriod(TimeUnit.SECONDS.toMillis(1), 1); beaconManager.setRangingListener(new RangingListener() { @Override public void onBeaconsDiscovered(Region paramRegion, List<Beacon> paramList) { if (paramList != null && !paramList.isEmpty()) { Beacon beacon = paramList.get(0); Proximity proximity = Utils.computeProximity(beacon); if (proximity == Proximity.IMMEDIATE) { Log.d(TAG, "entered in region " + paramRegion.getProximityUUID()); postNotification(paramRegion); } else if (proximity == Proximity.FAR) { Log.d(TAG, "exiting in region " + paramRegion.getProximityUUID()); removeNotification(paramRegion); } } } }); beaconManager.connect(new BeaconManager.ServiceReadyCallback() { @Override public void onServiceReady() { try { Log.d(TAG, "connected"); for (Region region : BEACONS) { beaconManager.startRanging(region); } } catch (RemoteException e) { Log.d("TAG", "Error while starting monitoring"); } } }); } } 

***编辑:代码来计算准确性

  public static double computeAccuracy(Beacon beacon) { if (beacon.getRssi() == 0) { return -1.0D; } double ratio = beacon.getRssi() / beacon.getMeasuredPower(); double rssiCorrection = 0.96D + Math.pow(Math.abs(beacon.getRssi()), 3.0D) % 10.0D / 150.0D; if (ratio <= 1.0D) { return Math.pow(ratio, 9.98D) * rssiCorrection; } return (0.103D + 0.89978D * Math.pow(ratio, 7.71D)) * rssiCorrection; } public static Proximity proximityFromAccuracy(double accuracy) { if (accuracy < 0.0D) { return Proximity.UNKNOWN; } if (accuracy < 0.5D) { return Proximity.IMMEDIATE; } if (accuracy <= 3.0D) { return Proximity.NEAR; } return Proximity.FAR; } public static Proximity computeProximity(Beacon beacon) { return proximityFromAccuracy(computeAccuracy(beacon)); } 

检查这一个我希望这会帮助你。 你可以通过这个函数Utils.computeProximity(nearestBeacon)find接近。

 beaconManager.setRangingListener(new BeaconManager.RangingListener() { @Override public void onBeaconsDiscovered(Region region, final List<Beacon> beaconList) { if (!beaconList.isEmpty()) { Beacon nearestBeacon = beaconList.get(0); Log.e("Current Proximity - ", String.valueOf(Utils.computeProximity(nearestBeacon))); } } }); 

从您的服务中,您也可以使用这个库来扫描iBeacons。 它可以节省您的用户一些电池 。 我也更喜欢这个,因为BeaconManager实际上产生了它自己的服务,所以你有2个服务只运行扫描iBeacons。 但是它确实缺乏距离计算。

另外请注意,要扫描iBeacons,您需要:

  • 有一个蓝牙LE芯片:任何。
  • 有蓝牙:任何。
  • 有位置:Android 6+。
  • 有位置运行时权限:Android 6+。
  • 在30秒内最多开始5次扫描:Android 7+。

为了让您的服务继续运行,您将需要添加以下广播监听器:

  • 位置状态改变了
  • 蓝牙状态改变了
  • 启动接收器

从这些接收器,你应该再次启动您的服务。