4
votes

I am trying to get the Major and Minor values from a iBeacon in background. Right now I'm able to detect when I'm entering into a Region but I don't know which Major or Minor the beacon is advertising. Is there any way of getting this? Or should I use the normal bluetooth api provided by Google to get the raw data and capture the needed bytes? Once I use either AltBeacon and Bluetooth standard libs I don't get anything.

I used the example code provided in http://altbeacon.github.io/android-beacon-library/samples.html in order to get the background region detection and implemented the interface BluetoothAdapter.LeScanCallback in order to get the raw data to get the Major and Minor bytes, but as I add all I need to get that the app doesn't even enter in didEnterRegion method.

Regards,

Iván

2

2 Answers

4
votes

In order to read the beacon identifiers, simply use the ranging APIs:

beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", null, null, null));           
beaconManager.setRangeNotifier(new RangeNotifier() {
    @Override 
    public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
        if (beacons.size() > 0) {
            Log.i(TAG, "The first beacon I see has minor id "+beacons.iterator().next().getId3());  
        }
    }
});

You must call the above after you have entered the region or after you have a service connection.

1
votes

Fixed!!! Yes, it's posible. I post the example code here: I hope someone finds this useful

Regards.

public class MyRegionApp extends Application implements BootstrapNotifier, BluetoothAdapter.LeScanCallback {
    private final String DebugTag="HOLAREGION";
    private RegionBootstrap regionBootstrap;
    private BackgroundPowerSaver backgroundPowerSaver;
    private BeaconManager mBeaconManager;
    private static final String UUID = "01122334-4556-6778-899a-abbccddeeff0";
    private long time=0;
    private BluetoothAdapter mBluetoothAdapter;
    private String Minor;
    private String Major;
    private String UUID1;
    private BluetoothManager bluemanager;

