1
0
mirror of https://codeberg.org/Freeyourgadget/Gadgetbridge synced 2024-11-28 12:56:49 +01:00

Drop support for legacy (pre 0.12.0) database

This commit is contained in:
Andreas Shimokawa 2017-02-23 22:44:44 +01:00
parent 49e1b55ad8
commit 08080b02bb
14 changed files with 6 additions and 632 deletions

View File

@ -27,7 +27,6 @@ import java.util.concurrent.TimeUnit;
import java.util.concurrent.locks.Lock; import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock; import java.util.concurrent.locks.ReentrantLock;
import nodomain.freeyourgadget.gadgetbridge.database.DBConstants;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.database.DBOpenHelper; import nodomain.freeyourgadget.gadgetbridge.database.DBOpenHelper;
@ -335,11 +334,7 @@ public class GBApplication extends Application {
if (lockHandler != null) { if (lockHandler != null) {
lockHandler.closeDb(); lockHandler.closeDb();
} }
DBHelper dbHelper = new DBHelper(context); boolean result = deleteOldActivityDatabase(context);
boolean result = true;
if (dbHelper.existsDB(DBConstants.DATABASE_NAME)) {
result = getContext().deleteDatabase(DBConstants.DATABASE_NAME);
}
result &= getContext().deleteDatabase(DATABASE_NAME); result &= getContext().deleteDatabase(DATABASE_NAME);
return result; return result;
} }
@ -352,8 +347,8 @@ public class GBApplication extends Application {
public static synchronized boolean deleteOldActivityDatabase(Context context) { public static synchronized boolean deleteOldActivityDatabase(Context context) {
DBHelper dbHelper = new DBHelper(context); DBHelper dbHelper = new DBHelper(context);
boolean result = true; boolean result = true;
if (dbHelper.existsDB(DBConstants.DATABASE_NAME)) { if (dbHelper.existsDB("ActivityDatabase")) {
result = getContext().deleteDatabase(DBConstants.DATABASE_NAME); result = getContext().deleteDatabase("ActivityDatabase");
} }
return result; return result;
} }

View File

@ -1,11 +1,9 @@
package nodomain.freeyourgadget.gadgetbridge.activities; package nodomain.freeyourgadget.gadgetbridge.activities;
import android.app.AlertDialog; import android.app.AlertDialog;
import android.app.ProgressDialog;
import android.content.DialogInterface; import android.content.DialogInterface;
import android.content.IntentFilter; import android.content.IntentFilter;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.os.AsyncTask;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.NavUtils; import android.support.v4.app.NavUtils;
import android.view.MenuItem; import android.view.MenuItem;
@ -18,16 +16,11 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.util.Collections;
import java.util.List;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R; 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.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB; import nodomain.freeyourgadget.gadgetbridge.util.GB;
@ -37,7 +30,6 @@ public class DbManagementActivity extends GBActivity {
private Button exportDBButton; private Button exportDBButton;
private Button importDBButton; private Button importDBButton;
private Button importOldActivityDataButton;
private Button deleteOldActivityDBButton; private Button deleteOldActivityDBButton;
private Button deleteDBButton; private Button deleteDBButton;
private TextView dbPath; private TextView dbPath;
@ -68,22 +60,7 @@ public class DbManagementActivity extends GBActivity {
} }
}); });
boolean hasOldDB = hasOldActivityDatabase(); int oldDBVisibility = hasOldActivityDatabase() ? View.VISIBLE : View.GONE;
int oldDBVisibility = hasOldDB ? View.VISIBLE : View.GONE;
View oldDBTitle = findViewById(R.id.mergeOldActivityDataTitle);
oldDBTitle.setVisibility(oldDBVisibility);
View oldDBText = findViewById(R.id.mergeOldActivityDataText);
oldDBText.setVisibility(oldDBVisibility);
importOldActivityDataButton = (Button) findViewById(R.id.mergeOldActivityData);
importOldActivityDataButton.setVisibility(oldDBVisibility);
importOldActivityDataButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mergeOldActivityDbContents();
}
});
deleteOldActivityDBButton = (Button) findViewById(R.id.deleteOldActivityDB); deleteOldActivityDBButton = (Button) findViewById(R.id.deleteOldActivityDB);
deleteOldActivityDBButton.setVisibility(oldDBVisibility); deleteOldActivityDBButton.setVisibility(oldDBVisibility);
@ -104,7 +81,7 @@ public class DbManagementActivity extends GBActivity {
} }
private boolean hasOldActivityDatabase() { private boolean hasOldActivityDatabase() {
return new DBHelper(this).getOldActivityDatabaseHandler() != null; return new DBHelper(this).existsDB("ActivityDatabase");
} }
private String getExternalPath() { private String getExternalPath() {
@ -156,67 +133,6 @@ public class DbManagementActivity extends GBActivity {
.show(); .show();
} }
private void mergeOldActivityDbContents() {
final DBHelper helper = new DBHelper(getBaseContext());
final ActivityDatabaseHandler oldHandler = helper.getOldActivityDatabaseHandler();
if (oldHandler == null) {
GB.toast(this, getString(R.string.dbmanagementactivity_no_old_activitydatabase_found), Toast.LENGTH_LONG, GB.ERROR);
return;
}
selectDeviceForMergingActivityDatabaseInto(new DeviceSelectionCallback() {
@Override
public void invoke(final GBDevice device) {
if (device == null) {
GB.toast(DbManagementActivity.this, getString(R.string.dbmanagementactivity_no_connected_device), Toast.LENGTH_LONG, GB.ERROR);
return;
}
try (DBHandler targetHandler = GBApplication.acquireDB()) {
final ProgressDialog progress = ProgressDialog.show(DbManagementActivity.this, getString(R.string.dbmanagementactivity_merging_activity_data_title), getString(R.string.dbmanagementactivity_please_wait_while_merging), true, false);
new AsyncTask<Object, ProgressDialog, Object>() {
@Override
protected Object doInBackground(Object[] params) {
helper.importOldDb(oldHandler, device, targetHandler);
if (!isFinishing() && !isDestroyed()) {
progress.dismiss();
}
return null;
}
}.execute((Object[]) null);
} catch (Exception ex) {
GB.toast(DbManagementActivity.this, getString(R.string.dbmanagementactivity_error_importing_old_activity_data), Toast.LENGTH_LONG, GB.ERROR, ex);
}
}
});
}
private void selectDeviceForMergingActivityDatabaseInto(final DeviceSelectionCallback callback) {
GBDevice connectedDevice = ((GBApplication)getApplication()).getDeviceManager().getSelectedDevice();
if (connectedDevice == null) {
callback.invoke(null);
return;
}
final List<GBDevice> availableDevices = Collections.singletonList(connectedDevice);
GBDeviceAdapter adapter = new GBDeviceAdapter(getBaseContext(), availableDevices);
new AlertDialog.Builder(this)
.setCancelable(true)
.setTitle(R.string.dbmanagementactivity_associate_old_data_with_device)
.setAdapter(adapter, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
GBDevice device = availableDevices.get(which);
callback.invoke(device);
}
})
.setNegativeButton(R.string.Cancel, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
// ignore, just return
}
})
.show();
}
private void deleteActivityDatabase() { private void deleteActivityDatabase() {
new AlertDialog.Builder(this) new AlertDialog.Builder(this)
.setCancelable(true) .setCancelable(true)
@ -271,8 +187,4 @@ public class DbManagementActivity extends GBActivity {
} }
return super.onOptionsItemSelected(item); return super.onOptionsItemSelected(item);
} }
public interface DeviceSelectionCallback {
void invoke(GBDevice device);
}
} }

