Android AltBeacon后台服务测距

时间:2014-10-28 13:24:34

标签: java android bluetooth ibeacon altbeacon

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

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

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

RangingActivity

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

2 个答案:

答案 0 :(得分:6)

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

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

答案 1 :(得分:1)

您应该扩展Applicaton类并开始区域后台监控,就像解释here一样(参见&#34;在后台启动应用程序&#34;)。

为了进行测距,在同一个类中实现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();
            }
        }
    }