I am programming an app that is intended to help children get up and active in the classroom by assigning questions to beacons. The app works like this:
- enter a gamecode from the api (similar to Kahoot)
- start scanning for beacons
- upon finding and being within a meter of a certain beacon, enter the question screen and ask a question that the user must answer.
- repeat steps 2 and 3 until out of questions.
The problem in question comes from the 2nd step of the process. I am looking to get a list of all beacons I have (either hardcoded into the app, or gathering them on the fly) so that I can easily just pick a random beacon and have the user go find that beacon to answer the next question. When I try to hard code in the beacons, the distancing does not work (it just reads 0.0), and when I try to gather them while the app runs, the app will crash or hang whenever the beacons update. I am using the Kontakt Android SDK.
I have tried putting for
loops in onIBeaconsUpdated
to gather from the list of updating beacons and just pick from those randomly, but it will constantly change the beacon that it is looking for, making it impossible for the user to complete.
I have also tried making a list of beacons using the details from beacons on the Kontakt.io web panel, but I must be missing a step that links these generated beacons to the physical beacons or something because listOfHardcodedBeacons.get(0).getDistance()
will always return 0.0 no matter which beacon you're looking at or how far you are from the beacon.
Please excuse my terrible code:
@Override
protected void onCreate(Bundle savedInstanceState) {
setContentView(R.layout.activity_scanner);
distanceTV = findViewById(R.id.distanceText);
setupProximityManager();
fillBeaconList(listOfHardcodedBeacons);
randint = random.nextInt(listOfHardcodedBeacons.size());
super.onCreate(savedInstanceState);
}
private void fillBeaconList(List<IBeaconDevice> beaconList) {
//beacon #1
BeaconDevice beacon1 = new BeaconDevice.Builder()
.uniqueId("q0hg")
.proximityUUID(UUID.fromString("f7826da6-4fa2-4e98-8024-bc5b71e0893e"))
.major(1)
.minor(0)
.address("D3:95:F8:1E:CB:6E")
.build();
//beacon #2
BeaconDevice beacon2 = new BeaconDevice.Builder()
.uniqueId("eHI1")
.proximityUUID(UUID.fromString("f7826da6-4fa2-4e98-8024-bc5b71e0893e"))
.major(1)
.minor(1)
.address("CF:FE:16:60:0D:50")
.build();
//beacon #3
BeaconDevice beacon3 = new BeaconDevice.Builder()
.uniqueId("R9Bq")
.proximityUUID(UUID.fromString("f7826da6-4fa2-4e98-8024-bc5b71e0893e"))
.major(1)
.minor(2)
.address("CF:81:E3:B6:D1:D0")
.build();
//beacon #4
BeaconDevice beacon4 = new BeaconDevice.Builder()
.uniqueId("zUiD")
.proximityUUID(UUID.fromString("f7826da6-4fa2-4e98-8024-bc5b71e0893e"))
.major(55910)
.minor(12620)
.address("DC:65:69:47:93:26")
.build();
//beacon #5
BeaconDevice beacon5 = new BeaconDevice.Builder()
.uniqueId("QR18")
.proximityUUID(UUID.fromString("f7826da6-4fa2-4e98-8024-bc5b71e0893e"))
.major(30785)
.minor(10106)
.address("D7:1F:B8:AF:85:B2")
.build();
//beacon #6
BeaconDevice beacon6 = new BeaconDevice.Builder()
.uniqueId("uhnG")
.proximityUUID(UUID.fromString("f7826da6-4fa2-4e98-8024-bc5b71e0893e"))
.major(48261)
.minor(35926)
.address("CC:2C:82:59:93:C6")
.build();
beaconList.add(beacon1);
beaconList.add(beacon2);
beaconList.add(beacon3);
beaconList.add(beacon4);
beaconList.add(beacon5);
beaconList.add(beacon6);
}
//TODO: figure out list of known beacons and do stuff
private IBeaconListener createIBeaconListener() {
return new IBeaconListener() {
@Override
public void onIBeaconDiscovered(IBeaconDevice ibeacon, IBeaconRegion region) {
//Toast.makeText(getApplicationContext(), String.format("I found beacon %s! :D", ibeacon.getUniqueId()), Toast.LENGTH_SHORT).show();
}
@Override
public void onIBeaconsUpdated(List<IBeaconDevice> ibeaconList, IBeaconRegion region) {
/* This was my original code. It pulls the closest beacon. It isn't what I want because I don't want the user to keep pulling questions from the same beacon.
String rounded = df.format(ibeaconList.get(0).getDistance());
distanceTV.setText(String.format("Distance to %s: ", ibeaconList.get(0).getUniqueId()) + rounded);
if(ibeaconList.get(0).getDistance() <= 2.7432) { //2.7432 = 9 feet
distanceTV.setText("Found it! :D");
handler.postDelayed(new Runnable() {
@Override
public void run() {
toQuestions();
}
}, 1000);
proximityManager.stopScanning();
}
*/
}
@Override
public void onIBeaconLost(IBeaconDevice ibeacon, IBeaconRegion region) {
//Toast.makeText(getApplicationContext(), String.format("I lost beacon %s! D:", ibeacon.getUniqueId()), Toast.LENGTH_SHORT).show();
}
};
}
public void toQuestions() {
Intent intent = new Intent(this, QuestionActivity.class);
intent.addFlags(Intent.FLAG_ACTIVITY_REORDER_TO_FRONT);
this.startActivity(intent);
finish();
}
As of now, the code will only pull from the first beacon in ibeaconList
and tell the user to go to that one, but that isn't ideal for the goal of the app. As stated earlier, I want to pull from a random list of predefined beacons and just shuffle through the list randomly. I have written and deleted probably 4 different non functioning solutions to my problem and I'm just not sure what to do at this point. Any help would be appreciated. I did my best to make this as clear as possible but if you still need more information I will be happy to provide it.