View File

@ -1,78 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.activities;
import android.app.ProgressDialog;
import android.os.AsyncTask;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast;
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R;
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.util.GB;
public class OnboardingActivity extends GBActivity {
private Button importOldActivityDataButton;
private TextView importOldActivityDataText;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_onboarding);
Bundle extras = getIntent().getExtras();
GBDevice device;
if (extras != null) {
device = extras.getParcelable(GBDevice.EXTRA_DEVICE);
} else {
throw new IllegalArgumentException("Must provide a device when invoking this activity");
}
importOldActivityDataText = (TextView) findViewById(R.id.textview_import_old_activitydata);
importOldActivityDataText.setText(String.format(getString(R.string.import_old_db_information), device.getName()));
importOldActivityDataButton = (Button) findViewById(R.id.button_import_old_activitydata);
final GBDevice finalDevice = device;
importOldActivityDataButton.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
mergeOldActivityDbContents(finalDevice);
}
});
}
private void mergeOldActivityDbContents(final GBDevice device) {
if (device == null) {
return;
}
final DBHelper helper = new DBHelper(getBaseContext());
final ActivityDatabaseHandler oldHandler = helper.getOldActivityDatabaseHandler();
if (oldHandler == null) {
GB.toast(this, "No old activity database found, nothing to import.", Toast.LENGTH_LONG, GB.ERROR);
return;
}
try (DBHandler targetHandler = GBApplication.acquireDB()) {
final ProgressDialog progress = ProgressDialog.show(OnboardingActivity.this, "Merging Activity Data", "Please wait while merging your activity data...", true, false);
new AsyncTask<Object, ProgressDialog, Object>() {
@Override
protected Object doInBackground(Object[] params) {
helper.importOldDb(oldHandler, device, targetHandler);
progress.dismiss();
finish();
return null;
}
}.execute((Object[]) null);
} catch (Exception ex) {
GB.toast(OnboardingActivity.this, "Error importing old activity data into new database.", Toast.LENGTH_LONG, GB.ERROR, ex);
}
}
}

