mirror of
https://codeberg.org/Freeyourgadget/Gadgetbridge
synced 2024-12-25 18:15:49 +01:00
Basic database import and export (to external storage)
(In the Debug Activity)
This commit is contained in:
parent
b9d5fc6572
commit
cc549a6c49
@ -13,20 +13,34 @@ import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.Button;
|
||||
import android.widget.EditText;
|
||||
import android.widget.Toast;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.DBHelper;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
||||
|
||||
public class DebugActivity extends Activity {
|
||||
Button sendSMSButton;
|
||||
Button sendEmailButton;
|
||||
Button incomingCallButton;
|
||||
Button outgoingCallButton;
|
||||
Button startCallButton;
|
||||
Button endCallButton;
|
||||
Button testNotificationButton;
|
||||
Button setMusicInfoButton;
|
||||
Button setTimeButton;
|
||||
Button rebootButton;
|
||||
EditText editContent;
|
||||
private static final Logger LOG = LoggerFactory.getLogger(DebugActivity.class);
|
||||
|
||||
private Button sendSMSButton;
|
||||
private Button sendEmailButton;
|
||||
private Button incomingCallButton;
|
||||
private Button outgoingCallButton;
|
||||
private Button startCallButton;
|
||||
private Button endCallButton;
|
||||
private Button testNotificationButton;
|
||||
private Button setMusicInfoButton;
|
||||
private Button setTimeButton;
|
||||
private Button rebootButton;
|
||||
private Button exportDBButton;
|
||||
private Button importDBButton;
|
||||
private EditText editContent;
|
||||
|
||||
private BroadcastReceiver mReceiver = new BroadcastReceiver() {
|
||||
@Override
|
||||
@ -114,6 +128,21 @@ public class DebugActivity extends Activity {
|
||||
}
|
||||
});
|
||||
|
||||
exportDBButton = (Button) findViewById(R.id.exportDBButton);
|
||||
exportDBButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
exportDB();
|
||||
}
|
||||
});
|
||||
importDBButton = (Button) findViewById(R.id.importDBButton);
|
||||
importDBButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(View v) {
|
||||
importDB();
|
||||
}
|
||||
});
|
||||
|
||||
rebootButton = (Button) findViewById(R.id.rebootButton);
|
||||
rebootButton.setOnClickListener(new View.OnClickListener() {
|
||||
@Override
|
||||
@ -156,6 +185,34 @@ public class DebugActivity extends Activity {
|
||||
});
|
||||
}
|
||||
|
||||
private void exportDB() {
|
||||
try {
|
||||
ActivityDatabaseHandler dbHandler = GBApplication.getActivityDatabaseHandler();
|
||||
DBHelper helper = new DBHelper(this);
|
||||
File dir = FileUtils.getExternalFilesDir();
|
||||
File destFile = helper.exportDB(dbHandler, dir);
|
||||
Toast.makeText(this, "Exported to: " + destFile.getAbsolutePath(), Toast.LENGTH_LONG).show();
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Unable to export db", ex);
|
||||
Toast.makeText(this, "Error exporting DB: " + ex.getMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void importDB() {
|
||||
try {
|
||||
ActivityDatabaseHandler dbHandler = GBApplication.getActivityDatabaseHandler();
|
||||
DBHelper helper = new DBHelper(this);
|
||||
File dir = FileUtils.getExternalFilesDir();
|
||||
File sourceFile = new File(dir, dbHandler.getDatabaseName());
|
||||
helper.importDB(dbHandler, sourceFile);
|
||||
helper.validateDB(dbHandler);
|
||||
Toast.makeText(this, "Import successful.", Toast.LENGTH_LONG).show();
|
||||
} catch (Exception ex) {
|
||||
LOG.error("Unable to import db", ex);
|
||||
Toast.makeText(this, "Error importing DB: " + ex.getMessage(), Toast.LENGTH_LONG).show();
|
||||
}
|
||||
}
|
||||
|
||||
private void testNotification() {
|
||||
NotificationManager nManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);
|
||||
NotificationCompat.Builder ncomp = new NotificationCompat.Builder(this);
|
||||
|
@ -12,8 +12,10 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.database.ActivityDatabaseHandler;
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
||||
public class GBApplication extends Application {
|
||||
private static GBApplication context;
|
||||
@ -47,20 +49,15 @@ public class GBApplication extends Application {
|
||||
|
||||
private void setupLogging() {
|
||||
if (isFileLoggingEnabled()) {
|
||||
File dir = getExternalFilesDir(null);
|
||||
if (dir != null) {
|
||||
if (!dir.exists()) {
|
||||
dir.mkdirs();
|
||||
}
|
||||
try {
|
||||
File dir = FileUtils.getExternalFilesDir();
|
||||
// used by assets/logback.xml since the location cannot be statically determined
|
||||
System.setProperty("GB_LOGFILES_DIR", dir.getAbsolutePath());
|
||||
} else {
|
||||
Log.e("GBApplication", "External files dir is null, cannot log to file");
|
||||
} catch (IOException ex) {
|
||||
Log.e("GBApplication", "External files dir not available, cannot log to file, ex");
|
||||
System.setProperty("GB_LOGFILES_DIR", "/dev/null");
|
||||
|
||||
}
|
||||
} else {
|
||||
System.setProperty("GB_LOGFILES_DIR", "/dev/null"); // just to please logback configuration, not used at all
|
||||
try {
|
||||
ch.qos.logback.classic.Logger root = (ch.qos.logback.classic.Logger) LoggerFactory.getLogger(Logger.ROOT_LOGGER_NAME);
|
||||
root.detachAppender("FILE");
|
||||
|
@ -0,0 +1,67 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.database;
|
||||
|
||||
import android.content.Context;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.database.sqlite.SQLiteOpenHelper;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.text.DateFormat;
|
||||
import java.text.SimpleDateFormat;
|
||||
import java.util.Date;
|
||||
import java.util.Locale;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.util.FileUtils;
|
||||
|
||||
public class DBHelper {
|
||||
private final Context context;
|
||||
|
||||
public DBHelper(Context context) {
|
||||
this.context = context;
|
||||
}
|
||||
|
||||
private String getClosedDBPath(SQLiteOpenHelper dbHandler) throws IllegalStateException {
|
||||
SQLiteDatabase db = dbHandler.getReadableDatabase();
|
||||
String path = db.getPath();
|
||||
db.close(); // reference counted, so may still be open
|
||||
if (db.isOpen()) {
|
||||
throw new IllegalStateException("Database must be closed");
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
public File exportDB(SQLiteOpenHelper dbHandler, File toDir) throws IllegalStateException, IOException {
|
||||
String dbPath = getClosedDBPath(dbHandler);
|
||||
File sourceFile = new File(dbPath);
|
||||
File destFile = new File(toDir, sourceFile.getName());
|
||||
if (destFile.exists()) {
|
||||
File backup = new File(toDir, destFile.getName() + "_" + getDate());
|
||||
destFile.renameTo(backup);
|
||||
} else if (!toDir.exists()) {
|
||||
if (!toDir.mkdirs()) {
|
||||
throw new IOException("Unable to create directory: " + toDir.getAbsolutePath());
|
||||
}
|
||||
}
|
||||
|
||||
FileUtils.copyFile(sourceFile, destFile);
|
||||
return destFile;
|
||||
}
|
||||
|
||||
private String getDate() {
|
||||
return new SimpleDateFormat("yyyyMMdd-HHmmss", Locale.US).format(new Date());
|
||||
}
|
||||
|
||||
public void importDB(SQLiteOpenHelper dbHandler, File fromFile) throws IllegalStateException, IOException {
|
||||
String dbPath = getClosedDBPath(dbHandler);
|
||||
File toFile = new File(dbPath);
|
||||
FileUtils.copyFile(fromFile, toFile);
|
||||
}
|
||||
|
||||
public void validateDB(SQLiteOpenHelper dbHandler) throws IOException {
|
||||
try (SQLiteDatabase db = dbHandler.getReadableDatabase()) {
|
||||
if (!db.isDatabaseIntegrityOk()) {
|
||||
throw new IOException("Database integrity is not OK");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,45 @@
|
||||
package nodomain.freeyourgadget.gadgetbridge.util;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.nio.channels.FileChannel;
|
||||
|
||||
import nodomain.freeyourgadget.gadgetbridge.GBApplication;
|
||||
|
||||
public class FileUtils {
|
||||
/**
|
||||
* Copies the the given sourceFile to destFile, overwriting it, in case it exists.
|
||||
* @param sourceFile
|
||||
* @param destFile
|
||||
* @throws IOException
|
||||
*/
|
||||
public static void copyFile(File sourceFile, File destFile) throws IOException {
|
||||
if (!sourceFile.exists()) {
|
||||
throw new IOException("Does not exist: " + sourceFile.getAbsolutePath());
|
||||
}
|
||||
copyFile(new FileInputStream(sourceFile), new FileOutputStream(destFile));
|
||||
}
|
||||
|
||||
private static void copyFile(FileInputStream sourceStream, FileOutputStream destStream) throws IOException {
|
||||
try (FileChannel fromChannel = sourceStream.getChannel(); FileChannel toChannel = destStream.getChannel()) {
|
||||
fromChannel.transferTo(0, fromChannel.size(), toChannel);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the existing external storage dir.
|
||||
* @throws IOException when the directory is not available
|
||||
*/
|
||||
public static File getExternalFilesDir() throws IOException {
|
||||
File dir = GBApplication.getContext().getExternalFilesDir(null);
|
||||
if (dir == null) {
|
||||
throw new IOException("Unable to access external files dir: null");
|
||||
}
|
||||
if (!dir.exists() && !dir.mkdirs()) {
|
||||
throw new IOException("Unable to access external files dir: does not exist");
|
||||
}
|
||||
return dir;
|
||||
}
|
||||
}
|
@ -109,4 +109,23 @@
|
||||
android:layout_alignParentStart="true"
|
||||
android:layout_alignEnd="@+id/endCallButton" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Export DB"
|
||||
android:id="@+id/exportDBButton"
|
||||
android:layout_above="@+id/rebootButton"
|
||||
android:layout_alignEnd="@+id/textView"
|
||||
android:layout_alignParentStart="true"
|
||||
android:singleLine="false" />
|
||||
|
||||
<Button
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:text="Import DB"
|
||||
android:id="@+id/importDBButton"
|
||||
android:layout_alignTop="@+id/exportDBButton"
|
||||
android:layout_alignParentEnd="true"
|
||||
android:layout_toEndOf="@+id/exportDBButton" />
|
||||
|
||||
</RelativeLayout>
|
||||
|
Loading…
Reference in New Issue
Block a user