I'm setting out to create a settings activity for my app. I've defined a PreferenceActivity
with a nice layout including a ListPreference
object for the user to select a bluetooth device. I'm having trouble dynamically populating the list.
I would like to populate ListPreference
with values from an array adapter (which I'll create and populate with relevant bluetooth device names).
If this were a spinner View, I could just call setAdapter()
. However with the ListPreference
object I can't figure out how to attach an adapter (findviewByID
won't cast from View To ListPreference
, so I can't even get a handle to the object).
I would like to attach an adapter and then populate the adapter with values, which in turn would populate the ListPreference
with values.
ListPreference
doesn't work with adapters, it works with strings. See setEntries()
and setEntryValues()
To get at your ListPreference
, call findPreference()
on your PreferenceActivity
. Cast the Preference
you get back to ListPreference
.
For the special case of a list of bluetooth devices, you can use the following class:
package de.duenndns;
import android.bluetooth.*;
import android.content.Context;
import android.preference.ListPreference;
import android.util.AttributeSet;
import java.util.Set;
public class BluetoothDevicePreference extends ListPreference {
public BluetoothDevicePreference(Context context, AttributeSet attrs) {
super(context, attrs);
BluetoothAdapter bta = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = bta.getBondedDevices();
CharSequence[] entries = new CharSequence[pairedDevices.size()];
CharSequence[] entryValues = new CharSequence[pairedDevices.size()];
int i = 0;
for (BluetoothDevice dev : pairedDevices) {
entries[i] = dev.getName();
if (entries[i] == null) entries[i] = "unknown";
entryValues[i] = dev.getAddress();
i++;
}
setEntries(entries);
setEntryValues(entryValues);
}
public BluetoothDevicePreference(Context context) {
this(context, null);
}
}
It can be involved directly from your prefs XML to store the MAC as a prefs string:
<de.duenndns.BluetoothDevicePreference
android:key="bluetooth_mac"
android:title="Bluetooth Device"
android:dialogTitle="Choose Bluetooth Device" />
Just an Update to this in case someone else comes along, ge0rg answer works but changed it a little to take in consideration of multiple preferences and not just the bluetooth one and also if they dont have any paired devices set up so you dont get an error with a null array.
ListPreference BTList = (ListPreference) findPreference("your preference key");
BluetoothAdapter mBluetoothAdapter = BluetoothAdapter.getDefaultAdapter();
Set<BluetoothDevice> pairedDevices = mBluetoothAdapter.getBondedDevices();
CharSequence[] entries = new CharSequence[1];
CharSequence[] entryValues = new CharSequence[1];
entries[0] = "No Devices";
entryValues[0] = "";
if(pairedDevices.size() > 0){
entries = new CharSequence[pairedDevices.size()];
entryValues = new CharSequence[pairedDevices.size()];
int i=0;
for(BluetoothDevice device : pairedDevices){
entries[i] = device.getName();
entryValues[i] = device.getAddress();
i++;
}
}
BTList.setEntries(entries);
BTList.setEntryValues(entryValues);
`Hope this helps someone...oh and this is put under the onCreate method for the preference activity
Another way would be to override onPrepareDialogBuilder of ListPreference and to initialize setSingleChoiceItems of AlertDialog.Builder directly with your adapter:
public class AdapterListPreference extends ListPreference
{
@Override
protected void onPrepareDialogBuilder( AlertDialog.Builder builder )
{
// don't call super.onPrepareDialogBuilder() because it'll check
// for Entries and set up a setSingleChoiceItems() for them that
// will never be used
final ListAdapter adapter = …;
builder.setSingleChoiceItems(
adapter,
0,
new DialogInterface.OnClickListener()
{
@Override
public void onClick( DialogInterface dialog, int which )
{
// adapter.getItemId( which )
dialog.dismiss();
}
} );
builder.setPositiveButton( null, null );
}
}
If you look at the Android sources, you'll find that onPrepareDialogBuilder() does call:
public AlertDialog.Builder setSingleChoiceItems (CharSequence[] items, int checkedItem, DialogInterface.OnClickListener listener)
with those entry arrays. To make ListPreference use some adapter (e.g. ArrayAdaper, CursorAdapter), you just need to call:
public AlertDialog.Builder setSingleChoiceItems (ListAdapter adapter, int checkedItem, DialogInterface.OnClickListener listener)
instead.
This way ListPreference will operate on the adapter directly and you don't need to copy the data from the adapter to put them into the entries arrays.
Find a working sample here.