mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-11-24 19:06:53 +01:00
Drop support for legacy (pre 0.12.0) database
This commit is contained in:
parent
49e1b55ad8
commit
08080b02bb
@ -27,7 +27,6 @@ import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.locks.Lock;
|
||||
import java.util.concurrent.locks.ReentrantLock;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBConstants;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBOpenHelper;
|
||||
@ -335,11 +334,7 @@ public class GBApplication extends Application {
|
||||
if (lockHandler != null) {
|
||||
lockHandler.closeDb();
|
||||
}
|
||||
DBHelper dbHelper = new DBHelper(context);
|
||||
boolean result = true;
|
||||
if (dbHelper.existsDB(DBConstants.DATABASE_NAME)) {
|
||||
result = getContext().deleteDatabase(DBConstants.DATABASE_NAME);
|
||||
}
|
||||
boolean result = deleteOldActivityDatabase(context);
|
||||
result &= getContext().deleteDatabase(DATABASE_NAME);
|
||||
return result;
|
||||
}
|
||||
@ -352,8 +347,8 @@ public class GBApplication extends Application {
|
||||
public static synchronized boolean deleteOldActivityDatabase(Context context) {
|
||||
DBHelper dbHelper = new DBHelper(context);
|
||||
boolean result = true;
|
||||
if (dbHelper.existsDB(DBConstants.DATABASE_NAME)) {
|
||||
result = getContext().deleteDatabase(DBConstants.DATABASE_NAME);
|
||||
if (dbHelper.existsDB("ActivityDatabase")) {
|
||||
result = getContext().deleteDatabase("ActivityDatabase");
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
@ -1,11 +1,9 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.activities;
|
||||
|
||||
import android.app.AlertDialog;
|
||||
import android.app.ProgressDialog;
|
||||
import android.content.DialogInterface;
|
||||
import android.content.IntentFilter;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.os.AsyncTask;
|
||||
import android.os.Bundle;
|
||||
import android.support.v4.app.NavUtils;
|
||||
import android.view.MenuItem;
|
||||
@ -18,16 +16,11 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
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.util.FileUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.GB;
|
||||
|
||||
@ -37,7 +30,6 @@ public class DbManagementActivity extends GBActivity {
|
||||
|
||||
private Button exportDBButton;
|
||||
private Button importDBButton;
|
||||
private Button importOldActivityDataButton;
|
||||
private Button deleteOldActivityDBButton;
|
||||
private Button deleteDBButton;
|
||||
private TextView dbPath;
|
||||
@ -68,22 +60,7 @@ public class DbManagementActivity extends GBActivity {
|
||||
}
|
||||
});
|
||||
|
||||
boolean hasOldDB = hasOldActivityDatabase();
|
||||
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();
|
||||
}
|
||||
});
|
||||
int oldDBVisibility = hasOldActivityDatabase() ? View.VISIBLE : View.GONE;
|
||||
|
||||
deleteOldActivityDBButton = (Button) findViewById(R.id.deleteOldActivityDB);
|
||||
deleteOldActivityDBButton.setVisibility(oldDBVisibility);
|
||||
@ -104,7 +81,7 @@ public class DbManagementActivity extends GBActivity {
|
||||
}
|
||||
|
||||
private boolean hasOldActivityDatabase() {
|
||||
return new DBHelper(this).getOldActivityDatabaseHandler() != null;
|
||||
return new DBHelper(this).existsDB("ActivityDatabase");
|
||||
}
|
||||
|
||||
private String getExternalPath() {
|
||||
@ -156,67 +133,6 @@ public class DbManagementActivity extends GBActivity {
|
||||
.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() {
|
||||
new AlertDialog.Builder(this)
|
||||
.setCancelable(true)
|
||||
@ -271,8 +187,4 @@ public class DbManagementActivity extends GBActivity {
|
||||
}
|
||||
return super.onOptionsItemSelected(item);
|
||||
}
|
||||
|
||||
public interface DeviceSelectionCallback {
|
||||
void invoke(GBDevice device);
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -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();
|
||||
}
|
||||
}
|
@ -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";
|
||||
}
|
@ -6,7 +6,6 @@ import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
import android.support.annotation.NonNull;
|
||||
import android.support.annotation.Nullable;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
@ -14,7 +13,6 @@ import org.slf4j.LoggerFactory;
|
||||
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;
|
||||
@ -26,11 +24,7 @@ import de.greenrobot.dao.query.Query;
|
||||
import de.greenrobot.dao.query.QueryBuilder;
|
||||
import de.greenrobot.dao.query.WhereCondition;
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.devices.AbstractSampleProvider;
|
||||
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.ActivityDescriptionDao;
|
||||
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.DeviceAttributesDao;
|
||||
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.TagDao;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.User;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.UserAttributes;
|
||||
import nodomain.freeyourgadget.gadgetbridge.entities.UserDao;
|
||||
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.ValidByDate;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DateTimeUtils;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.DeviceHelper;
|
||||
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
|
||||
@ -547,149 +530,6 @@ public class DBHelper {
|
||||
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() {
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
DaoSession session = dbHandler.getDaoSession();
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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);
|
||||
}
|
||||
}
|
@ -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) {
|
||||
}
|
||||
}
|
@ -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 {
|
||||
}
|
@ -23,7 +23,6 @@ import java.util.UUID;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
import nodomain.freeyourgadget.gadgetbridge.R;
|
||||
import nodomain.freeyourgadget.gadgetbridge.activities.OnboardingActivity;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
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.CallSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.CannedMessagesSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.DeviceType;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.MusicStateSpec;
|
||||
import nodomain.freeyourgadget.gadgetbridge.model.NotificationSpec;
|
||||
@ -195,20 +193,7 @@ public class DeviceCommunicationService extends Service implements SharedPrefere
|
||||
if (device.isInitialized()) {
|
||||
try (DBHandler dbHandler = GBApplication.acquireDB()) {
|
||||
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
|
||||
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) {
|
||||
}
|
||||
}
|
||||
|
@ -31,7 +31,6 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_weight="1"
|
||||
|
||||
android:singleLine="false"
|
||||
android:text="Export DB" />
|
||||
|
||||
<Button
|
||||
@ -65,13 +64,6 @@
|
||||
android:textAppearance="?android:attr/textAppearanceMedium"
|
||||
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
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="wrap_content"
|
||||
@ -79,14 +71,6 @@
|
||||
android:orientation="horizontal"
|
||||
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
|
||||
android:id="@+id/deleteOldActivityDB"
|
||||
android:layout_width="wrap_content"
|
||||
|
@ -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>
|
@ -351,23 +351,12 @@
|
||||
<string name="charts_legend_heartrate">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_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="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_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 Import / Delete</string>
|
||||
<string name="activity_db_management_merge_old_title">Legacy Database Delete</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_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_import_successful">Import successful.</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_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>
|
||||
|
Loading…
Reference in New Issue
Block a user