Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Is it possible to load ListPreference items from an adapter?

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.

like image 848
Brad Hein Avatar asked May 29 '10 23:05

Brad Hein


4 Answers

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" />
like image 162
ge0rg Avatar answered Nov 17 '22 21:11

ge0rg


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.

like image 21
CommonsWare Avatar answered Nov 17 '22 21:11

CommonsWare


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

like image 5
DRing Avatar answered Nov 17 '22 20:11

DRing


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.

like image 4
mf511 Avatar answered Nov 17 '22 20:11

mf511