Kontakt.io SDK:有没有办法在信标列表中进行硬编码,以便我可以在需要搜索信标时随机从中提取?

Kontakt.io SDK: Is there a way to hard code in a list of beacons so that I can pull from them randomly whenever I need to search for a beacon?

我正在编写一个应用程序,旨在通过向信标分配问题来帮助 children 在课堂上活跃起来。该应用程序的工作方式如下:

  1. 从 api(类似于 Kahoot)
  2. 输入游戏代码
  3. 开始扫描信标
  4. 找到某个信标并在其一米范围内时,进入问题屏幕并提出用户必须回答的问题。
  5. 重复第 2 步和第 3 步,直到没有问题。

问题来自流程的第 2 步。我希望获得我拥有的所有信标的列表(硬编码到应用程序中,或即时收集它们),以便我可以轻松地选择一个随机信标并让用户找到该信标来回答下一个问题。当我尝试在信标中进行硬编码时,距离不起作用(它只读取 0.0),当我尝试在应用程序运行时收集它们时,只要信标更新,应用程序就会崩溃或挂起。我正在使用 Kontakt Android SDK。

我尝试在 onIBeaconsUpdated 中放置 for 循环以从更新信标列表中收集并随机选择这些信标,但它会不断改变它正在寻找的信标,使得用户不可能完成。

我也曾尝试使用 Kontakt.io 网络面板上信标的详细信息制作信标列表,但我必须缺少将这些生成的信标链接到物理信标或其他东西的步骤,因为 listOfHardcodedBeacons.get(0).getDistance() 将始终 return 0.0 无论您正在查看哪个信标或您离信标有多远。

请原谅我糟糕的代码:

 @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();
    }

截至目前,代码只会从 ibeaconList 中的第一个信标提取并告诉用户转到那个信标,但这对于应用程序的目标来说并不理想。如前所述,我想从一个随机的预定义信标列表中抽取,然后随机地在列表中随机播放。我已经为我的问题编写并删除了可能有 4 种不同的无效解决方案,我只是不确定此时该怎么做。任何帮助,将不胜感激。我已尽力使这一点尽可能清楚,但如果您仍需要更多信息,我将很乐意提供。

对于可能读到这篇文章的任何人,我找到了答案。我所做的是:

IBeaconFilter filter;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        setContentView(R.layout.activity_scanner);
        distanceTV = findViewById(R.id.distanceText);
        fillBeaconList(listOfHardcodedBeacons);
        randint = random.nextInt(listOfHardcodedBeacons.size());
        filter = new IBeaconUniqueIdFilter(listOfHardcodedBeacons.get(randint).getUniqueId());

        setupProximityManager();

        super.onCreate(savedInstanceState);
    }

private void setupProximityManager(){
        proximityManager = ProximityManagerFactory.create(this);

        //configure proximity manager basic options
        proximityManager.configuration()
                //using ranging for continuous scanning or MONITORING for scanning with intervals
                .scanPeriod(ScanPeriod.RANGING)
                //using BALANCED for best performance/battery ratio
                .scanMode(ScanMode.LOW_LATENCY)
                //OnDeviceUpdate callback will be received with 1 second interval
                .deviceUpdateCallbackInterval(TimeUnit.MILLISECONDS.toMillis(20));

        //setting up iBeacon and Eddystone spaces listeners
        //proximityManager.setSpaceListener(createSpaceListener());

        //setting up iBeaconListener to only listen for random beacon (filter)
        proximityManager.filters().iBeaconFilter(filter);
        proximityManager.setIBeaconListener(createIBeaconListener());
        proximityManager.setEddystoneListener(new SimpleEddystoneListener() {
        });

    }

这让我可以在 onIBeaconsUpdated 中保留我现有的(已注释的)代码,而不会出现任何混乱的列表。该解决方案采用在 Activity 开始时创建的随机整数,然后将该整数用作硬编码信标列表的索引,然后将其用作过滤器的唯一 ID。当 Proximity Manager 开始扫描时,它只会检测该 uniqueID 的信标。这是我在其他任何地方都没有见过的解决方案,所以我在这里发布以供后代使用。