View File

@ -1,105 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.database;
import android.content.Context;
import android.database.Cursor;
import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper;
import android.widget.Toast;
import java.io.File;
import nodomain.freeyourgadget.gadgetbridge.database.schema.ActivityDBCreationScript;
import nodomain.freeyourgadget.gadgetbridge.database.schema.SchemaMigration;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoMaster;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.DATABASE_NAME;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_TIMESTAMP;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES;
/**
* @deprecated can be removed entirely, only used for backwards compatibility
*/
public class ActivityDatabaseHandler extends SQLiteOpenHelper implements DBHandler {
private static final int DATABASE_VERSION = 7;
private static final String UPDATER_CLASS_NAME_PREFIX = "ActivityDBUpdate_";
private final Context context;
public ActivityDatabaseHandler(Context context) {
super(context, DATABASE_NAME, null, DATABASE_VERSION);
this.context = context;
}
@Override
public void onCreate(SQLiteDatabase db) {
try {
ActivityDBCreationScript script = new ActivityDBCreationScript();
script.createSchema(db);
} catch (RuntimeException ex) {
GB.toast("Error creating database.", Toast.LENGTH_SHORT, GB.ERROR, ex);
}
}
@Override
public void onUpgrade(SQLiteDatabase db, int oldVersion, int newVersion) {
new SchemaMigration(UPDATER_CLASS_NAME_PREFIX).onUpgrade(db, oldVersion, newVersion);
}
@Override
public void onDowngrade(SQLiteDatabase db, int oldVersion, int newVersion) {
new SchemaMigration(UPDATER_CLASS_NAME_PREFIX).onDowngrade(db, oldVersion, newVersion);
}
@Override
public SQLiteDatabase getDatabase() {
return super.getWritableDatabase();
}
@Override
public void closeDb() {
}
@Override
public void openDb() {
}
@Override
public SQLiteOpenHelper getHelper() {
return this;
}
public Context getContext() {
return context;
}
public boolean hasContent() {
File dbFile = getContext().getDatabasePath(getDatabaseName());
if (dbFile == null || !dbFile.exists()) {
return false;
}
try {
try (SQLiteDatabase db = this.getReadableDatabase()) {
try (Cursor cursor = db.query(TABLE_GBACTIVITYSAMPLES, new String[]{KEY_TIMESTAMP}, null, null, null, null, null, "1")) {
return cursor.moveToFirst();
}
}
} catch (Exception ex) {
// can't expect anything
GB.log("Error looking for old activity data: " + ex.getMessage(), GB.ERROR, ex);
return false;
}
}
@Override
public DaoSession getDaoSession() {
throw new UnsupportedOperationException();
}
@Override
public DaoMaster getDaoMaster() {
throw new UnsupportedOperationException();
}
}

View File

@ -1,18 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.database;
/**
* TODO: Legacy, can be removed once migration support for old ActivityDatabase is removed
* @deprecated only for backwards compatibility
*/
public class DBConstants {
public static final String DATABASE_NAME = "ActivityDatabase";
public static final String TABLE_GBACTIVITYSAMPLES = "GBActivitySamples";
public static final String KEY_TIMESTAMP = "timestamp";
public static final String KEY_PROVIDER = "provider";
public static final String KEY_INTENSITY = "intensity";
public static final String KEY_STEPS = "steps";
public static final String KEY_CUSTOM_SHORT = "customShort";
public static final String KEY_TYPE = "type";
}

View File

