AltBeacon / android-beacon-library

Allows Android apps to interact with BLE beacons
Apache License 2.0
2.85k stars 837 forks source link

onBeaconServiceConnect() not Called in 6.0 and 7.0 (works in 8+) with LiveData #796

Closed kababu007 closed 5 years ago

kababu007 commented 5 years ago

Expected behavior

onBeaconServiceConnect() should get called when using in LiveData in MVVM

Actual behavior

onBeaconServiceConnect() doesnt get called in 6.0 7.0 but works in 8+ when using LiveData in MVVM.

Steps to reproduce this behavior

Use MVVM with LiveData instead of implementing BeaconConsumer in fragment / activity. It works fine when we implement BeaconConsumer in fragment or activity. Also with LiveData it works in 8+.

Mobile device model and OS version

Motorola Android 7.0 API 24
 Tango Lenova 6.0

Android Beacon Library version

2.15.2

Code:

public class BeaconLiveData extends MutableLiveData implements RangeNotifier, BeaconConsumer, MonitorNotifier {

private Context context;
private BeaconManager beaconManager;
private List<String> beaconUuidList;
private Region region;
private boolean isInitialized;

@Inject
public BeaconLiveData(Context context) {
    this.context = context;
    beaconUuidList = getBeaconUuidList();
    if (!isInitialized) {
        initializeBeaconManager();
    }
}

@Override
public void observe(@NonNull LifecycleOwner owner, @NonNull Observer<Beacon> observer) {
    super.observe(owner, observer);
}

@Override
protected void onActive() {
    super.onActive();
    startMonitoringAndRanging();
}

@Override
protected void onInactive() {
    super.onInactive();
    stopMonitoringAndRanging();
}

private void initializeBeaconManager() {
    beaconManager = BeaconManager.getInstanceForApplication(context);
    BeaconManager.setAndroidLScanningDisabled(true);
    beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout(context.getString(R.string.beacon_layout)));
    region = new Region("backgroundRegion", Identifier.parse(StringConstants.ENTRY_BEACON_UUID), null, null);
    beaconManager.setBackgroundBetweenScanPeriod(ApplicationConstants.SCAN_PERIOD);
    beaconManager.setForegroundBetweenScanPeriod(ApplicationConstants.SCAN_PERIOD);
    beaconManager.bind(this);
    isInitialized = true;
}

private List<String> getBeaconUuidList() {
    return Arrays.asList(StringConstants.test_POS,
            StringConstants.test_ADHOC,
            StringConstants.test_GAS,
            StringConstants.test_LOC,
            StringConstants.test_ENTRY_BEACON_UUID);
}

private boolean istestBeacon(Beacon beacon) {
    if (beaconUuidList != null && !beaconUuidList.isEmpty()) {
        for (String uuid : beaconUuidList) {
            if (beacon.getId1().toString().equals(uuid)) {
                return true;
            }
        }
    }
    return false;
}

private void startMonitoringAndRanging() {
    if (beaconManager != null && isInitialized) {
        beaconManager.addRangeNotifier(this);
        beaconManager.addMonitorNotifier(this);
    } else {
        initializeBeaconManager();
    }
}

private void stopMonitoringAndRanging() {
    if (beaconManager != null) {
        beaconManager.removeRangeNotifier(this);
        beaconManager.removeMonitorNotifier(this);
    }
}

@Override
public void didRangeBeaconsInRegion(Collection<Beacon> collection, Region region) {
    if (collection != null && collection.size() > 0) {
        //beacons were detected;
        for (Beacon beacon : collection) {
            if (beacon != null && istestBeacon(beacon)) {
                setValue(beacon);
                return;
            }
        }
    } else {
        //no beacons in the region;
        setValue(null);
        Logger.d("Beacon has fallen out of range");
    }
}

@Override
public void onBeaconServiceConnect() {
    if (beaconManager != null) {
        beaconManager.addRangeNotifier(this);
        beaconManager.addMonitorNotifier(this);
        try {
            beaconManager.startRangingBeaconsInRegion(region);
        } catch (RemoteException ex) {
            Logger.e(ex.getMessage());
        }
    }
}

@Override
public void didEnterRegion(Region region) {

}

@Override
public Context getApplicationContext() {
    return context;
}

@Override
public void unbindService(ServiceConnection serviceConnection) {

}

@Override
public boolean bindService(Intent intent, ServiceConnection serviceConnection, int i) {
    return false;
}

@Override
public void didExitRegion(Region region) {

}

@Override
public void didDetermineStateForRegion(int i, Region region) {

}

}

IMPORTANT: This forum is reserved for feature requests or reproducible bugs with the library itself. If you need help with using the library with your project, please open a new question on StackOverflow.com.

davidgyoung commented 5 years ago

When implementing BeaconConsumer with non-Context objects, you must chain these methods to a context method: unbindService, bindService, context.

See here for more info: https://stackoverflow.com/a/32866373/1461050

For additional help with project-specific yses of the library, please open new questions on StackOverflow.com so we can keep this forum reserved for bugs and feature requests.

kababu007 commented 5 years ago

It fixes the issues. Thank you.