【问题标题】:Android AltBeacon Background Service RangingAndroid AltBeacon 后台服务测距
【发布时间】:2014-10-28 13:24:33
【问题描述】:

我正在使用 AltBeacon 库开发蓝牙应用程序。似乎每个应用程序只允许 BeaconManager 的实例。我面临的问题是:我想要一个持续运行的后台服务,不断进行蓝牙测距并发送通知。如果我打开我的应用程序(将其带到前台),我就是暂停测距的服务。然后,前台活动将进行测距并在屏幕上显示内容。

问题在于活动和服务中的信标管理器(来自BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);)是同一个实例。因此,当活动关闭时,beaconManager.unbind(this); 会被调用,并且服务中的范围通知器不再触发。

是否有可能获得两个单独的信标管理器实例?如果没有,我该如何在持续运行的服务和活动中进行测距?

测距活动

@Override
protected void onCreate(Bundle savedInstanceState) {
...
regionEstimote = new Region("estimote", null, null, null);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));
beaconManager.bind(this);
}
@Override
protected void onDestroy() {
    super.onDestroy();
    notificationManager.cancel(NOTIFICATION_ID);
    //beaconManager.unbind(this);
}
@Override
public void onBeaconServiceConnect() {
    beaconManager.setRangeNotifier(new RangeNotifier() {
        ....
    });
    try {
        beaconManager.startRangingBeaconsInRegion(regionEstimote);
    } catch (RemoteException e) {
        Log.e(TAG, "RangingActivity", e);
    }
}

BeaconService.java

@Override
public int onStartCommand(Intent intent, int flags, int startId) {
    if(beaconHistory == null)
        beaconHistory = new HashMap<Integer, Date>();

    mBeaconManager = BeaconManager.getInstanceForApplication(this);
    mBeaconManager.getBeaconParsers().add(new BeaconParser().
            setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24"));

    return START_STICKY;
}

@Override
public void onDestroy() {
    super.onDestroy();
    beaconHistory = null;
    mBeaconManager.unbind(this);
}
@Override
public void onBeaconServiceConnect() {
    mBeaconManager.setRangeNotifier(new RangeNotifier() {
        @Override
        public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
            if(ActivityBase.isActivityVisible()) {   //don't do ranging logic if any activity from my app is in the foreground
                return;
            }
            ...
        }
    });

    try {
        mBeaconManager.startRangingBeaconsInRegion(regionMint);
    } catch (RemoteException e) {
        Log.e(TAG, "BeaconService", e);
    }
}

【问题讨论】:

    标签: java android bluetooth ibeacon altbeacon


    【解决方案1】:

    这是一个自定义android.app.Application 类非常有用的情况。 BeaconManager 是一个单例,因此只允许同时存在一个。同样,Application 类对于每个活动的 Android 应用程序都有一个实例。如果您想同时在ActivityService 中进行信标检测,请使用集中式Application 类绑定到BeaconManager,然后将回调转发到您的ActivityService .

    您可以在此处查看在 Application 类中绑定到 BeaconManager 的示例,然后在参考应用程序中将回调传递给 Activityhttps://github.com/AltBeacon/android-beacon-library-reference/blob/master/app/src/main/java/org/altbeacon/beaconreference/BeaconReferenceApplication.java

    【讨论】:

    • 嗨 davidgyoung,即使应用程序 ui 不可见,我也想在后台服务中扫描信标。您能否指导我并分享代码 sn-p 来实现这一目标。提前致谢
    • 在此处查看示例:altbeacon.github.io/android-beacon-library/samples.html 在后台启动应用程序下。您不需要自己的服务,因为图书馆提供了服务。只需在自定义 Application 类中实现回调即可。
    • 非常感谢.. 我试过了,但是一旦您退出应用程序,扫描就会停止。例如。如果你来到主屏幕。我想实现连续扫描。请帮帮我。
    • 不,扫描将在后台以降低的速度继续。 (默认情况下每 5 分钟一次。)查看参考应用程序,这是一个基于上述示例执行此操作的工作应用程序。 github.com/AltBeacon/android-beacon-library-reference 也看这里 altbeacon.github.io/android-beacon-library/battery_manager.html
    • 非常感谢..我明白了..:)
    【解决方案2】:

    您应该扩展 Applicaton 类并像 here 中解释的那样启动区域后台监控(请参阅“在后台启动应用程序”)。

    为了进行测距,在同一个类中实现 RangeNotifier:

    public class AndroidApp extends Application implements BootstrapNotifier, RangeNotifier {...
    

    在 didEnterRegion 中开始测距:

    @Override
    public void didEnterRegion(Region region) {
        try {
            mBeaconManager.startRangingBeaconsInRegion(region);
        }
        catch (RemoteException e) {
            if (BuildConfig.DEBUG) Log.d(Const.TAG, "Can't start ranging");
        }
    }
    
    1. 实现 didRangeBeaconsInRegion 方法:

      @Override
      public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
          if (beacons.size() > 0) {
              Beacon firstBeacon = beacons.iterator().next();
              if (BuildConfig.DEBUG) Log.d(Const.TAG, "Beacon ranged: UUID: "
                      + firstBeacon.getId1().toString() + " Major: "
                      + firstBeacon.getId2().toString() + " Minor: "
                      + firstBeacon.getId3().toString());
      
              // Do something with the result
      
              // Stop ranging
              try {
                  mBeaconManager.stopRangingBeaconsInRegion(region);
              } catch (RemoteException e) {
                  e.printStackTrace();
              }
          }
      }
      

    【讨论】:

    • 你能分享一个使用 RangeNotifier 的示例类应用吗?
    • 为什么需要停止测距信标?
    • @DiegoRivera,您需要停止测距信标以节省电池寿命。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-11-02
    • 1970-01-01
    • 2020-06-05
    • 1970-01-01
    • 1970-01-01
    • 2014-01-27
    • 1970-01-01
    相关资源
    最近更新 更多