@ -6,7 +6,6 @@ import android.database.sqlite.SQLiteDatabase;
import android.database.sqlite.SQLiteOpenHelper; import android.database.sqlite.SQLiteOpenHelper;
import android.support.annotation.NonNull; import android.support.annotation.NonNull;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;
import android.widget.Toast;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
@ -14,7 +13,6 @@ import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Calendar; import java.util.Calendar;
import java.util.Date; import java.util.Date;
import java.util.List; import java.util.List;
@ -26,11 +24,7 @@ import de.greenrobot.dao.query.Query;
import de.greenrobot.dao.query.QueryBuilder; import de.greenrobot.dao.query.QueryBuilder;
import de.greenrobot.dao.query.WhereCondition; import de.greenrobot.dao.query.WhereCondition;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator; import nodomain.freeyourgadget.gadgetbridge.devices.DeviceCoordinator;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleHealthSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.devices.pebble.PebbleMisfitSampleProvider;
import nodomain.freeyourgadget.gadgetbridge.entities.AbstractActivitySample;
import nodomain.freeyourgadget.gadgetbridge.entities.ActivityDescription; import nodomain.freeyourgadget.gadgetbridge.entities.ActivityDescription;
import nodomain.freeyourgadget.gadgetbridge.entities.ActivityDescriptionDao; import nodomain.freeyourgadget.gadgetbridge.entities.ActivityDescriptionDao;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
@ -38,29 +32,18 @@ import nodomain.freeyourgadget.gadgetbridge.entities.Device;
import nodomain.freeyourgadget.gadgetbridge.entities.DeviceAttributes; import nodomain.freeyourgadget.gadgetbridge.entities.DeviceAttributes;
import nodomain.freeyourgadget.gadgetbridge.entities.DeviceAttributesDao; import nodomain.freeyourgadget.gadgetbridge.entities.DeviceAttributesDao;
import nodomain.freeyourgadget.gadgetbridge.entities.DeviceDao; import nodomain.freeyourgadget.gadgetbridge.entities.DeviceDao;
import nodomain.freeyourgadget.gadgetbridge.entities.PebbleHealthActivityOverlay;
import nodomain.freeyourgadget.gadgetbridge.entities.PebbleHealthActivityOverlayDao;
import nodomain.freeyourgadget.gadgetbridge.entities.Tag; import nodomain.freeyourgadget.gadgetbridge.entities.Tag;
import nodomain.freeyourgadget.gadgetbridge.entities.TagDao; import nodomain.freeyourgadget.gadgetbridge.entities.TagDao;
import nodomain.freeyourgadget.gadgetbridge.entities.User; import nodomain.freeyourgadget.gadgetbridge.entities.User;
import nodomain.freeyourgadget.gadgetbridge.entities.UserAttributes; import nodomain.freeyourgadget.gadgetbridge.entities.UserAttributes;
import nodomain.freeyourgadget.gadgetbridge.entities.UserDao; import nodomain.freeyourgadget.gadgetbridge.entities.UserDao;
import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice; import nodomain.freeyourgadget.gadgetbridge.impl.GBDevice;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityKind;
import nodomain.freeyourgadget.gadgetbridge.model.ActivitySample;
import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser; import nodomain.freeyourgadget.gadgetbridge.model.ActivityUser;
import nodomain.freeyourgadget.gadgetbridge.model.ValidByDate; import nodomain.freeyourgadget.gadgetbridge.model.ValidByDate;
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils; import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper; import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils; import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
import nodomain.freeyourgadget.gadgetbridge.util.GB;
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 * Provides utiliy access to some common entities, so you won't need to use
@ -547,149 +530,6 @@ public class DBHelper {
return tag; return tag;
} }
/**
* 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, DBHandler targetDBHandler) {
DaoSession tempSession = targetDBHandler.getDaoMaster().newSession();
try {
importActivityDatabase(oldDb, targetDevice, tempSession);
} finally {
tempSession.clear();
}
}
private boolean isEmpty(DaoSession session) {
long totalSamplesCount = session.getMiBandActivitySampleDao().count();
totalSamplesCount += session.getPebbleHealthActivitySampleDao().count();
return totalSamplesCount == 0;
}
private void importActivityDatabase(ActivityDatabaseHandler oldDbHandler, GBDevice targetDevice, DaoSession session) {
try (SQLiteDatabase oldDB = oldDbHandler.getReadableDatabase()) {
User user = DBHelper.getUser(session);
for (DeviceCoordinator coordinator : DeviceHelper.getInstance().getAllCoordinators()) {
if (coordinator.supports(targetDevice)) {
AbstractSampleProvider<? extends AbstractActivitySample> sampleProvider = (AbstractSampleProvider<? extends AbstractActivitySample>) coordinator.getSampleProvider(targetDevice, session);
importActivitySamples(oldDB, targetDevice, session, sampleProvider, user);
break;
}
}
}
}
private <T extends AbstractActivitySample> void importActivitySamples(SQLiteDatabase fromDb, GBDevice targetDevice, DaoSession targetSession, AbstractSampleProvider<T> sampleProvider, User user) {
if (sampleProvider instanceof PebbleMisfitSampleProvider) {
GB.toast(context, "Migration of old Misfit data is not supported!", Toast.LENGTH_LONG, GB.WARN);
return;
}
String order = "timestamp";
final String where = "provider=" + sampleProvider.getID();
boolean convertActivityTypeToRange = false;
int currentTypeRun, previousTypeRun, currentTimeStamp, currentTypeStartTimeStamp, currentTypeEndTimeStamp;
List<PebbleHealthActivityOverlay> overlayList = new ArrayList<>();
final int BATCH_SIZE = 100000; // 100.000 samples = rougly 20 MB per batch
List<T> newSamples;
if (sampleProvider instanceof PebbleHealthSampleProvider) {
convertActivityTypeToRange = true;
previousTypeRun = ActivitySample.NOT_MEASURED;
currentTypeStartTimeStamp = -1;
currentTypeEndTimeStamp = -1;
} else {
previousTypeRun = currentTypeStartTimeStamp = currentTypeEndTimeStamp = 0;
}
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();
newSamples = new ArrayList<>(Math.min(BATCH_SIZE, cursor.getCount()));
while (cursor.moveToNext()) {
T newSample = sampleProvider.createActivitySample();
newSample.setProvider(sampleProvider);
newSample.setUserId(userId);
newSample.setDeviceId(deviceId);
currentTimeStamp = cursor.getInt(colTimeStamp);
newSample.setTimestamp(currentTimeStamp);
newSample.setRawIntensity(getNullableInt(cursor, colIntensity, ActivitySample.NOT_MEASURED));
currentTypeRun = getNullableInt(cursor, colType, ActivitySample.NOT_MEASURED);
newSample.setRawKind(currentTypeRun);
if (convertActivityTypeToRange) {
//at the beginning there is no start timestamp
if (currentTypeStartTimeStamp == -1) {
currentTypeStartTimeStamp = currentTypeEndTimeStamp = currentTimeStamp;
previousTypeRun = currentTypeRun;
}
if (currentTypeRun != previousTypeRun) {
//we used not to store the last sample, now we do the opposite and we need to round up
currentTypeEndTimeStamp = currentTimeStamp;
//if the Type has changed, the run has ended. Only store light and deep sleep data
if (previousTypeRun == 4) {
overlayList.add(new PebbleHealthActivityOverlay(currentTypeStartTimeStamp, currentTypeEndTimeStamp, sampleProvider.toRawActivityKind(ActivityKind.TYPE_LIGHT_SLEEP), deviceId, userId, null));
} else if (previousTypeRun == 5) {
overlayList.add(new PebbleHealthActivityOverlay(currentTypeStartTimeStamp, currentTypeEndTimeStamp, sampleProvider.toRawActivityKind(ActivityKind.TYPE_DEEP_SLEEP), deviceId, userId, null));
}
currentTypeStartTimeStamp = currentTimeStamp;
previousTypeRun = currentTypeRun;
} else {
//just expand the run
currentTypeEndTimeStamp = currentTimeStamp;
}
}
newSample.setSteps(getNullableInt(cursor, colSteps, ActivitySample.NOT_MEASURED));
if (colCustomShort > -1) {
newSample.setHeartRate(getNullableInt(cursor, colCustomShort, ActivitySample.NOT_MEASURED));
} else {
newSample.setHeartRate(ActivitySample.NOT_MEASURED);
}
newSamples.add(newSample);
if ((newSamples.size() % BATCH_SIZE) == 0) {
sampleProvider.getSampleDao().insertOrReplaceInTx(newSamples, true);
targetSession.clear();
newSamples.clear();
}
}
// and insert the remaining samples
if (!newSamples.isEmpty()) {
sampleProvider.getSampleDao().insertOrReplaceInTx(newSamples, true);
}
// store the overlay records
if (!overlayList.isEmpty()) {
PebbleHealthActivityOverlayDao overlayDao = targetSession.getPebbleHealthActivityOverlayDao();
overlayDao.insertOrReplaceInTx(overlayList);
}
}
}
private int getNullableInt(Cursor cursor, int columnIndex, int defaultValue) {
if (cursor.isNull(columnIndex)) {
return defaultValue;
}
return cursor.getInt(columnIndex);
}
public static void clearSession() { public static void clearSession() {
try (DBHandler dbHandler = GBApplication.acquireDB()) { try (DBHandler dbHandler = GBApplication.acquireDB()) {
DaoSession session = dbHandler.getDaoSession(); DaoSession session = dbHandler.getDaoSession();

View File

@ -1,27 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.database.schema;
import android.database.sqlite.SQLiteDatabase;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
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;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES;
public class ActivityDBCreationScript {
public void createSchema(SQLiteDatabase db) {
String CREATE_GBACTIVITYSAMPLES_TABLE = "CREATE TABLE " + TABLE_GBACTIVITYSAMPLES + " ("
+ KEY_TIMESTAMP + " INT,"
+ KEY_PROVIDER + " TINYINT,"
+ KEY_INTENSITY + " SMALLINT,"
+ KEY_STEPS + " TINYINT,"
+ KEY_TYPE + " TINYINT,"
+ KEY_CUSTOM_SHORT + " INT,"
+ " PRIMARY KEY (" + KEY_TIMESTAMP + "," + KEY_PROVIDER + ") ON CONFLICT REPLACE)" + DBHelper.getWithoutRowId();
db.execSQL(CREATE_GBACTIVITYSAMPLES_TABLE);
}
}

View File

@ -1,31 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.database.schema;
import android.database.sqlite.SQLiteDatabase;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES;
/**
* Upgrade and downgrade with DB versions <= 5 is not supported.
* Just recreates the default schema. Those GB versions may or may not
* work with that, but this code will probably not create a DB for them
* anyway.
*/
public class ActivityDBUpdate_4 extends ActivityDBCreationScript implements DBUpdateScript {
@Override
public void upgradeSchema(SQLiteDatabase db) {
recreateSchema(db);
}
@Override
public void downgradeSchema(SQLiteDatabase db) {
recreateSchema(db);
}
private void recreateSchema(SQLiteDatabase db) {
DBHelper.dropTable(TABLE_GBACTIVITYSAMPLES, db);
createSchema(db);
}
}

