我想在列表视图中显示检测到的beacon UUID,Major和Minor。当我的onServiceConnect()方法被调用时,它将在列表中添加项(UUID,Major,Minor值)。虽然它在我调试我的代码时显示了列表项,但我的应用程序在几秒钟后终止,让我发现此错误:
适配器的内容已更改,但ListView未收到 通知。确保未修改适配器的内容 来自后台线程,但仅来自UI线程。确保你的 适配器在其内容发生变化时调用notifyDataSetChanged()。
这是我的代码
public class NotifyDemo_Sc4 extends Activity implements BeaconConsumer {
private ListView list;
private ArrayList<String> arrayList;
Button buttonNotify,b2;
private BeaconManager beaconManager;
private BluetoothAdapter mBluetoothAdapter;
private static final String TAG = "MainActivity";
private int nos_calls=0;
private boolean run_call=true;
Beacon beacon;
ArrayAdapter<String> adapter;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_notifydemo);
WebView view = (WebView) findViewById(R.id.myWebView3);
buttonNotify = (Button) findViewById(R.id.buttonViewNotific);
b2 = (Button) findViewById(R.id.buttondemo);
b2.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
Intent i = new Intent(NotifyDemo_Sc4.this, HomeScreen.class);
startActivity(i);
}
});
view.loadUrl("file:///android_asset/name.html");
list = (ListView) findViewById(R.id.listview2);
arrayList = new ArrayList<String>();
adapter = new ArrayAdapter<String>(getApplicationContext(), android.R.layout.simple_spinner_item, arrayList);
list.setAdapter(adapter);
adapter.notifyDataSetChanged();
runOnUiThread(new Runnable() {
public void run() {
adapter.notifyDataSetChanged();
}
});
// requestLayout();
beaconManager = org.altbeacon.beacon.BeaconManager.getInstanceForApplication(this);
beaconManager.getBeaconParsers().add(new BeaconParser().setBeaconLayout("m:2-3=0215,i:4-19,i:20-21,i:22-23,p:24-24,d:25-25"));
beaconManager.bind(this);
beaconManager.setDebug(true);
beaconManager.setBackgroundScanPeriod(1100l);
beaconManager.setAndroidLScanningDisabled(false);
Log.d(TAG, "didEnterRegion" + beaconManager);
mBluetoothAdapter = ((BluetoothManager) getSystemService(Context.BLUETOOTH_SERVICE)).getAdapter();
// Create the adapter to convert the array to views
// ArrayAdapter adapter = new ArrayAdapter<>(this, arrayOfDevices);
// Attach the adapter to a ListView
}
@Override
protected void onDestroy() {
super.onDestroy();
beaconManager.unbind(this);
}
@Override
public void onBeaconServiceConnect() {
blefunction();
// nos_calls++;
final Region region = new Region("myBeaons", Identifier.parse("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"), null, null);
// runOnUiThread(new Runnable() {
final Handler handler = new Handler();
handler.postDelayed(new Runnable() {
@Override
public void run() {
beaconManager.setRangeNotifier(new RangeNotifier() {
@Override
public void didRangeBeaconsInRegion(Collection<Beacon> beacons, Region region) {
for (Beacon beacon : beacons) {
beacon = beacons.iterator().next();
String b = beacon.toString();
double b2 = beacon.getDistance();
Log.i(TAG, "The first beacon I see is about " + beacon.toString() + " Distance " + beacon.getDistance() + " meters away.");
Log.i(TAG, "Beacon Detected" + beacon.toString());
arrayList.add("Beacon UUID, Major, Minor:" + b + "\n");
Toast.makeText(getApplicationContext(), " The beacon " + "The distance " + beacon.getDistance() + " meters away.", Toast.LENGTH_SHORT);
}
}
});
}}, 3000);
try
{
beaconManager.startRangingBeaconsInRegion(new Region("myRangingUniqueId", Identifier.parse("E2C56DB5-DFFB-48D2-B060-D0F5A71096E0"), Identifier.parse("0"), Identifier.parse("1")));
}
catch(RemoteException e){}
}
void blefunction()
{if(run_call = true){
mBluetoothAdapter.startLeScan(new BluetoothAdapter.LeScanCallback() {
@Override
public void onLeScan(final BluetoothDevice device, int rssi, byte[] scanRecord) {
Log.d(TAG, "Scanned BLE device with mac: " + device.getAddress());
String add = "C4:BE84:05:EE:BF";
long e = System.currentTimeMillis();
Log.i(TAG, "in " + (e) + "ms");
// Toast.makeText(getApplicationContext(), "BLE Scanned Device Address: " + device.getAddress() + "/n" + "Time in milliseconds:" + e + " ms", Toast.LENGTH_SHORT).show();
run_call = false; }
});}}
}
答案 0 :(得分:0)
问题是由于任何非UI线程的线程操纵它包含的adapter
或arrayList
引起的。至少有一行更改了信标回调中的arrayList
,这不在UI线程上:
arrayList.add("Beacon UUID, Major, Minor:" + b + "\n");
要解决此问题,您需要将该行包装在如下所示的块中。为了获得最佳效率,您应该将整个信标迭代循环包装在这样的块中,这样您就不会在循环内重复创建新的Runnable
。
runOnUiThread(new Runnable() {
public void run() {
...
}
});
您还需要从UI线程调用adapter.notifyDataSetChanged();
以使更改生效。你应该把它添加到块的末尾。
虽然这不是问题的一部分,但值得注意的是,迭代beacons
的循环内的以下行会将beacon
的值设置为列表中的第一项。这可能会违背迭代beacons
的目的,因此您可能希望删除该行:
beacon = beacons.iterator().next();