#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 является хорошей ссылкой.