Skip to content

Commit

Permalink
Merge pull request TeamNewPipe/NewPipe#5225 from XiangRongLin/extract…
Browse files Browse the repository at this point in the history
…_settings_import

Extract settings import
  • Loading branch information
Stypox authored and tossj committed Apr 19, 2021
1 parent 4b4b7ba commit 52358b5
Show file tree
Hide file tree
Showing 9 changed files with 268 additions and 126 deletions.
4 changes: 3 additions & 1 deletion app/build.gradle
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
Expand Up @@ -32,14 +32,9 @@
import org.schabi.newpipelegacy.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.newpipelegacy.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
Expand Up @@ -3,22 +3,14 @@ package org.schabi.newpipelegacy.settings
import android.content.SharedPreferences
import org.schabi.newpipelegacy.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()
}
}
}
@@ -0,0 +1,21 @@
package org.schabi.newpipelegacy.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/newpipelegacy/util/ZipHelper.java
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;
}
}
}

0 comments on commit 52358b5

Please sign in to comment.