Reputation: 137
I'm using the Estimote SDK for Android. I'm trying to change the provided code on the official site. I want to show the list of the detected beacons in a ListFragment (with some information for each Beacon).
In my main Activity i start all the necessary (service, listeners..), and in particular i have this onCreate(...) method:
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
beaconManager.setRangingListener(new BeaconManager.RangingListener() {
@Override
public void onBeaconsDiscovered(Region region, List<Beacon> beacons) {
// update the list of the beacons in the ListFragment in some way
}
});
}
If i understood correctly, this method is called continuosly every fixed time.
This is the code of the ListFragment:
public class DiscoveredBeacons extends ListFragment {
private List<Beacon> beacons = new ArrayList<Beacon>();
private Beacon beacon;
private View mContentView = null;
@Override
public void onActivityCreated(Bundle savedInstanceState) {
super.onActivityCreated(savedInstanceState);
this.setListAdapter(new MyListAdapter(getActivity(), R.layout.beacon_row, beacons));
}
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
mContentView = inflater.inflate(R.layout.beacons_list, null);
return mContentView;
}
// this does not work if i call it from the main Activity
public void updateList(List<Beacon> beacons) {
beacons.clear();
beacons.addAll(beacons);
((MyListAdapter) getListAdapter()).notifyDataSetChanged();
}
private class MyListAdapter extends ArrayAdapter<Beacon> {
private List<Beacon> items;
public MyListAdapter(Context context, int textViewResourceId,
List<Beacon> items) {
super(context, textViewResourceId, items);
this.items = items;
}
@Override
public View getView(int position, View convertView, ViewGroup parent) {
View v = convertView;
if (v == null) {
LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.beacon_row, null);
}
Beacon beacon = items.get(position);
if (beacon != null) {
TextView number = (TextView) v.findViewById(R.id.number);
TextView rssi = (TextView) v.findViewById(R.id.rssi);
TextView power = (TextView) v.findViewById(R.id.power);
TextView distance = (TextView) v.findViewById(R.id.distance);
if(number != null) {
number.setText("Beacon number " + (position + 1));
}
if (rssi != null) {
rssi.setText("rssi: " + beacon.getRssi()); // int
}
if (power != null) {
power.setText("power: " + beacon.getMeasuredPower()); // int
}
if(distance != null) {
distance.setText("distance: " + Utils.computeAccuracy(beacon));
}
}
return v;
}
}
}
As you can see, i tried to put a public method in the ListFragment, and call it the listener inside the onCreate, but this doesn't work. In particular i get an exception:
04-01 20:14:04.029 18052-18052/it.loris.beaconsdetector E/AndroidRuntime﹕ FATAL EXCEPTION: main Process: it.loris.beaconsdetector, PID: 18052 java.lang.UnsupportedOperationException at java.util.Collections$UnmodifiableCollection.clear(Collections.java:936) at it.loris.beaconsdetector.DiscoveredBeacons.updateList(DiscoveredBeacons.java:40) at it.loris.beaconsdetector.BeaconsDetector$1.onBeaconsDiscovered(BeaconsDetector.java:41) at com.estimote.sdk.BeaconManager$IncomingHandler.handleMessage(BeaconManager.java:479) at android.os.Handler.dispatchMessage(Handler.java:102) at android.os.Looper.loop(Looper.java:135) at android.app.ActivityThread.main(ActivityThread.java:5274) at java.lang.reflect.Method.invoke(Native Method) at java.lang.reflect.Method.invoke(Method.java:372) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:909) at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:704)
Thank you for your help.
Upvotes: 1
Views: 278
Reputation: 827
Try adding this to getView()
if (convertView == null) {
LayoutInflater vi = (LayoutInflater) getActivity().getSystemService(
Context.LAYOUT_INFLATER_SERVICE);
v = vi.inflate(R.layout.beacon_row, null);
} else { v = convertView; }
Upvotes: 0
Reputation: 5893
It's an easy mistake. You are trying to clear a List of Beacons, but not your list, the list instance you receive from the method. Use "this" to access your beacon in your list fragment. and add the beacons you receive from the method. this should fix it.
// this does not work if i call it from the main Activity
public void updateList(List<Beacon> beacons) {
// Call this to refer your variable in List fragment
this.beacons.clear();
this.beacons.addAll(beacons);
((MyListAdapter) getListAdapter()).notifyDataSetChanged();
}
Upvotes: 1