Guillaume P. Guillaume P. - 4 months ago 9
Android Question

What am i doing wrong? Saving ArrayList of BluetoothDevice to SharedPreferences

I am currently writing an android application to control Bluetooth Devices. I am trying to save an

ArrayList<BluetoothDevice>
to
SharedPreferences
using Gson and Json classes, but when I try running this bit of code on my phone, I can't get the name of each device but I can get their addresses. I see this error in Android Monitor log (using Android Studio) :


03-28 16:12:51.706 17640-17640/? E/BluetoothDevice: BT not enabled.
Cannot get Remote Device name


I'm using a custom class to manage the list of Devices, here is the relevant code :

public class DeviceList {

private ArrayList<BluetoothDevice> mDeviceList_bt;
private ArrayList<String> mDeviceList_s;

private ArrayAdapter mAdapter;

private String PREFS_NAME;

SharedPreferences mPrefs;
SharedPreferences.Editor mEditor;

private int i = 0;

public DeviceList(Context c, String Prefs_Name){

this.PREFS_NAME = Prefs_Name;

mDeviceList_bt = new ArrayList<BluetoothDevice>();
mDeviceList_s = new ArrayList<String>();

mPrefs = PreferenceManager.getDefaultSharedPreferences(c);
mEditor = mPrefs.edit();

mAdapter = new ArrayAdapter(c, android.R.layout.simple_list_item_1, mDeviceList_s);
}

public void readFromSharedPrefs(){

Gson gson = new Gson();
String json = mPrefs.getString(PREFS_NAME, null);
Type type = new TypeToken<ArrayList<BluetoothDevice>>() {}.getType();
mDeviceList_bt = gson.fromJson(json, type);

for (BluetoothDevice device : mDeviceList_bt) {
mDeviceList_s.add(device.getName() + "\n" + device.getAddress());
}

mAdapter.notifyDataSetChanged();
}

public void saveToSharedPrefs(){
Gson gson = new Gson();
String json = gson.toJson(mDeviceList_bt); // myObject - instance of MyObject
mEditor.putString(PREFS_NAME, json);
mEditor.commit();
}


For example, if I save the list with these 3 devices :

DeviceName1
8C:DE:52:FA:96:0A

DeviceName2
00:3E:01:00:47:4E

DeviceName3
8C:DE:52:FA:B5:F0


I get this after I read from
SharedPreferences
:

null
8C:DE:52:FA:96:0A

null
00:3E:01:00:47:4E

null
8C:DE:52:FA:B5:F0


Any idea what I am doing wrong?

Thank you in advance!

Answer

The device name is not saved in BluetoothDevice. Instead the name is cached in the BluetoothService:

/**
 * Get the friendly Bluetooth name of the remote device.
 *
 * <p>The local adapter will automatically retrieve remote names when
 * performing a device scan, and will cache them. This method just returns
 * the name for this device from the cache.
 * <p>Requires {@link android.Manifest.permission#BLUETOOTH}
 *
 * @return the Bluetooth name, or null if there was a problem.
 */
    public String getName() {
    if (sService == null) {
        Log.e(TAG, "BT not enabled. Cannot get Remote Device name");
        return null;
    }
    try {
        return sService.getRemoteName(this);
    } catch (RemoteException e) {Log.e(TAG, "", e);}
    return null;
}

It seems your deserialised BluetoothDevices are not properly initialised (not connected to the bluetooth service). What you can do is save only the MAC address (and the device name) in the preferences. You can then use

BluetoothDevice device = BluetoothAdapter.getDefaultAdapter().getRemoteDevice(macAddress);

to get a properly initialised device.

Be aware that you may run into problems because iOS and Android devices may change their MAC address after some time.