Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Extract settings import #5225

Merged
merged 10 commits into from
Jan 14, 2021
4 changes: 3 additions & 1 deletion app/build.gradle
Original file line number Diff line number Diff line change
Expand Up @@ -102,6 +102,7 @@ ext {
groupieVersion = '2.8.1'
markwonVersion = '4.6.0'
googleAutoServiceVersion = '1.0-rc7'
mockitoVersion = '3.6.0'
}

configurations {
Expand Down Expand Up @@ -235,7 +236,8 @@ dependencies {
implementation "org.ocpsoft.prettytime:prettytime:4.0.6.Final"

testImplementation 'junit:junit:4.13.1'
testImplementation 'org.mockito:mockito-core:3.6.0'
testImplementation "org.mockito:mockito-core:${mockitoVersion}"
testImplementation "org.mockito:mockito-inline:${mockitoVersion}"

androidTestImplementation "androidx.test.ext:junit:1.1.2"
androidTestImplementation "androidx.room:room-testing:${androidxRoomVersion}"
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -32,14 +32,9 @@
import org.schabi.newpipe.util.ZipHelper;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Locale;
import java.util.Map;
import java.util.zip.ZipFile;

import static org.schabi.newpipe.util.Localization.assureCorrectAppLanguage;

Expand All @@ -49,13 +44,6 @@ public class ContentSettingsFragment extends BasePreferenceFragment {

private ContentSettingsManager manager;

private File databasesDir;
private File newpipeDb;
private File newpipeDbJournal;
private File newpipeDbShm;
private File newpipeDbWal;
private File newpipeSettings;

private String thumbnailLoadToggleKey;
private String youtubeRestrictedModeEnabledKey;

Expand Down Expand Up @@ -120,16 +108,8 @@ public boolean onPreferenceTreeClick(final Preference preference) {
@Override
public void onCreatePreferences(final Bundle savedInstanceState, final String rootKey) {
final File homeDir = ContextCompat.getDataDir(requireContext());
databasesDir = new File(homeDir, "/databases");
newpipeDb = new File(homeDir, "/databases/newpipe.db");
newpipeDbJournal = new File(homeDir, "/databases/newpipe.db-journal");
newpipeDbShm = new File(homeDir, "/databases/newpipe.db-shm");
newpipeDbWal = new File(homeDir, "/databases/newpipe.db-wal");

newpipeSettings = new File(homeDir, "/databases/newpipe.settings");
newpipeSettings.delete();

manager = new ContentSettingsManager(homeDir);
manager = new ContentSettingsManager(new NewPipeFileLocator(homeDir));
manager.deleteSettingsFile();

addPreferencesFromResource(R.xml.content_settings);

Expand Down Expand Up @@ -224,33 +204,24 @@ private void exportDatabase(final String path) {

private void importDatabase(final String filePath) {
// check if file is supported
try (ZipFile zipFile = new ZipFile(filePath)) {
} catch (final IOException ioe) {
if (!ZipHelper.isValidZipFile(filePath)) {
Toast.makeText(getContext(), R.string.no_valid_zip_file, Toast.LENGTH_SHORT)
.show();
.show();
return;
}

try {
if (!databasesDir.exists() && !databasesDir.mkdir()) {
if (!manager.ensureDbDirectoryExists()) {
throw new Exception("Could not create databases dir");
}

final boolean isDbFileExtracted = ZipHelper.extractFileFromZip(filePath,
newpipeDb.getPath(), "newpipe.db");

if (isDbFileExtracted) {
newpipeDbJournal.delete();
newpipeDbWal.delete();
newpipeDbShm.delete();
} else {
if (!manager.extractDb(filePath)) {
Toast.makeText(getContext(), R.string.could_not_import_all_files, Toast.LENGTH_LONG)
.show();
.show();
}

//If settings file exist, ask if it should be imported.
if (ZipHelper.extractFileFromZip(filePath, newpipeSettings.getPath(),
"newpipe.settings")) {
if (manager.extractSettings(filePath)) {
final AlertDialog.Builder alert = new AlertDialog.Builder(getContext());
alert.setTitle(R.string.import_settings);

Expand All @@ -261,7 +232,8 @@ private void importDatabase(final String filePath) {
});
alert.setPositiveButton(getString(R.string.finish), (dialog, which) -> {
dialog.dismiss();
loadSharedPreferences(newpipeSettings);
manager.loadSharedPreferences(PreferenceManager
.getDefaultSharedPreferences(requireContext()));
// restart app to properly load db
System.exit(0);
});
Expand All @@ -275,34 +247,6 @@ private void importDatabase(final String filePath) {
}
}

private void loadSharedPreferences(final File src) {
try (ObjectInputStream input = new ObjectInputStream(new FileInputStream(src))) {
final SharedPreferences.Editor prefEdit = PreferenceManager
.getDefaultSharedPreferences(requireContext()).edit();
prefEdit.clear();
final Map<String, ?> entries = (Map<String, ?>) input.readObject();
for (final Map.Entry<String, ?> entry : entries.entrySet()) {
final Object v = entry.getValue();
final String key = entry.getKey();

if (v instanceof Boolean) {
prefEdit.putBoolean(key, (Boolean) v);
} else if (v instanceof Float) {
prefEdit.putFloat(key, (Float) v);
} else if (v instanceof Integer) {
prefEdit.putInt(key, (Integer) v);
} else if (v instanceof Long) {
prefEdit.putLong(key, (Long) v);
} else if (v instanceof String) {
prefEdit.putString(key, (String) v);
}
}
prefEdit.commit();
} catch (final IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}

/*//////////////////////////////////////////////////////////////////////////
// Error
//////////////////////////////////////////////////////////////////////////*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,22 +3,14 @@ package org.schabi.newpipe.settings
import android.content.SharedPreferences
import org.schabi.newpipe.util.ZipHelper
import java.io.BufferedOutputStream
import java.io.File
import java.io.FileInputStream
import java.io.FileOutputStream
import java.io.IOException
import java.io.ObjectInputStream
import java.io.ObjectOutputStream
import java.lang.Exception
import java.util.zip.ZipOutputStream

class ContentSettingsManager(
private val newpipeDb: File,
private val newpipeSettings: File
) {

constructor(homeDir: File) : this(
File(homeDir, "databases/newpipe.db"),
File(homeDir, "databases/newpipe.settings")
)
class ContentSettingsManager(private val fileLocator: NewPipeFileLocator) {

/**
* Exports given [SharedPreferences] to the file in given outputPath.
Expand All @@ -28,18 +20,83 @@ class ContentSettingsManager(
fun exportDatabase(preferences: SharedPreferences, outputPath: String) {
ZipOutputStream(BufferedOutputStream(FileOutputStream(outputPath)))
.use { outZip ->
ZipHelper.addFileToZip(outZip, newpipeDb.path, "newpipe.db")
ZipHelper.addFileToZip(outZip, fileLocator.db.path, "newpipe.db")

try {
ObjectOutputStream(FileOutputStream(newpipeSettings)).use { output ->
ObjectOutputStream(FileOutputStream(fileLocator.settings)).use { output ->
output.writeObject(preferences.all)
output.flush()
}
} catch (e: IOException) {
e.printStackTrace()
}

ZipHelper.addFileToZip(outZip, newpipeSettings.path, "newpipe.settings")
ZipHelper.addFileToZip(outZip, fileLocator.settings.path, "newpipe.settings")
}
}

fun deleteSettingsFile() {
fileLocator.settings.delete()
}

/**
* Tries to create database directory if it does not exist.
*
* @return Whether the directory exists afterwards.
*/
fun ensureDbDirectoryExists(): Boolean {
return fileLocator.dbDir.exists() || fileLocator.dbDir.mkdir()
}

fun extractDb(filePath: String): Boolean {
val success = ZipHelper.extractFileFromZip(filePath, fileLocator.db.path, "newpipe.db")
if (success) {
fileLocator.dbJournal.delete()
fileLocator.dbWal.delete()
fileLocator.dbShm.delete()
}

return success
}

fun extractSettings(filePath: String): Boolean {
return ZipHelper
.extractFileFromZip(filePath, fileLocator.settings.path, "newpipe.settings")
}

fun loadSharedPreferences(preferences: SharedPreferences) {
try {
val preferenceEditor = preferences.edit()

ObjectInputStream(FileInputStream(fileLocator.settings)).use { input ->
preferenceEditor.clear()
@Suppress("UNCHECKED_CAST")
val entries = input.readObject() as Map<String, *>
for ((key, value) in entries) {
when (value) {
is Boolean -> {
preferenceEditor.putBoolean(key, value)
}
is Float -> {
preferenceEditor.putFloat(key, value)
}
is Int -> {
preferenceEditor.putInt(key, value)
}
is Long -> {
preferenceEditor.putLong(key, value)
}
is String -> {
preferenceEditor.putString(key, value)
}
}
}
preferenceEditor.commit()
}
} catch (e: IOException) {
e.printStackTrace()
} catch (e: ClassNotFoundException) {
e.printStackTrace()
}
}
}
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
package org.schabi.newpipe.settings

import java.io.File

/**
* Locates specific files of NewPipe based on the home directory of the app.
*/
class NewPipeFileLocator(private val homeDir: File) {

val dbDir by lazy { File(homeDir, "/databases") }

val db by lazy { File(homeDir, "/databases/newpipe.db") }

val dbJournal by lazy { File(homeDir, "/databases/newpipe.db-journal") }

val dbShm by lazy { File(homeDir, "/databases/newpipe.db-shm") }

val dbWal by lazy { File(homeDir, "/databases/newpipe.db-wal") }

val settings by lazy { File(homeDir, "/databases/newpipe.settings") }
}
10 changes: 10 additions & 0 deletions app/src/main/java/org/schabi/newpipe/util/ZipHelper.java
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.zip.ZipEntry;
import java.util.zip.ZipFile;
import java.util.zip.ZipInputStream;
import java.util.zip.ZipOutputStream;

Expand Down Expand Up @@ -99,4 +101,12 @@ public static boolean extractFileFromZip(final String filePath, final String fil
return found;
}
}

public static boolean isValidZipFile(final String filePath) {
try (ZipFile ignored = new ZipFile(filePath)) {
return true;
} catch (final IOException ioe) {
return false;
}
}
}
Loading