0

我正在编写一个应用程序,旨在通过将问题分配给信标来帮助孩子们在课堂上起床并活跃起来。该应用程序的工作原理如下:

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

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

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

我还尝试使用 Kontakt.io 网络面板上的信标的详细信息制作信标列表,但我一定错过了将这些生成的信标链接到物理信标或其他东西的步骤,因为listOfHardcodedBeacons.get(0).getDistance()无论您使用哪个信标,都将始终返回 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 种不同的不起作用的解决方案,但我现在不知道该怎么做。任何帮助,将不胜感激。我已尽力使这一点尽可能清楚,但如果您仍需要更多信息,我将很乐意提供。

4

1 回答 1

0

对于任何可能阅读此内容的人,我想出了答案。我所做的是这样的:

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 启动时创建的随机 int,然后使用该 int 作为硬编码信标列表的索引,然后将其用作过滤器的唯一 ID。当 Proximity Manager 开始扫描时,它只会检测到该 uniqueID 的信标。这是我在其他任何地方都没有见过的解决方案,所以我在这里发布以供后代使用。

于 2019-05-04T05:22:58.260 回答