Question

I am using the RadiusNetworks API to work with iBeacons.

I have made use of this library and it works fine, however i would have to ask what i am doing wrong that the background scanning does not happen in my application? What am I missing?

Here's the implementation i have so far, i only kept the code relevant to the beacon side, however setting the activity to background stops the scanning completely...

package ro.gebs.zonizbeacon;



public class MainActivity extends FragmentActivity
        implements NavigationDrawerFragment.NavigationDrawerCallbacks, SearchView.OnQueryTextListener, IBeaconConsumer, RangeNotifier, IBeaconDataNotifier {
    /**
     * Fragment managing the behaviors, interactions and presentation of the navigation drawer.
     */
    private NavigationDrawerFragment mNavigationDrawerFragment;
    private MainOffersFragment mOffersFragment;

    protected static final String TAG = "BeaconActivity";
    private IBeaconManager iBeaconManager = IBeaconManager.getInstanceForApplication(this);


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);

        //getActionBar().setIcon(R.drawable.home);
        setContentView(R.layout.activity_main);



        BeaconUtils.verifyBluetooth(MainActivity.this);
        iBeaconManager.bind(this);
    }




    @Override
    protected void onDestroy() {
        super.onDestroy();
        iBeaconManager.unBind(this);
    }

    @Override
    protected void onPause() {
        super.onPause();
        if (iBeaconManager.isBound(this)) iBeaconManager.setBackgroundMode(this, true);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (iBeaconManager.isBound(this)) iBeaconManager.setBackgroundMode(this, false);

    }


    @Override
    public void onIBeaconServiceConnect() {
        Region region = new Region("MainActivityRanging", null, null, null);
        try {
            iBeaconManager.startRangingBeaconsInRegion(region);
            iBeaconManager.setRangeNotifier(this);
        } catch (RemoteException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void iBeaconDataUpdate(IBeacon iBeacon, IBeaconData iBeaconData, DataProviderException e) {
        if (e != null) {
            Log.d(TAG, "data fetch error:" + e);
        }
        if (iBeaconData != null) {
            String displayString = iBeacon.getProximityUuid() + " " + iBeacon.getMajor() + " " + iBeacon.getMinor() + "\n" + "Welcome message:" + iBeaconData.get("welcomeMessage");
            Log.d(TAG, displayString);
        }
    }

    @Override
    public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
        for (IBeacon iBeacon : iBeacons) {
            iBeacon.requestData(this);
            String displayString = iBeacon.getProximityUuid() + " " + iBeacon.getMajor() + " " + iBeacon.getMinor() + "\n";
            Log.d(TAG, displayString);
        }
    }
}
Was it helpful?

Solution

How are you sending your activity to the background? Are you hitting the back button, the home button or what?

I suspect what is happening is that Android is actually terminating your App. Your onDestroy method looks like this:

@Override
protected void onDestroy() {
    super.onDestroy();
    iBeaconManager.unBind(this);
}

If Android calls this method, the iBeaconManager will unbind to the AndroidIBeaconService effectively stopping scanning. Even if you remove this code, Android will still kill the service automatically if it decides to terminate the app.

If you want to keep this running in the background, you need to attach the IBeaconManager to something that has a longer life cycle than that activity. The easiest way to do this is with a custom Android Application class like this (which must also be declared in your manifest):

public class MyTestIBeaconApplication extends Application {
    private BackgroundPowerSaver backgroundPowerSaver;
    private IBeaconManager iBeaconManager;

    public void onCreate() {
        super.onCreate();
        // Simply constructing this class and holding a reference to it 
        // enables auto battery saving of about 60%
        backgroundPowerSaver = new BackgroundPowerSaver(this);
        iBeaconManager = IBeaconManager.getInstanceForApplication(this);
    }
}

The BackgroundPowerSaver part (only in the Pro version of the library) is optional, but will automatically slow down the scans frequency when your app is in the background to save battery. If you use this, you no longer have to make calls to setBackgroundMode in your various onPause and onResume methods.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top