View File

@ -1,27 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.database.schema;
import android.database.sqlite.SQLiteDatabase;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.database.DBUpdateScript;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.KEY_CUSTOM_SHORT;
import static nodomain.freeyourgadget.gadgetbridge.database.DBConstants.TABLE_GBACTIVITYSAMPLES;
/**
* Adds a column "customShort" to the table "GBActivitySamples"
*/
public class ActivityDBUpdate_6 implements DBUpdateScript {
@Override
public void upgradeSchema(SQLiteDatabase db) {
if (!DBHelper.existsColumn(TABLE_GBACTIVITYSAMPLES, KEY_CUSTOM_SHORT, db)) {
String ADD_COLUMN_CUSTOM_SHORT = "ALTER TABLE " + TABLE_GBACTIVITYSAMPLES + " ADD COLUMN "
+ KEY_CUSTOM_SHORT + " INT;";
db.execSQL(ADD_COLUMN_CUSTOM_SHORT);
}
}
@Override
public void downgradeSchema(SQLiteDatabase db) {
}
}

View File

@ -1,8 +0,0 @@
package nodomain.freeyourgadget.gadgetbridge.database.schema;
/**
* Bugfix for users who installed 0.8.1 cleanly, i.e. without any previous
* database. Perform Update script 6 again.
*/
public class ActivityDBUpdate_7 extends ActivityDBUpdate_6 {
}

