diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/LockHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/LockHandler.java index 506a6883..bf59275e 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/LockHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/LockHandler.java @@ -44,6 +44,11 @@ public class LockHandler implements DBHandler { } + @Override + public DaoMaster getDaoMaster() { + return daoMaster; + } + private boolean isValid() { return daoMaster != null; } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java index c3526d7f..a5def126 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/activities/DebugActivity.java @@ -27,12 +27,19 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; +import java.util.ArrayList; import java.util.GregorianCalendar; +import java.util.List; +import java.util.Set; import nodomain.freeyourgadget.gadgetbridge.GBApplication; +import nodomain.freeyourgadget.gadgetbridge.GBException; import nodomain.freeyourgadget.gadgetbridge.R; +import nodomain.freeyourgadget.gadgetbridge.adapter.GBDeviceAdapter; +import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.DeviceService; @@ -40,6 +47,7 @@ import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationType; +import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.Prefs; @@ -292,6 +300,55 @@ public class DebugActivity extends GBActivity { .show(); } + private void insertActivityDbContents() { + DBHelper helper = new DBHelper(getBaseContext()); + ActivityDatabaseHandler oldHandler = helper.getOldActivityDatabaseHandler(); + if (oldHandler == null) { + return; + } + GBDevice device = getDeviceForMergingActivityDatabaseInto(); + if (device == null) { + return; + } + try (DBHandler targetHandler = GBApplication.acquireDB()) { + helper.importOldDb(oldHandler, device, targetHandler.getDaoMaster(), targetHandler); + } catch (GBException e) { + e.printStackTrace(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + private GBDevice getDeviceForMergingActivityDatabaseInto() { + final List availableDevices = new ArrayList<>(DeviceHelper.getInstance().getAvailableDevices(getBaseContext())); + if (availableDevices.isEmpty()) { + return null; + } else if (availableDevices.size() == 1) { + return availableDevices.get(0); + } + GBDeviceAdapter adapter = new GBDeviceAdapter(getBaseContext(), availableDevices); + + final GBDevice[] result = new GBDevice[1]; + new AlertDialog.Builder(this) + .setCancelable(true) + .setTitle("Delete Activity Data?") + .setSingleChoiceItems(adapter, -1, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + GBDevice device = availableDevices.get(which); + result[0] = device; + } + }) + .setMessage("Select the device to merge the previous activity database data into.") + .setNegativeButton("Cancel", new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + } + }) + .show(); + return result[0]; + } + private void deleteActivityDatabase() { new AlertDialog.Builder(this) .setCancelable(true) diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/ActivityDatabaseHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/ActivityDatabaseHandler.java index 0578f261..68abfcc6 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/ActivityDatabaseHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/ActivityDatabaseHandler.java @@ -292,6 +292,19 @@ public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandl return -1; } + public boolean hasContent() { + try { + try (SQLiteDatabase db = this.getReadableDatabase()) { + try (Cursor cursor = db.query(TABLE_GBACTIVITYSAMPLES, new String[]{KEY_TIMESTAMP}, null, null, null, KEY_TIMESTAMP + " DESC", "1")) { + return cursor.moveToFirst(); + } + } + } catch (Exception ex) { + // can't expect anything + return false; + } + } + @Override public DaoSession getDaoSession() { throw new UnsupportedOperationException(); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBHandler.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBHandler.java index 2de13236..9a9923cc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBHandler.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBHandler.java @@ -32,5 +32,6 @@ public interface DBHandler extends AutoCloseable { SQLiteDatabase getDatabase(); + DaoMaster getDaoMaster(); DaoSession getDaoSession(); } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBHelper.java index fc5bbea4..c6666e5b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBHelper.java @@ -4,10 +4,12 @@ import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteOpenHelper; +import android.support.annotation.Nullable; import java.io.File; import java.io.IOException; import java.text.SimpleDateFormat; +import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; @@ -15,7 +17,10 @@ import java.util.Locale; import de.greenrobot.dao.query.Query; 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; @@ -26,11 +31,19 @@ import nodomain.freeyourgadget.gadgetbridge.entities.UserAttributes; import nodomain.freeyourgadget.gadgetbridge.entities.UserDao; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; +import nodomain.freeyourgadget.gadgetbridge.model.HeartRateSample; import nodomain.freeyourgadget.gadgetbridge.model.ValidByDate; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; +import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_CUSTOM_SHORT; +import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_INTENSITY; +import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS; +import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP; +import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TYPE; +import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES; + /** * Provides utiliy access to some common entities, so you won't need to use * their DAO classes. @@ -302,4 +315,76 @@ public class DBHelper { } return false; } + + /** + * Returns the old activity database handler if there is any content in that + * db, or null otherwise. + * @return the old activity db handler or null + */ + @Nullable + public ActivityDatabaseHandler getOldActivityDatabaseHandler() { + ActivityDatabaseHandler handler = new ActivityDatabaseHandler(context); + if (handler.hasContent()) { + return handler; + } + return null; + } + + public void importOldDb(ActivityDatabaseHandler oldDb, GBDevice targetDevice, DaoMaster daoMaster, DBHandler targetDBHandler) { + DaoSession tempSession = daoMaster.newSession(); + try { + importActivityDatabase(oldDb, targetDevice, tempSession, targetDBHandler); + } finally { + tempSession.clear(); + } + } + + private boolean isEmpty(DaoSession session) { + long totalSamplesCount = session.getMiBandActivitySampleDao().count(); + totalSamplesCount += session.getPebbleActivitySampleDao().count(); + return totalSamplesCount == 0; + } + + private void importActivityDatabase(ActivityDatabaseHandler oldDbHandler, GBDevice targetDevice, DaoSession session, DBHandler targetDBHandler) { + try (SQLiteDatabase oldDB = oldDbHandler.getReadableDatabase()) { + User user = DBHelper.getUser(session); + for (DeviceCoordinator coordinator : DeviceHelper.getInstance().getAllCoordinators()) { + AbstractSampleProvider sampleProvider = (AbstractSampleProvider) coordinator.getSampleProvider(targetDBHandler); + importActivitySamples(oldDB, targetDevice, session, sampleProvider, user); + } + } + } + + private void importActivitySamples(SQLiteDatabase fromDb, GBDevice targetDevice, DaoSession targetSession, AbstractSampleProvider sampleProvider, User user) { + String order = "timestamp"; + final String where = "provider=" + sampleProvider.getID(); + + try (Cursor cursor = fromDb.query(TABLE_GBACTIVITYSAMPLES, null, where, null, null, null, order)) { + int colTimeStamp = cursor.getColumnIndex(KEY_TIMESTAMP); + int colIntensity = cursor.getColumnIndex(KEY_INTENSITY); + int colSteps = cursor.getColumnIndex(KEY_STEPS); + int colType = cursor.getColumnIndex(KEY_TYPE); + int colCustomShort = cursor.getColumnIndex(KEY_CUSTOM_SHORT); + Long deviceId = DBHelper.getDevice(targetDevice, targetSession).getId(); + Long userId = user.getId(); + List newSamples = new ArrayList<>(cursor.getCount()); + while (cursor.moveToNext()) { + T newSample = sampleProvider.createActivitySample(); + newSample.setUserId(userId); + newSample.setDeviceId(deviceId); + newSample.setTimestamp(cursor.getInt(colTimeStamp)); + newSample.setRawKind(cursor.getInt(colType)); + newSample.setProvider(sampleProvider); + newSample.setRawIntensity(cursor.getInt(colIntensity)); + newSample.setSteps(cursor.getInt(colSteps)); + + int hrValue = cursor.getInt(colCustomShort); + if (newSample instanceof HeartRateSample) { + ((HeartRateSample)newSample).setHeartRate(hrValue); + } + newSamples.add(newSample); + } + sampleProvider.getSampleDao().insertInTx(newSamples, true); + } + } } diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBOpenHelper.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBOpenHelper.java index 2ea94f23..5861f00b 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBOpenHelper.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/database/DBOpenHelper.java @@ -3,27 +3,24 @@ package nodomain.freeyourgadget.gadgetbridge.database; import android.content.Context; import android.database.Cursor; import android.database.sqlite.SQLiteDatabase; +import android.support.annotation.Nullable; import java.util.ArrayList; import java.util.List; -import nodomain.freeyourgadget.gadgetbridge.LockHandler; import nodomain.freeyourgadget.gadgetbridge.database.schema.SchemaMigration; import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; -import nodomain.freeyourgadget.gadgetbridge.devices.SampleProvider; import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample; import nodomain.freeyourgadget.gadgetbridge.entities.DaoMaster; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.User; -import nodomain.freeyourgadget.gadgetbridge.impl.GBActivitySample; -import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample; +import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.model.HeartRateSample; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_CUSTOM_SHORT; import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_INTENSITY; -import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_PROVIDER; import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_STEPS; import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP; import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TYPE; @@ -39,69 +36,6 @@ public class DBOpenHelper extends DaoMaster.OpenHelper { this.context = context; } - public boolean importOldDbIfNecessary(DaoMaster daoMaster, DBHandler targetDBHandler) { - DaoSession tempSession = daoMaster.newSession(); - try { - if (isEmpty(tempSession)) { - importActivityDatabaseInto(tempSession, targetDBHandler); - return true; - } - } finally { - tempSession.clear(); - } - return false; - } - - private boolean isEmpty(DaoSession session) { - long totalSamplesCount = session.getMiBandActivitySampleDao().count(); - totalSamplesCount += session.getPebbleActivitySampleDao().count(); - return totalSamplesCount == 0; - } - - private void importActivityDatabaseInto(DaoSession session, DBHandler targetDBHandler) { - ActivityDatabaseHandler handler = new ActivityDatabaseHandler(getContext()); - - try (SQLiteDatabase db = handler.getReadableDatabase()) { - User user = DBHelper.getUser(session); - for (DeviceCoordinator coordinator : DeviceHelper.getInstance().getAllCoordinators()) { - AbstractSampleProvider sampleProvider = (AbstractSampleProvider) coordinator.getSampleProvider(targetDBHandler); - importActivitySamples(db, session, sampleProvider, user); - } - } - } - - private void importActivitySamples(SQLiteDatabase fromDb, DaoSession targetSession, AbstractSampleProvider sampleProvider, User user) { - String order = "timestamp"; - final String where = "provider=" + sampleProvider.getID(); - - try (Cursor cursor = fromDb.query(TABLE_GBACTIVITYSAMPLES, null, where, null, null, null, order)) { - int colTimeStamp = cursor.getColumnIndex(KEY_TIMESTAMP); - int colIntensity = cursor.getColumnIndex(KEY_INTENSITY); - int colSteps = cursor.getColumnIndex(KEY_STEPS); - int colType = cursor.getColumnIndex(KEY_TYPE); - int colCustomShort = cursor.getColumnIndex(KEY_CUSTOM_SHORT); - Long userId = user.getId(); - List newSamples = new ArrayList<>(cursor.getCount()); - while (cursor.moveToNext()) { - T newSample = sampleProvider.createActivitySample(); - newSample.setUserId(userId); - newSample.setDeviceId(deviceId); - newSample.setTimestamp(cursor.getInt(colTimeStamp)); - newSample.setRawKind(cursor.getInt(colType)); - newSample.setProvider(sampleProvider); - newSample.setRawIntensity(cursor.getInt(colIntensity)); - newSample.setSteps(cursor.getInt(colSteps)); - - int hrValue = cursor.getInt(colCustomShort); - if (newSample instanceof HeartRateSample) { - ((HeartRateSample)newSample).setHeartRate(hrValue); - } - newSamples.add(newSample); - } - sampleProvider.getSampleDao().insertInTx(newSamples, true); - } - } - @Override public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) { new SchemaMigration(updaterClassNamePrefix).onUpgrade(db, oldVersion, newVersion); diff --git a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/entities/AbstractActivitySample.java b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/entities/AbstractActivitySample.java index a568edc7..57d607bc 100644 --- a/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/entities/AbstractActivitySample.java +++ b/app/src/main/java/nodomain/freeyourgadget/gadgetbridge/entities/AbstractActivitySample.java @@ -38,7 +38,7 @@ public abstract class AbstractActivitySample implements ActivitySample { public abstract Long getUserId(); - public abstract void setDeviceId(Long userId); + public abstract void setDeviceId(Long deviceId); public abstract Long getDeviceId();