0
votes

I am using AltBeacon library in Android App.

I implement an activity followed by example and it is okay to detect beacon and trigger didEnterRegion successfully. ex

public class MonitoringActivity extends Activity implements BeaconConsumer {

And then I implement a background application and it is okay to detect beacon and trigger didEnterRegion in background. ex

public class BackgroundApplication extends Application implements BootstrapNotifier {

But when I try to combine them together, it does not work.

What I want to do is: call a MonitoringActivity to start beaconManager.startMonitoringBeaconsInRegion from BackgroundApplication didEnterRegion() call.

The idea is :

BackgroundApplication watch specific uuid + major:null + minor:null. When it detected, start activity which implements beaconConsumer and it watch small specific region with specific major and minor id and do the related action, ex query data from cloud by specific major/minor id.

My test tells me:

  1. when I have "regionBootstrap = new RegionBootstrap(this, regionList);" in BackgroundApplication onCreate(), the MonitoringActivity shows nothing even if beacon is advertising. After I remove regionBootStrap register, MonitoringActivity shows beacon correctly.

  2. In previous case, another way to make MonitoringActivity show beacon correctly is : pause the app (go to background) and resume it (back to foreground) again and then MonitoringActivity didEnterRegion triggered correctly.

  3. I try to push back regionBootstrap register from app launch time to later, ex MonitoringActivity onPause(). In this case, after app launch, MonitoringActivity show beacons correctly. And when I pause it to background, the startBeaconMonitoring() called which do the regionBootstrap register. but in this case, the background task cannot detect the beacon didEnterRegion.

I guess it is caused by one beaconManager in BackgroundApplication and another beaconManager in MonitoringActivity and they are conflicted but I am not sure.

Here is my AndroidManifest.xml

<application
    android:name="com.abc.BackgroundApplication"
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:launchMode="singleInstance"
        android:name="com.abc.MonitoringActivity"
        android:label="@string/app_name"
        android:screenOrientation="portrait" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
</application>

Now my temporary solution is back to general usage: 1. make monitorActivity clean as normal activity without beacon monitoring activity. 2. let backgroundApplication monitor region with specific uuid/major/minorId in background. When region entered, call and pass major/minorId to monitorActivity and do the related action.

But in this way, I need to pre-configure all specific uuid/major/minorId in backgroundApplication for region callback.

I want to monitor simple one specific uuid and null major/minorId region in backgroundApplication and let monitorActivity handle the different region case of different major/minorId. Is it possible?

Ex, create and monitor a region xxx/null/null and when didEnterRegion is triggered, we can get it is triggered by which exactly major/minorId. Now major/minorId I get from region is null/null which is the same as what I created.

Any comment is appreciated.

Updated: Here is my first idea which is the same as David's suggestion. But as I mentioned, the MonitorActivity onBeaconServiceConnect is called but didEnterRegion won't be callback. But after I I pause it to background and resume it again to foreground, the didEnterRegion is called correctly. That is why I try to ask for some suggestions.

In BackgroundApplication:

@Override
public void onCreate() {
    super.onCreate();
    Log.i(TAG, "App started up");
    BeaconManager beaconManager = BeaconManager.getInstanceForApplication(this);
    beaconManager.getBeaconParsers().add(new BeaconParser().
            setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24"));
    //set scan frequency
    beaconManager.setBackgroundBetweenScanPeriod(5000);

    // wake up the app when any beacon is seen (you can specify specific id filers in the parameters below)
    String uuid1 = "e37ba058-c5bd-40f0-b71d-xxxxxxxxxxxx";
    Identifier id1 = Identifier.parse(uuid1);
    Region region1 = new Region("com.abc.beaconRegion1", id1, null, null);

    ArrayList regionList = new ArrayList<Region>();
    regionList.add(region1);
    regionBootstrap = new RegionBootstrap(this, regionList);
}

@Override
public void didEnterRegion(org.altbeacon.beacon.Region region) {
    Log.i(TAG, "Got a didEnterRegion call");
    Intent intent = new Intent(this, MonitoringActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
    this.startActivity(intent);
}

At MonitorActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_monitor);

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

    //set table layout view
    msgList = (TableLayout)findViewById(R.id.msgList);
    msgList.setStretchAllColumns(true);
}

@Override
public void onBeaconServiceConnect() {
    beaconManager.setMonitorNotifier(new MonitorNotifier() {
        @Override
        public void didEnterRegion(Region region) {
            Log.i(TAG,"didEnterREgion");
            if(region.getId1() == null || region.getId2() == null || region.getId3() == null) {
                return;
            }
            Log.i(TAG, "I just saw an beacon for the first time!");
            uuid = region.getId1().toString();
            majorId = region.getId2().toInt();
            minorId = region.getId3().toInt();
        }
        @Override
        public void didExitRegion(Region region) {

        }

        @Override
        public void didDetermineStateForRegion(int state, Region region) {
        }
    });

    try {
        String uuid = "e37ba058-c5bd-40f0-b71d-xxxxxxxxxxxx";
        Identifier uuidId1 = Identifier.parse(uuid);
        Identifier majorId1 = Identifier.fromInt(21617);
        Identifier minorId1 = Identifier.fromInt(515);
        Identifier minorId2 = Identifier.fromInt(545);
        Region region1 = new Region("com.abc.beaconRegion1", uuidId1, majorId1, minorId1);
        beaconManager.startMonitoringBeaconsInRegion(region1);
        Region region2 = new Region("com.abc.beaconRegion2", uuidId2, majorId1, minorId2);
        beaconManager.startMonitoringBeaconsInRegion(region2);
        Log.i(TAG,"beaconManager start monitor beacons in region");

    } catch (RemoteException e) {
        Log.e("log_tag", e.toString());
    }
}
1

1 Answers

0
votes

A few tips:

  • The RegionBootstrap class is only designed to be used a single time in a central Application class. Using on in an Activity class, and using multiple instances of RegionBootstrap will not work properly.

  • When using RegionBootstrap you may add new regions to monitor dynamically from an Activity simply by calling: BeaconManager.getInstanceForApplication(MyActivity.this).startMonitoringBeaconsInRegion(region); Any beacons discovered will be included in the didEnterRegion callback in the central application class. You may the use a variety of techniques to pass the information about the detected beacons from your central Application class to the Activity.

  • Alternately to the point immediately above, you may also start monitoring beacons in an Activity using code like in the Monitoring Sample Code here. This involves binding to the BeaconManager from the Activity with beaconManager.bind(MyActivity.this); then starting monitoring for your specific region after the onBeaconServiceConnect() method is called.