View File

@ -23,7 +23,6 @@ import java.util.UUID;
import nodomain.freeyourgadget.gadgetbridge.GBApplication; import nodomain.freeyourgadget.gadgetbridge.GBApplication;
import nodomain.freeyourgadget.gadgetbridge.R; import nodomain.freeyourgadget.gadgetbridge.R;
import nodomain.freeyourgadget.gadgetbridge.activities.OnboardingActivity;
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler; import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper; import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession; import nodomain.freeyourgadget.gadgetbridge.entities.DaoSession;
@ -40,7 +39,6 @@ import nodomain.freeyourgadget.gadgetbridge.model.Alarm;
import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec; import nodomain.freeyourgadget.gadgetbridge.model.CalendarEventSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CallSpec; import nodomain.freeyourgadget.gadgetbridge.model.CallSpec;
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec; import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec; import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec; import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
@ -195,20 +193,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
if (device.isInitialized()) { if (device.isInitialized()) {
try (DBHandler dbHandler = GBApplication.acquireDB()) { try (DBHandler dbHandler = GBApplication.acquireDB()) {
DaoSession session = dbHandler.getDaoSession(); DaoSession session = dbHandler.getDaoSession();
boolean askForDBMigration = false;
if (DBHelper.findDevice(device, session) == null && device.getType() != DeviceType.VIBRATISSIMO && (device.getType() != DeviceType.LIVEVIEW)) {
askForDBMigration = true;
}
DBHelper.getDevice(device, session); // implicitly creates the device in database if not present, and updates device attributes DBHelper.getDevice(device, session); // implicitly creates the device in database if not present, and updates device attributes
if (askForDBMigration) {
DBHelper dbHelper = new DBHelper(context);
if (dbHelper.getOldActivityDatabaseHandler() != null) {
Intent startIntent = new Intent(context, OnboardingActivity.class);
startIntent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
startIntent.putExtra(GBDevice.EXTRA_DEVICE, device);
startActivity(startIntent);
}
}
} catch (Exception ignore) { } catch (Exception ignore) {
} }
} }

