Add class DeviceManager that provides access to the list of managed devices

Basically moved code out of ControlCenter to a separate class. Also provides
change events when the device list has changed, or changes to the device
state have occurred.
This commit is contained in:
cpfeiffer 2016-06-18 23:35:34 +02:00
parent 2890fd6737
commit 233a6155cc
8 changed files with 169 additions and 72 deletions

View File

@ -31,6 +31,7 @@ import java.util.concurrent.locks.ReentrantLock;
import nodomain.freeyourgadget.gadgetbridge.database.DBConstants;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBOpenHelper;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoMaster;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDeviceService;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
@ -75,6 +76,7 @@ public class GBApplication extends Application {
return dir.getAbsolutePath();
}
};
private static DeviceManager deviceManager;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
@ -120,6 +122,8 @@ public class GBApplication extends Application {
setupDatabase(this);
deviceManager = new DeviceManager(this);
deviceService = createDeviceService();
GB.environment = GBEnvironment.createDeviceEnvironment();
// mActivityDatabaseHandler = new ActivityDatabaseHandler(context);
@ -153,7 +157,7 @@ public class GBApplication extends Application {
static void setupDatabase(Context context) {
// DaoMaster.DevOpenHelper helper = new DaoMaster.DevOpenHelper(this, "test-db", null);
DBOpenHelper helper = new DBOpenHelper(context, "test-db", null);
DBOpenHelper helper = new DBOpenHelper(context, "test-db2", null);
SQLiteDatabase db = helper.getWritableDatabase();
DaoMaster daoMaster = new DaoMaster(db);
if (lockHandler == null) {
@ -402,4 +406,8 @@ public class GBApplication extends Application {
public static GBPrefs getGBPrefs() {
return gbPrefs;
}
public static DeviceManager getDeviceManager() {
return deviceManager;
}
}

View File

@ -33,7 +33,6 @@ import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import de.cketti.library.changelog.ChangeLog;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
@ -41,6 +40,7 @@ import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.charts.ChartsActivity;
import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapter;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -50,18 +50,17 @@ public class ControlCenter extends GBActivity {
private static final Logger LOG = LoggerFactory.getLogger(ControlCenter.class);
public static final String ACTION_REFRESH_DEVICELIST
= "nodomain.freeyourgadget.gadgetbridge.controlcenter.action.set_version";
private TextView hintTextView;
private FloatingActionButton fab;
private ImageView background;
private SwipeRefreshLayout swipeLayout;
private GBDeviceAdapter mGBDeviceAdapter;
private GBDevice selectedDevice = null;
private final List<GBDevice> deviceList = new ArrayList<>();
private DeviceManager deviceManager;
/**
* Temporary field for the context menu
*/
private GBDevice selectedDevice;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
@ -71,46 +70,16 @@ public class ControlCenter extends GBActivity {
case GBApplication.ACTION_QUIT:
finish();
break;
case ACTION_REFRESH_DEVICELIST:
case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
case DeviceManager.ACTION_DEVICES_CHANGED:
refreshPairedDevices();
break;
case GBDevice.ACTION_DEVICE_CHANGED:
GBDevice dev = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
if (dev.getAddress() != null) {
int index = deviceList.indexOf(dev); // search by address
if (index >= 0) {
deviceList.set(index, dev);
} else {
deviceList.add(dev);
}
}
updateSelectedDevice(dev);
refreshPairedDevices();
refreshBusyState(dev);
GBDevice selectedDevice = deviceManager.getSelectedDevice();
refreshBusyState(selectedDevice);
enableSwipeRefresh(selectedDevice);
break;
}
}
};
private void updateSelectedDevice(GBDevice dev) {
if (selectedDevice == null) {
selectedDevice = dev;
} else {
if (!selectedDevice.equals(dev)) {
if (selectedDevice.isConnected() && dev.isConnected()) {
LOG.warn("multiple connected devices -- this is currently not really supported");
selectedDevice = dev; // use the last one that changed
}
if (!selectedDevice.isConnected()) {
selectedDevice = dev; // use the last one that changed
}
}
}
}
private void refreshBusyState(GBDevice dev) {
if (dev.isBusy()) {
swipeLayout.setRefreshing(true);
@ -120,7 +89,6 @@ public class ControlCenter extends GBActivity {
swipeLayout.setRefreshing(false);
}
}
mGBDeviceAdapter.notifyDataSetChanged();
}
@Override
@ -128,6 +96,8 @@ public class ControlCenter extends GBActivity {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_controlcenter);
deviceManager = GBApplication.getDeviceManager();
hintTextView = (TextView) findViewById(R.id.hintTextView);
ListView deviceListView = (ListView) findViewById(R.id.deviceListView);
fab = (FloatingActionButton) findViewById(R.id.fab);
@ -140,12 +110,13 @@ public class ControlCenter extends GBActivity {
}
});
final List<GBDevice> deviceList = deviceManager.getDevices();
mGBDeviceAdapter = new GBDeviceAdapter(this, deviceList);
deviceListView.setAdapter(this.mGBDeviceAdapter);
deviceListView.setOnItemClickListener(new AdapterView.OnItemClickListener() {
@Override
public void onItemClick(AdapterView parent, View v, int position, long id) {
GBDevice gbDevice = deviceList.get(position);
GBDevice gbDevice = mGBDeviceAdapter.getItem(position);
if (gbDevice.isInitialized()) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice);
Class<? extends Activity> primaryActivity = coordinator.getPrimaryActivity();
@ -155,7 +126,7 @@ public class ControlCenter extends GBActivity {
startActivity(startIntent);
}
} else {
GBApplication.deviceService().connect(deviceList.get(position));
GBApplication.deviceService().connect(gbDevice);
}
}
});
@ -172,13 +143,9 @@ public class ControlCenter extends GBActivity {
IntentFilter filterLocal = new IntentFilter();
filterLocal.addAction(GBApplication.ACTION_QUIT);
filterLocal.addAction(ACTION_REFRESH_DEVICELIST);
filterLocal.addAction(GBDevice.ACTION_DEVICE_CHANGED);
filterLocal.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
filterLocal.addAction(DeviceManager.ACTION_DEVICES_CHANGED);
LocalBroadcastManager.getInstance(this).registerReceiver(mReceiver, filterLocal);
registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
refreshPairedDevices();
/*
* Ask for permission to intercept notifications on first run.
@ -200,7 +167,7 @@ public class ControlCenter extends GBActivity {
GBApplication.deviceService().start();
enableSwipeRefresh(selectedDevice);
enableSwipeRefresh(deviceManager.getSelectedDevice());
if (GB.isBluetoothEnabled() && deviceList.isEmpty() && Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
startActivity(new Intent(this, DiscoveryActivity.class));
} else {
@ -212,7 +179,7 @@ public class ControlCenter extends GBActivity {
public void onCreateContextMenu(ContextMenu menu, View v, ContextMenu.ContextMenuInfo menuInfo) {
super.onCreateContextMenu(menu, v, menuInfo);
AdapterView.AdapterContextMenuInfo acmi = (AdapterView.AdapterContextMenuInfo) menuInfo;
selectedDevice = deviceList.get(acmi.position);
selectedDevice = mGBDeviceAdapter.getItem(acmi.position);
if (selectedDevice != null && selectedDevice.isBusy()) {
// no context menu when device is busy
return;
@ -254,6 +221,7 @@ public class ControlCenter extends GBActivity {
}
private void fetchActivityData() {
GBDevice selectedDevice = deviceManager.getSelectedDevice();
if (selectedDevice == null) {
return;
}
@ -364,17 +332,12 @@ public class ControlCenter extends GBActivity {
}
private void refreshPairedDevices() {
Set<GBDevice> availableDevices = DeviceHelper.getInstance().getAvailableDevices(this);
deviceList.retainAll(availableDevices);
for (GBDevice availableDevice : availableDevices) {
if (!deviceList.contains(availableDevice)) {
deviceList.add(availableDevice);
}
}
boolean connected = false;
List<GBDevice> deviceList = deviceManager.getDevices();
GBDevice connectedDevice = null;
for (GBDevice device : deviceList) {
if (device.isConnected() || device.isConnecting()) {
connected = true;
connectedDevice = device;
break;
}
}
@ -385,8 +348,8 @@ public class ControlCenter extends GBActivity {
background.setVisibility(View.INVISIBLE);
}
if (connected) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(selectedDevice);
if (connectedDevice != null) {
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(connectedDevice);
hintTextView.setText(coordinator.getTapString());
} else if (!deviceList.isEmpty()) {
hintTextView.setText(R.string.tap_a_device_to_connect);

View File

@ -26,6 +26,7 @@ import java.util.Locale;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandPreferencesActivity;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -78,7 +79,7 @@ public class SettingsActivity extends AbstractSettingsActivity {
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newVal) {
Intent refreshIntent = new Intent(ControlCenter.ACTION_REFRESH_DEVICELIST);
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(refreshIntent);
preference.setSummary(newVal.toString());
return true;
@ -90,7 +91,7 @@ public class SettingsActivity extends AbstractSettingsActivity {
pref.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newVal) {
Intent refreshIntent = new Intent(ControlCenter.ACTION_REFRESH_DEVICELIST);
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(refreshIntent);
preference.setSummary(newVal.toString());
return true;

View File

@ -20,7 +20,6 @@ import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoMaster;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.DeviceAttributes;

View File

@ -0,0 +1,128 @@
package nodomain.freeyourgadget.gadgetbridge.devices;
import android.bluetooth.BluetoothDevice;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.support.v4.content.LocalBroadcastManager;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
/**
* Provides access to the list of devices managed by Gadgetbridge.
* Changes to the devices (e.g. connection state) or the list of devices
* are broadcasted via #ACTION_DEVICE_CHANGED
*/
public class DeviceManager {
private static final Logger LOG = LoggerFactory.getLogger(DeviceManager.class);
/**
* Intent action to notify that the list of devices has changed.
*/
public static final String ACTION_DEVICES_CHANGED
= "nodomain.freeyourgadget.gadgetbridge.devices.devicemanager.action.devices_changed";
/**
* Intent action to notify this class that the list of devices shall be refreshed.
*/
public static final String ACTION_REFRESH_DEVICELIST
= "nodomain.freeyourgadget.gadgetbridge.devices.devicemanager.action.set_version";
private final Context context;
/**
* This list is final, it will never be recreated. Only its contents change.
* This allows direct access to the list from ListAdapters.
*/
private final List<GBDevice> deviceList = new ArrayList<>();
private GBDevice selectedDevice = null;
private final BroadcastReceiver mReceiver = new BroadcastReceiver() {
@Override
public void onReceive(Context context, Intent intent) {
String action = intent.getAction();
switch (action) {
case ACTION_REFRESH_DEVICELIST:
case BluetoothDevice.ACTION_BOND_STATE_CHANGED:
refreshPairedDevices();
break;
case GBDevice.ACTION_DEVICE_CHANGED:
GBDevice dev = intent.getParcelableExtra(GBDevice.EXTRA_DEVICE);
if (dev.getAddress() != null) {
int index = deviceList.indexOf(dev); // search by address
if (index >= 0) {
deviceList.set(index, dev);
} else {
deviceList.add(dev);
}
}
updateSelectedDevice(dev);
refreshPairedDevices();
break;
}
}
};
public DeviceManager(Context context) {
this.context = context;
IntentFilter filterLocal = new IntentFilter();
filterLocal.addAction(DeviceManager.ACTION_REFRESH_DEVICELIST);
filterLocal.addAction(GBDevice.ACTION_DEVICE_CHANGED);
filterLocal.addAction(BluetoothDevice.ACTION_BOND_STATE_CHANGED);
LocalBroadcastManager.getInstance(context).registerReceiver(mReceiver, filterLocal);
context.registerReceiver(mReceiver, new IntentFilter(BluetoothDevice.ACTION_BOND_STATE_CHANGED));
refreshPairedDevices();
}
private void updateSelectedDevice(GBDevice dev) {
if (selectedDevice == null) {
selectedDevice = dev;
} else {
if (!selectedDevice.equals(dev)) {
if (selectedDevice.isConnected() && dev.isConnected()) {
LOG.warn("multiple connected devices -- this is currently not really supported");
selectedDevice = dev; // use the last one that changed
}
if (!selectedDevice.isConnected()) {
selectedDevice = dev; // use the last one that changed
}
}
}
}
private void refreshPairedDevices() {
Set<GBDevice> availableDevices = DeviceHelper.getInstance().getAvailableDevices(context);
deviceList.retainAll(availableDevices);
for (GBDevice availableDevice : availableDevices) {
if (!deviceList.contains(availableDevice)) {
deviceList.add(availableDevice);
}
}
notifyDevicesChanged();
}
/**
* The returned list is final, it will never be recreated. Only its contents change.
* This allows direct access to the list from ListAdapters.
*/
public List<GBDevice> getDevices() {
return Collections.unmodifiableList(deviceList);
}
public GBDevice getSelectedDevice() {
return selectedDevice;
}
private void notifyDevicesChanged() {
LocalBroadcastManager.getInstance(context).sendBroadcast(new Intent(ACTION_DEVICES_CHANGED));
}
}

View File

@ -8,7 +8,7 @@ import android.support.v4.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.AbstractSettingsActivity;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_GENERIC;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_INCOMING_CALL;
@ -17,14 +17,11 @@ import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.OR
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.ORIGIN_SMS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_ADDRESS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_DEVICE_TIME_OFFSET_HOURS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_DONT_ACK_TRANSFER;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_FITNESS_GOAL;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_RESERVE_ALARM_FOR_CALENDAR;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_USE_HR_FOR_SLEEP_DETECTION;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_MIBAND_WEARSIDE;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.PREF_USER_ALIAS;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_COUNT;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.VIBRATION_PROFILE;
import static nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst.getNotificationPrefKey;
public class MiBandPreferencesActivity extends AbstractSettingsActivity {
@ -38,7 +35,7 @@ public class MiBandPreferencesActivity extends AbstractSettingsActivity {
developmentMiaddr.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() {
@Override
public boolean onPreferenceChange(Preference preference, Object newVal) {
Intent refreshIntent = new Intent(ControlCenter.ACTION_REFRESH_DEVICELIST);
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(refreshIntent);
preference.setSummary(newVal.toString());
return true;

View File

@ -7,7 +7,7 @@ import android.content.Intent;
import android.support.v4.content.LocalBroadcastManager;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.util.Prefs;
public class BluetoothStateChangeReceiver extends BroadcastReceiver {
@ -18,7 +18,7 @@ public class BluetoothStateChangeReceiver extends BroadcastReceiver {
if (action.equals(BluetoothAdapter.ACTION_STATE_CHANGED)) {
if (intent.getIntExtra(BluetoothAdapter.EXTRA_STATE, -1) == BluetoothAdapter.STATE_ON) {
Intent refreshIntent = new Intent(ControlCenter.ACTION_REFRESH_DEVICELIST);
Intent refreshIntent = new Intent(DeviceManager.ACTION_REFRESH_DEVICELIST);
LocalBroadcastManager.getInstance(context).sendBroadcast(refreshIntent);
Prefs prefs = GBApplication.getPrefs();

View File

@ -18,6 +18,7 @@ import java.util.Set;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceManager;
import nodomain.freeyourgadget.gadgetbridge.devices.UnknownDeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandConst;
import nodomain.freeyourgadget.gadgetbridge.devices.miband.MiBandCoordinator;