【问题标题】:Estimote beacons region detection from a service in background从后台服务估计信标区域检测
【发布时间】:2014-08-30 05:49:15
【问题描述】:

我最近开始测试 Estimote Beacons,我尝试在进入信标区域时从后台服务启动通知,但不幸的是我的解决方案不起作用。它不会给出错误,但在发现信标时不会启动通知。我不知道这是一些代码错误还是只是这样做的方式是错误的。我已经阅读了this 其他问题,但它似乎有点不同,因为我使用的是服务而不是活动,但也许答案是相似的(与应用程序上下文相关)......

这是我的服务代码

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();
      }



}

我将非常感谢任何形式的帮助,在此先感谢!

【问题讨论】:

    标签: android ibeacon ibeacon-android estimote


    【解决方案1】:

    此代码对我有用。确保您放置了正确的 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));
     }
    

    【讨论】:

    • 好的,这个解决方案有效,谢谢!但我对此有一个疑问,你如何“计算接近度”?是 sdk 或官方代码中的内容还是您自己的解决方案?所以从这里我了解到 BeaconManager.setMonitoringListener() 在这种情况下不可用,我们必须使用 setRangingListener() 代替??
    • 计算精度的代码应该在 SDK 中。但是我使用的是自定义 sdk 实现,所以我编辑了答案以向您展示代码。关于 setMonitoringListener 我无法让它工作,所以我完成了使用这个解决方案。
    • 我正在为我的 Xamarin 应用程序集成,这里 EnterRegion 和 ExitRegion 依次调用多次,不知道为什么?我读过它,它应该只在设备处于区域范围内时触发。但是当它进入范围时,它会依次触发,直到设备超出信标范围。请帮忙排序
    • 您不能在后台连续使用测距。这不是一个好习惯。它会很快耗尽电池和资源。出于后台目的,仅使用监控或在需要时使用监控一段时间,而不是连续监控或两者混合。如果您仍然这样做,让我告诉您您的应用在 Play 商店中发布时可能会被拒绝。
    • @AjaySharma 因为您使用的是测距,所以您的触发器将在每个扫描周期触发,直到您处于信标范围内。这不是一个好习惯。仅使用监控。
    【解决方案2】:

    检查这个我希望这会对你有所帮助。你可以通过这个函数Utils.computeProximity(nearestBeacon)找到接近度。

    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)));
                }
            }
    });
    

    【讨论】:

      【解决方案3】:

      通过您的服务,您还可以使用此 library 扫描 iBeacons。 它可以为您的用户节省一些battery。我也更喜欢这个,因为 BeaconManager 实际上会产生它自己的服务,因此您运行 2 个服务只是为了扫描 iBeacons。然而,它确实缺乏距离计算。

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

      • 拥有蓝牙 LE 芯片:任意。
      • 开启蓝牙:任意。
      • 定位在:Android 6+。
      • 具有定位运行时权限:Android 6+。
      • 30 秒内最多启动 5 次扫描:Android 7+。

      为了让您的服务保持运行,您必须添加以下广播侦听器:

      • 位置状态已更改
      • 蓝牙状态已更改
      • 引导接收器

      您应该从这些接收器重新启动您的服务。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2015-02-07
        • 1970-01-01
        • 2021-11-25
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多