View File

@ -31,7 +31,6 @@
android:layout_height="wrap_content" android:layout_height="wrap_content"
android:layout_weight="1" android:layout_weight="1"
android:singleLine="false"
android:text="Export DB" /> android:text="Export DB" />
<Button <Button
@ -65,13 +64,6 @@
android:textAppearance="?android:attr/textAppearanceMedium" android:textAppearance="?android:attr/textAppearanceMedium"
android:textColor="@color/accent" /> android:textColor="@color/accent" />
<TextView
android:id="@+id/mergeOldActivityDataText"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="@string/activity_db_management_merge_old_explanation"
android:textAppearance="?android:attr/textAppearanceSmall" />
<LinearLayout <LinearLayout
android:layout_width="match_parent" android:layout_width="match_parent"
android:layout_height="wrap_content" android:layout_height="wrap_content"
@ -79,14 +71,6 @@
android:orientation="horizontal" android:orientation="horizontal"
android:weightSum="2"> android:weightSum="2">
<Button
android:id="@+id/mergeOldActivityData"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal"
android:layout_weight="1"
android:text="Import old activity data" />
<Button <Button
android:id="@+id/deleteOldActivityDB" android:id="@+id/deleteOldActivityDB"
android:layout_width="wrap_content" android:layout_width="wrap_content"

View File

@ -1,31 +0,0 @@
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:paddingBottom="@dimen/activity_vertical_margin"
android:paddingLeft="@dimen/activity_horizontal_margin"
android:paddingRight="@dimen/activity_horizontal_margin"
android:paddingTop="@dimen/activity_vertical_margin"
tools:context="nodomain.freeyourgadget.gadgetbridge.activities.ControlCenter">
<Button
android:id="@+id/button_import_old_activitydata"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="fill_horizontal"
android:layout_alignParentBottom="true"
android:layout_centerHorizontal="true"
android:text="@string/import_old_db_buttonlabel" />
<TextView
android:id="@+id/textview_import_old_activitydata"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_above="@+id/button_import_old_activitydata"
android:layout_alignParentEnd="true"
android:layout_alignParentStart="true"
android:layout_alignParentTop="true"
android:text="@string/import_old_db_information" />
</RelativeLayout>

View File

