使用 AltBeacon:从应用程序设置开始和停止扫描

Using AltBeacon: start and stop scanning from app settings

我正在将 AltBeacon API 集成到现有应用程序中。当用户进入或离开 "bluetooth zone".

时,应用程序应在 后台 中启动操作

此功能应该是可选的,用户应该从设置开始和停止扫描。

我尝试了 bind/unbind BeaconConsumer,但我看到,在后台 BluetoothLeScanner 一直在扫描!如何阻止 BluetoothLeScanner 扫描?这是正确的方法吗?

代码如下:

@Override
    public void onCreate() {
        super.onCreate();
        LogManager.setVerboseLoggingEnabled(true);
        log.debug("onCreate");
        mAllBeaconsRegion = new Region(ALLBEACONS, null, null, null);
        mBeaconManager = BeaconManager.getInstanceForApplication(this);
        mBackgroundPowerSaver = new BackgroundPowerSaver(this);
        mBeaconManager.setBackgroundBetweenScanPeriod(60000L);
        mBeaconManager.setBackgroundScanPeriod(2100L);
        // wake up the app when a beacon is seen
        mRegionBootstrap = new RegionBootstrap(this, mAllBeaconsRegion);
        mBeaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
        dsGlobal = new DbGlobalsHelper(getApplicationContext());
        boolean isBeaconScan = Utils.isBoolean(dsGlobal.getCursorGlobalsByKey(Constants.DB_KEY_BEACON_SCAN));
        if(isBeaconScan){
            mBeaconManager.bind(this);
        }else{
            mBeaconManager.unbind(this);
        }
    }

    // Set Regions to monitor at boot/startup
    private void setRegionsAtBoot(){
        Log.i(TAG, "setRegionsAtBoot");
        log.info("setRegionsAtBoot");
        SimpleBeaconStore beaconStore = new SimpleBeaconStore(this);
        List<SimpleBeacon> beacons = beaconStore.getBeacons();
        for (Iterator<SimpleBeacon> iterator = beacons.iterator(); iterator.hasNext();) {
            SimpleBeacon simpleBeacon = iterator.next();
            List<Identifier> listB = new ArrayList<Identifier>();
            StringTokenizer st = new StringTokenizer(simpleBeacon.getBeaconUuid(), "#");
            while (st.hasMoreTokens()) {
                listB.add(new Identifier(Identifier.parse(st.nextToken())));
            }
            try {
                Log.i(TAG, "setRegionsAtBoot " + simpleBeacon.getId());
                log.info("setRegionsAtBoot " + simpleBeacon.getId());
                Region region = new Region(simpleBeacon.getId(), listB);
                mBeaconManager.startRangingBeaconsInRegion(region);
            } catch (RemoteException e) {
                e.printStackTrace();
            }
        }
    }

    @Override
    public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
        // Start actions
        if (region.getUniqueId().equals(ALLBEACONS)){
            return;
        }
        if (beacons.size() > 0) {
            for (Beacon beacon: beacons) {
                Log.d(TAG, "Beacon "+beacon.toString()+" is about "+beacon.getDistance()+" meters away, with Rssi: "+beacon.getRssi());
                log.debug("Beacon " + beacon.toString() + " is about " + beacon.getDistance() + " meters away, with Rssi: " + beacon.getRssi());

                datasource = new DbZoneHelper(getApplicationContext());
                ZoneEntity ze = datasource.getCursorZoneByName(region.getUniqueId());

                if (beacon.getDistance() < ze.getRadius() && !ze.isStatus()) {
                    // 
                    Log.i(TAG, "Beacon " + beacon.toString() + " Just became less than " + ze.getRadius() + " meters away.");
                    log.info("*** Beacon " + beacon.toString() + " Just became less than " + ze.getRadius() + " meters away. ***");
                    String transitionType = getTransitionString(1);
                    NotificationUtil.sendNotification(getApplicationContext(), transitionType, region.getUniqueId());
                    worker = new Worker(getApplicationContext());
                    worker.handleTransition(1, region.getUniqueId(), Constants.BEACON);

                }
                if (beacon.getDistance() > (ze.getRadius() * EXITMULTIPLICATOR) && ze.isStatus()) {
                    // 
                    Log.i(TAG, "Beacon "+ beacon.toString()+" Just became over " + ze.getRadius() * EXITMULTIPLICATOR + " meters away.");
                    log.info("*** Beacon " + beacon.toString() + " Just became over " + ze.getRadius() * EXITMULTIPLICATOR + " meters away. ***");
                    String transitionType = getTransitionString(2);
                    NotificationUtil.sendNotification(getApplicationContext(), transitionType, region.getUniqueId());

                    worker = new Worker(getApplicationContext());
                    // 
                    worker.handleTransition(2, region.getUniqueId(), Constants.BEACON);

                }
            }
        }
    }

    @Override
    public void didDetermineStateForRegion(int arg0, Region arg1) {
    }

    @Override
    public void didEnterRegion(Region region) {

    }

    @Override
    public void didExitRegion(Region region) {

        if (region.getUniqueId().equals(ALLBEACONS)){
            return;
        }

        datasource = new DbZoneHelper(getApplicationContext());
        ZoneEntity ze = datasource.getCursorZoneByName(region.getUniqueId());

        if (ze.isStatus()) {
            // 
            Log.i(TAG, "Beacon " + region.getUniqueId() + " Just exited region.");
            log.info("Beacon " + region.getUniqueId() + " Just exited region.");
            String transitionType = getTransitionString(2);
            NotificationUtil.sendNotification(getApplicationContext(), transitionType, region.getUniqueId());

            worker = new Worker(getApplicationContext());

            worker.handleTransition(2, region.getUniqueId(), Constants.BEACON);
        }
    }

    @Override
    public void onBeaconServiceConnect() {
        Log.d(TAG, "onBeaconServiceConnect.");
        log.debug("onBeaconServiceConnect");
        setRegionsAtBoot();
        mBeaconManager.setRangeNotifier(this);
    }

    public void bind(){
        mBeaconManager.bind(this);
    }

    public void unbind(){
        mBeaconManager.unbind(this);
    }

我也在从我的设置中调用 bind/unbind。

显示的代码使用 RegionBootstrap class 在后台持续扫描信标。 class 本质上是为了永不停止扫描信标而设计的。 RegionBootstrap 在构建时绑定到扫描服务,实际上永远不会取消绑定。显示的代码手动绑定和解除绑定因此无效。

如果您想在不同时间开始和停止扫描,请不要使用 RegionBootstrap class,而是让您的 ApplicationActivity 工具BeaconConsumer 和 bind/unbind 如此处的监控示例代码所述:http://altbeacon.github.io/android-beacon-library/samples.html

编辑:RegionBootstrap 中添加了新方法,使动态区域监控更容易。您现在可以使用:regionBootstrap.disable() 完全停止扫描,或 regionBootstrap.removeRegion(region) 停止寻找单个区域。