mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2025-01-24 00:27:33 +01:00
WIP: more db work
This commit is contained in:
parent
ae548d0806
commit
61957d6cb0
@ -60,7 +60,7 @@ public class GBApplication extends Application {
|
||||
private static LimitedQueue mIDSenderLookup = new LimitedQueue(16);
|
||||
private static Prefs prefs;
|
||||
private static GBPrefs gbPrefs;
|
||||
private static DBHandler lockHandler;
|
||||
private static LockHandler lockHandler;
|
||||
/**
|
||||
* Note: is null on Lollipop and Kitkat
|
||||
*/
|
||||
@ -156,7 +156,10 @@ public class GBApplication extends Application {
|
||||
DBOpenHelper helper = new DBOpenHelper(context, "test-db", null);
|
||||
SQLiteDatabase db = helper.getWritableDatabase();
|
||||
DaoMaster daoMaster = new DaoMaster(db);
|
||||
lockHandler = new LockHandler(daoMaster, helper);
|
||||
if (lockHandler == null) {
|
||||
lockHandler = new LockHandler();
|
||||
}
|
||||
lockHandler.init(daoMaster, helper);
|
||||
}
|
||||
|
||||
public static Context getContext() {
|
||||
@ -179,6 +182,9 @@ public class GBApplication extends Application {
|
||||
* If acquiring was successful, callers must call #releaseDB when they
|
||||
* are done (from the same thread that acquired the lock!
|
||||
*
|
||||
* Callers must not hold a reference to the returned instance because it
|
||||
* will be invalidated at some point.
|
||||
*
|
||||
* @return the DBHandler
|
||||
* @throws GBException
|
||||
* @see #releaseDB()
|
||||
|
@ -9,23 +9,48 @@ import nodomain.freeyourgadget.gadgetbridge.entities.DaoMaster;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
|
||||
/**
|
||||
* A dummy DBHandler that does nothing more than implementing the release() method.
|
||||
* It is solely used for locking concurrent access to the database session.
|
||||
* Provides lowlevel access to the database.
|
||||
*/
|
||||
public class LockHandler implements DBHandler {
|
||||
|
||||
private final DaoMaster daoMaster;
|
||||
private DaoSession session;
|
||||
private final SQLiteOpenHelper helper;
|
||||
private DaoMaster daoMaster = null;
|
||||
private DaoSession session = null;
|
||||
private SQLiteOpenHelper helper = null;
|
||||
|
||||
public LockHandler(DaoMaster daoMaster, DBOpenHelper helper) {
|
||||
public LockHandler() {
|
||||
}
|
||||
|
||||
public void init(DaoMaster daoMaster, DBOpenHelper helper) {
|
||||
if (isValid()) {
|
||||
throw new IllegalStateException("DB must be closed before initializing it again");
|
||||
}
|
||||
if (daoMaster == null) {
|
||||
throw new IllegalArgumentException("daoMaster must not be null");
|
||||
}
|
||||
if (helper == null) {
|
||||
throw new IllegalArgumentException("helper must not be null");
|
||||
}
|
||||
this.daoMaster = daoMaster;
|
||||
this.helper = helper;
|
||||
session = daoMaster.newSession();
|
||||
if (session == null) {
|
||||
throw new RuntimeException("Unable to create database session");
|
||||
}
|
||||
}
|
||||
|
||||
private boolean isValid() {
|
||||
return daoMaster != null;
|
||||
}
|
||||
|
||||
private void ensureValid() {
|
||||
if (!isValid()) {
|
||||
throw new IllegalStateException("LockHandler is not in a valid state");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
ensureValid();
|
||||
GBApplication.releaseDB();
|
||||
}
|
||||
|
||||
@ -34,7 +59,7 @@ public class LockHandler implements DBHandler {
|
||||
if (session != null) {
|
||||
throw new IllegalStateException("session must be null");
|
||||
}
|
||||
// this will create completely new db instances. This handler will be dead
|
||||
// this will create completely new db instances and in turn update this handler through #init()
|
||||
GBApplication.setupDatabase(GBApplication.getContext());
|
||||
}
|
||||
|
||||
@ -46,20 +71,25 @@ public class LockHandler implements DBHandler {
|
||||
session.clear();
|
||||
session.getDatabase().close();
|
||||
session = null;
|
||||
helper = null;
|
||||
daoMaster = null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLiteOpenHelper getHelper() {
|
||||
ensureValid();
|
||||
return helper;
|
||||
}
|
||||
|
||||
@Override
|
||||
public DaoSession getDaoSession() {
|
||||
ensureValid();
|
||||
return session;
|
||||
}
|
||||
|
||||
@Override
|
||||
public SQLiteDatabase getDatabase() {
|
||||
ensureValid();
|
||||
return daoMaster.getDatabase();
|
||||
}
|
||||
}
|
||||
|
@ -4,20 +4,29 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoMaster;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
|
||||
/**
|
||||
* Provides lowlevel access to the database.
|
||||
*/
|
||||
public interface DBHandler extends AutoCloseable {
|
||||
/**
|
||||
* Closes the database.
|
||||
*/
|
||||
void closeDb();
|
||||
|
||||
/**
|
||||
* Opens the database. Note that this is only possible after an explicit
|
||||
* #closeDb(). Initially the db is implicitly open.
|
||||
*/
|
||||
void openDb();
|
||||
|
||||
SQLiteOpenHelper getHelper();
|
||||
|
||||
/**
|
||||
* Releases the DB handler. No access may be performed after calling this method.
|
||||
* Same as calling {@link GBApplication#releaseDB()}
|
||||
* Releases the DB handler. No DB access will be possible before
|
||||
* #openDb() will be called.
|
||||
*/
|
||||
void close() throws Exception;
|
||||
|
||||
|
@ -31,6 +31,13 @@ import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
||||
/**
|
||||
* Provides utiliy access to some common entities, so you won't need to use
|
||||
* their DAO classes.
|
||||
*
|
||||
* Maybe this code should actually be in the DAO classes themselves, but then
|
||||
* these should be under revision control instead of 100% generated at build time.
|
||||
*/
|
||||
public class DBHelper {
|
||||
private final Context context;
|
||||
|
||||
@ -134,9 +141,10 @@ public class DBHelper {
|
||||
}
|
||||
|
||||
public static User getUser(DaoSession session) {
|
||||
UserDao userDao = session.getUserDao();
|
||||
List<User> users = userDao.loadAll();
|
||||
ActivityUser prefsUser = new ActivityUser();
|
||||
UserDao userDao = session.getUserDao();
|
||||
Query<User> query = userDao.queryBuilder().where(UserDao.Properties.Name.eq(prefsUser.getName())).build();
|
||||
List<User> users = query.list();
|
||||
User user;
|
||||
if (users.isEmpty()) {
|
||||
user = createUser(prefsUser, session);
|
||||
@ -155,8 +163,6 @@ public class DBHelper {
|
||||
user.setGender(prefsUser.getGender());
|
||||
session.getUserDao().insert(user);
|
||||
|
||||
ensureUserAttributes(user, prefsUser, session);
|
||||
|
||||
return user;
|
||||
}
|
||||
|
||||
@ -187,6 +193,7 @@ public class DBHelper {
|
||||
return false;
|
||||
}
|
||||
|
||||
// TODO: move this into db queries?
|
||||
private static boolean isValidNow(ValidByDate element) {
|
||||
Calendar cal = DateTimeUtils.getCalendarUTC();
|
||||
Date nowUTC = cal.getTime();
|
||||
@ -221,15 +228,39 @@ public class DBHelper {
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isEqual(DeviceAttributes attr, GBDevice gbDevice) {
|
||||
if (!isEqual(attr.getFirmwareVersion1(), gbDevice.getFirmwareVersion())) {
|
||||
return false;
|
||||
}
|
||||
if (!isEqual(attr.getFirmwareVersion2(), gbDevice.getFirmwareVersion2())) {
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
private static boolean isEqual(String s1, String s2) {
|
||||
if (s1 == s2) {
|
||||
return true;
|
||||
}
|
||||
if (s1 != null) {
|
||||
return s1.equals(s2);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
public static Device getDevice(GBDevice gbDevice, DaoSession session) {
|
||||
DeviceDao deviceDao = session.getDeviceDao();
|
||||
Query<Device> query = deviceDao.queryBuilder().where(DeviceDao.Properties.Identifier.eq(gbDevice.getAddress())).build();
|
||||
List<Device> devices = query.list();
|
||||
Device device;
|
||||
if (devices.isEmpty()) {
|
||||
Device device = createDevice(session, gbDevice);
|
||||
return device;
|
||||
device = createDevice(session, gbDevice);
|
||||
} else {
|
||||
device = devices.get(0);
|
||||
}
|
||||
return devices.get(0);
|
||||
ensureDeviceAttributes(device, gbDevice, session);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
private static Device createDevice(DaoSession session, GBDevice gbDevice) {
|
||||
@ -239,18 +270,36 @@ public class DBHelper {
|
||||
DeviceCoordinator coordinator = DeviceHelper.getInstance().getCoordinator(gbDevice);
|
||||
device.setManufacturer(coordinator.getManufacturer());
|
||||
session.getDeviceDao().insert(device);
|
||||
List<DeviceAttributes> deviceAttributes = device.getDeviceAttributesList();
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
private static void ensureDeviceAttributes(Device device, GBDevice gbDevice, DaoSession session) {
|
||||
List<DeviceAttributes> deviceAttributes = device.getDeviceAttributesList();
|
||||
if (hasUpToDateDeviceAttributes(deviceAttributes, gbDevice)) {
|
||||
return;
|
||||
}
|
||||
DeviceAttributes attributes = new DeviceAttributes();
|
||||
|
||||
attributes.setDeviceId(device.getId());
|
||||
attributes.setValidFromUTC(DateTimeUtils.todayUTC());
|
||||
attributes.setFirmwareVersion1(gbDevice.getFirmwareVersion());
|
||||
// TODO: firmware version2? generically or through DeviceCoordinator?
|
||||
attributes.setFirmwareVersion2(gbDevice.getFirmwareVersion2());
|
||||
DeviceAttributesDao attributesDao = session.getDeviceAttributesDao();
|
||||
attributesDao.insert(attributes);
|
||||
|
||||
deviceAttributes.add(attributes);
|
||||
}
|
||||
|
||||
return device;
|
||||
private static boolean hasUpToDateDeviceAttributes(List<DeviceAttributes> deviceAttributes, GBDevice gbDevice) {
|
||||
for (DeviceAttributes attr : deviceAttributes) {
|
||||
if (!isValidNow(attr)) {
|
||||
return false;
|
||||
}
|
||||
if (isEqual(attr, gbDevice)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@ -10,6 +10,11 @@ import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.MiBandActivitySampleDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
|
||||
|
||||
/**
|
||||
* Base class for all sample providers. A Sample provider is device specific and provides
|
||||
* access to the device specific samples. There are both read and write operations.
|
||||
* @param <T>
|
||||
*/
|
||||
public abstract class AbstractSampleProvider<T extends AbstractActivitySample> implements SampleProvider<T> {
|
||||
private static final WhereCondition[] NO_CONDITIONS = new WhereCondition[0];
|
||||
private final DaoSession mSession;
|
||||
@ -51,12 +56,12 @@ public abstract class AbstractSampleProvider<T extends AbstractActivitySample> i
|
||||
|
||||
@Override
|
||||
public void addGBActivitySample(T activitySample) {
|
||||
getSampleDao().insert(activitySample);
|
||||
getSampleDao().insertOrReplace(activitySample);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addGBActivitySamples(T[] activitySamples) {
|
||||
getSampleDao().insertInTx(activitySamples);
|
||||
getSampleDao().insertOrReplaceInTx(activitySamples);
|
||||
}
|
||||
|
||||
// @Override
|
||||
|
@ -46,8 +46,9 @@ public class GBDevice implements Parcelable {
|
||||
private final String mName;
|
||||
private final String mAddress;
|
||||
private final DeviceType mDeviceType;
|
||||
private String mFirmwareVersion = null;
|
||||
private String mHardwareVersion = null;
|
||||
private String mFirmwareVersion;
|
||||
private String mFirmwareVersion2;
|
||||
private String mHardwareVersion;
|
||||
private State mState = State.NOT_CONNECTED;
|
||||
private short mBatteryLevel = BATTERY_UNKNOWN;
|
||||
private short mBatteryThresholdPercent = BATTERY_THRESHOLD_PERCENT;
|
||||
@ -68,6 +69,7 @@ public class GBDevice implements Parcelable {
|
||||
mAddress = in.readString();
|
||||
mDeviceType = DeviceType.values()[in.readInt()];
|
||||
mFirmwareVersion = in.readString();
|
||||
mFirmwareVersion2 = in.readString();
|
||||
mHardwareVersion = in.readString();
|
||||
mState = State.values()[in.readInt()];
|
||||
mBatteryLevel = (short) in.readInt();
|
||||
@ -86,6 +88,7 @@ public class GBDevice implements Parcelable {
|
||||
dest.writeString(mAddress);
|
||||
dest.writeInt(mDeviceType.ordinal());
|
||||
dest.writeString(mFirmwareVersion);
|
||||
dest.writeString(mFirmwareVersion2);
|
||||
dest.writeString(mHardwareVersion);
|
||||
dest.writeInt(mState.ordinal());
|
||||
dest.writeInt(mBatteryLevel);
|
||||
@ -113,11 +116,18 @@ public class GBDevice implements Parcelable {
|
||||
public String getFirmwareVersion() {
|
||||
return mFirmwareVersion;
|
||||
}
|
||||
public String getFirmwareVersion2() {
|
||||
return mFirmwareVersion2;
|
||||
}
|
||||
|
||||
public void setFirmwareVersion(String firmwareVersion) {
|
||||
mFirmwareVersion = firmwareVersion;
|
||||
}
|
||||
|
||||
public void setFirmwareVersion2(String firmwareVersion2) {
|
||||
mFirmwareVersion2 = firmwareVersion2;
|
||||
}
|
||||
|
||||
public String getHardwareVersion() {
|
||||
return mHardwareVersion;
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user