    @Override
    public void onCreate() {
        super.onCreate();
        time=System.currentTimeMillis();
        Log.d(DebugTag, "App started up");
        bluemanager= (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        mBluetoothAdapter = bluemanager.getAdapter();
        mBeaconManager = BeaconManager.getInstanceForApplication(this);
        //BeaconManager.getInstanceForApplication(this).getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:0-3=4c000215,i:4-19,i:20-21,i:22-23,p:24-24"));
        mBeaconManager.setBackgroundScanPeriod(1100l);

        mBeaconManager.setBackgroundBetweenScanPeriod(1100l);
        Region region = new Region("allbeacons", Identifier.parse(UUID) , null, null);

        //Region region = new Region("allbeacons", Identifier.parse(UUID) , null, null);
        //Region region = new Region("allbeacons", null , null, null);
        backgroundPowerSaver = new BackgroundPowerSaver(this);

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



    }




    @Override
    public void didDetermineStateForRegion(int arg0, Region arg1) {
        // TODO Auto-generated method stub
        Log.d(DebugTag, "Got a didDetermineStateForRegion call with region:"+arg1.toString() );
    }

    @Override
    public void didEnterRegion(Region arg0) {
        // TODO Auto-generated method stub
        time=System.currentTimeMillis()-time;

        Log.d(DebugTag, "Got a didEnterRegion call region:"+arg0.getUniqueId());
        Log.d(DebugTag, "Got a didEnterRegion call region TIME: "+time);



        mBluetoothAdapter.startLeScan(this);

        //Descomentar la siguiente línea si se desea que únicamente se lance la actividad únicamente la primera vez que la beacon es vista
        //regionBootstrap.disable();

        Toast.makeText(getApplicationContext(), "ENTRA EN LA REGION!!!",
                   Toast.LENGTH_SHORT).show();

        Intent intent = new Intent(this, MainActivity.class);
        intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
        this.startActivity(intent);

    }

    @Override
    public void didExitRegion(Region arg0) {
        // TODO Auto-generated method stub
        Log.d(DebugTag, "Got a didExitRegion call");
        Log.d(DebugTag, "Got a didExitRegion call with region:"+arg0.getUniqueId() );
    }



    @Override
    public void onLeScan(BluetoothDevice device, int rssi, byte[] scanRecord) {
        // TODO Auto-generated method stub
        Log.d(DebugTag, "Entra en onLeScan");
        Major="";
        Minor="";
        UUID1="";

        for (int i = 0; i<scanRecord.length; i++){
            if(i>8 && i<25)
                UUID1 += String.format("%02x", scanRecord[i]);
            else if(i>24 && i<27)
                Major += String.format("%02x", scanRecord[i]);
            else if(i>26 && i<29)
                Minor += String.format("%02x", scanRecord[i]);



        }

        stop();
        Log.d(DebugTag, "Got a didExitRegion call with MAJOR:"+Major+" MINOR: "+Minor+" and UUID: "+UUID1  );
    }

    public void stop(){

        mBluetoothAdapter.stopLeScan(this);
        Log.d(DebugTag+": scanLeDevice->"," REGION Stopped");
        Log.d(DebugTag, "Got a didExitRegion call with MAJOR:"+Major+" MINOR: "+Minor );

    }



}

With davidgyoung advised I got what I want as follows. Maybe I made mistakes but it works for me that I want to get once the log with the iBeacon info:

@Override
    public void onCreate() {
        super.onCreate();
        time=System.currentTimeMillis();
        Log.d(DebugTag, "App started up");
        //bluemanager= (BluetoothManager)getSystemService(Context.BLUETOOTH_SERVICE);
        //mBluetoothAdapter = bluemanager.getAdapter();
        mBeaconManager = BeaconManager.getInstanceForApplication(this);
        mBeaconManager.setBackgroundScanPeriod(8000l);

        mBeaconManager.setBackgroundBetweenScanPeriod(1100l);
        Region region = new Region("allbeacons", Identifier.parse(UUID) , null, null);

        //Region region = new Region("allbeacons", Identifier.parse(UUID) , null, null);
        //Region region = new Region("allbeacons", null , null, null);
        backgroundPowerSaver = new BackgroundPowerSaver(this);

        regionBootstrap = new RegionBootstrap(this, region);




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



    }




    @Override
    public void didDetermineStateForRegion(int arg0, Region arg1) {
        // TODO Auto-generated method stub
        Log.d(DebugTag, "Got a didDetermineStateForRegion call with region:"+arg1.toString() );
    }

    @Override
    public void didEnterRegion(Region arg0) {
        // TODO Auto-generated method stub
        time=System.currentTimeMillis()-time;

        Log.d(DebugTag, "Got a didEnterRegion call region:"+arg0.getUniqueId());
        Log.d(DebugTag, "Got a didEnterRegion call region TIME: "+time);


        if(enabler==true)
        {
             try {
                    mBeaconManager.startRangingBeaconsInRegion(arg0);
                    enabler=false;
                } catch (RemoteException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }   
        }






         mBeaconManager.setRangeNotifier(new RangeNotifier() {

                @Override
                public void didRangeBeaconsInRegion(Collection<Beacon> arg0,
                        Region arg1) {
                    // TODO Auto-generated method stub
                    if (arg0.size() > 0) {
                        Log.i(DebugTag, "The first beacon I see has UUID: "+arg0.iterator().next().getId1()+" major id:"+arg0.iterator().next().getId2()+"  minor id: "+arg0.iterator().next().getId3());  
                    }
                    try {
                        mBeaconManager.stopRangingBeaconsInRegion(arg1);
                    } catch (RemoteException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }

                }
            });


    }

    @Override
    public void didExitRegion(Region arg0) {
        // TODO Auto-generated method stub
        Log.d(DebugTag, "Got a didExitRegion call");
        Log.d(DebugTag, "Got a didExitRegion call with region:"+arg0.getUniqueId() );
        enabler=true;
    }


}