Пример приложения Android Beacon

#android #android-logcat #ibeacon-android

#Android #android-logcat #ibeacon-android

Вопрос:

Я пытаюсь создать приложение на маяках. итак, я получил пример кода отсюда.

Я запустил этот код, и как только я вошел в диапазон beacon, приложение завершило работу, и ошибка в logcat выглядит следующим образом:

 06-20 17:48:24.256: E/AndroidRuntime(18104): android.view.ViewRootImpl$CalledFromWrongThreadException: Only the original thread that created a view hierarchy can touch its views.
  

Пожалуйста, помогите мне.

Я проверил код, и ошибка находится между этими строками.

 iBeaconManager.setRangeNotifier(new RangeNotifier() {
        @Override
        public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
            if (iBeacons.size() > 0) {
                double distance = iBeacons.iterator().next().getAccuracy();
                DecimalFormat decimalFormat = new DecimalFormat("##.##");
                double distanceFormatted = Double.valueOf(decimalFormat.format(distance));
                TextView distanceTextView = (TextView) findViewById(R.id.am_tv_distance);
                distanceTextView.setText(String.valueOf(distanceFormatted)   " m");
            }
        }
    });
  

Ответ №1:

Вам необходимо выполнить изменения пользовательского интерфейса в потоке пользовательского интерфейса:

     iBeaconManager.setRangeNotifier(new RangeNotifier() {
    @Override
    public void didRangeBeaconsInRegion(Collection<IBeacon> iBeacons, Region region) {
        if (iBeacons.size() > 0) {
            double distance = iBeacons.iterator().next().getAccuracy();
            DecimalFormat decimalFormat = new DecimalFormat("##.##");
            double distanceFormatted = Double.valueOf(decimalFormat.format(distance));
            runOnUiThread(new Runnable() {

                  @Override
                  public void run() {
                        TextView distanceTextView = (TextView) findViewById(R.id.am_tv_distance);
                        distanceTextView.setText(String.valueOf(distanceFormatted)   " m");
                  }
            });
         }
    }
});
  

Комментарии:

1. Спасибо, я получаю только расстояние, а не диапазон

2. что бы вы ни делали, когда вы изменяете пользовательский интерфейс, вам нужно делать это в потоке пользовательского интерфейса. Итак, вам нужно изменить эти строки: TextView distanceTextView = (TextView) findViewById(R.id.am_tv_distance); distanceTextView.setText(String.valueOf(distanceFormatted) «m»); с помощью этих строк: runOnUiThread(new Runnable() { @Override public void run() { TextView distanceTextView =(TextView) findViewById(R.id.am_tv_distance);distanceTextView.setText(String.valueOf(distanceFormatted) «m»); } });

3. Это правильно. Вы должны обернуть любые изменения пользовательского интерфейса в метод обратного вызова библиотеки в runOnUiThread.

Ответ №2:

Для CalledFromWrongThreadException ,

напишите функцию и вызовите ее следующим образом:

 private void toastToDisplay(final String line) {
    runOnUiThread(new Runnable() {
        public void run() {
            //Toast.makeText(YourActivity.this, ""   line,
                    // Toast.LENGTH_LONG).show();
            TextView yourTextView = (TextView) findViewById(R.id.your_tv);
            yourTextView .setText(line);
        }
    });
}  
  

При желании вы можете отредактировать эту функцию с помощью требуемого distanceTextView или другого представления.
Что происходит, так это то, что служба выполняется в фоновом потоке вашего приложения, поэтому, когда вы напрямую вызываете операцию, которая обновляет пользовательский интерфейс, она конфликтует с потоком, в котором вы находитесь во время написания этого кода.

Таким образом, если текущий поток не является потоком пользовательского интерфейса, действие отправляется в очередь событий потока пользовательского интерфейса с помощью runOnUiThread

Что именно означает «я получаю только расстояние, а не диапазон»? …для iBeacons.iterator().next().getAccuracy(); части.. вы можете собирать сведения о маяке, используя для каждого цикла, например:

 for (IBeacon iBeacon : iBeacons) {
String line = "Major: "   iBeacon.getMajor()
                                      "Minor: "   iBeacon.getMinor()
                                      "Accuracy in m(s): "
                                      iBeacon.getAccuracy()
                                      "BluetoothAddress: "
                                      iBeacon.getBluetoothAddress()
                                      "Proximity: "   iBeacon.getProximity()
                                      "ProximityUuid: "
                                      iBeacon.getProximityUuid()   "Rssi: "
                                      iBeacon.getRssi()   "TxPower: "
                                      iBeacon.getTxPower(); 
toastToDisplay(line);
    }  
  

В случае, если вы его еще не видели, этот пример приложения для библиотеки Android iBeacon является хорошей ссылкой.