@ -351,23 +351,12 @@
<string name="charts_legend_heartrate">Heart Rate</string> <string name="charts_legend_heartrate">Heart Rate</string>
<string name="live_activity_heart_rate">Heart Rate</string> <string name="live_activity_heart_rate">Heart Rate</string>
<!-- Strings related to Onboading Activity -->
<string name="title_activity_onboarding">Database Import</string>
<string name="import_old_db_buttonlabel">Import old activity data</string>
<string name="import_old_db_information">Since Gadgetbridge 0.12.0 we use a new database format.
You are able to import old activity data and associate it with the device you are connecting to (%1$s).\n
\n
If you do not import old activity data now, you can still do it later by tapping the "MERGE OLD ACTIVITY DATA" button in the Database Management Activity"\n
\n
Please note that you can import data from Mi Band, Pebble Health and Morpheuz but NOT from Pebble Misfit.
</string>
<string name="pref_title_pebble_health_store_raw">Store raw record in the database</string> <string name="pref_title_pebble_health_store_raw">Store raw record in the database</string>
<string name="pref_summary_pebble_health_store_raw">If checked the data is stored \"as is\" and is available for later interpretation. NB: the database will be bigger in this case!</string> <string name="pref_summary_pebble_health_store_raw">If checked the data is stored \"as is\" and is available for later interpretation. NB: the database will be bigger in this case!</string>
<string name="action_db_management">Database Management</string> <string name="action_db_management">Database Management</string>
<string name="title_activity_db_management">Database Management</string> <string name="title_activity_db_management">Database Management</string>
<string name="activity_db_management_import_export_explanation">The database operations use the following path on your device. \nThis path is accessible to other Android applications and your computer. \nExpect to find your exported database (or place the database you want to import) there:</string> <string name="activity_db_management_import_export_explanation">The database operations use the following path on your device. \nThis path is accessible to other Android applications and your computer. \nExpect to find your exported database (or place the database you want to import) there:</string>
<string name="activity_db_management_merge_old_explanation">The activity data recorded with Gadgetbridge versions prior to 0.12 must be converted to a new format. \nYou can do this using the button below. Be aware that you must be connected to the device you want to associate the old activity data with! \nIf you already imported your data and are happy with the result, you may delete the old database.</string> <string name="activity_db_management_merge_old_title">Legacy Database Delete</string>
<string name="activity_db_management_merge_old_title">Legacy Database Import / Delete</string>
<string name="dbmanagementactivvity_cannot_access_export_path">Cannot access export path. Please contact the developers.</string> <string name="dbmanagementactivvity_cannot_access_export_path">Cannot access export path. Please contact the developers.</string>
<string name="dbmanagementactivity_exported_to">Exported to: %1$s</string> <string name="dbmanagementactivity_exported_to">Exported to: %1$s</string>
<string name="dbmanagementactivity_error_exporting_db">"Error exporting DB: %1$s"</string> <string name="dbmanagementactivity_error_exporting_db">"Error exporting DB: %1$s"</string>
@ -375,12 +364,6 @@
<string name="dbmanagementactivity_overwrite_database_confirmation">Really overwrite the current database? All your current activity data (if any) will be lost.</string> <string name="dbmanagementactivity_overwrite_database_confirmation">Really overwrite the current database? All your current activity data (if any) will be lost.</string>
<string name="dbmanagementactivity_import_successful">Import successful.</string> <string name="dbmanagementactivity_import_successful">Import successful.</string>
<string name="dbmanagementactivity_error_importing_db">"Error importing DB: %1$s"</string> <string name="dbmanagementactivity_error_importing_db">"Error importing DB: %1$s"</string>
<string name="dbmanagementactivity_no_old_activitydatabase_found">No old activity database found, nothing to import.</string>
<string name="dbmanagementactivity_no_connected_device">No connected device to associate old activity data with.</string>
<string name="dbmanagementactivity_merging_activity_data_title">Merging Activity Data</string>
<string name="dbmanagementactivity_please_wait_while_merging">Please wait while merging your activity data…</string>
<string name="dbmanagementactivity_error_importing_old_activity_data">Error importing old activity data into new database.</string>
<string name="dbmanagementactivity_associate_old_data_with_device">Associate old Data with Device</string>
<string name="dbmanagementactivity_delete_activity_data_title">Delete Activity Data?</string> <string name="dbmanagementactivity_delete_activity_data_title">Delete Activity Data?</string>
<string name="dbmanagementactivity_really_delete_entire_db">Really delete the entire database? All your activity data and information about your devices will be lost.</string> <string name="dbmanagementactivity_really_delete_entire_db">Really delete the entire database? All your activity data and information about your devices will be lost.</string>
<string name="dbmanagementactivity_database_successfully_deleted">Data successfully deleted.</string> <string name="dbmanagementactivity_database_successfully_deleted">Data successfully deleted.</string>