mirror of
https://github.com/TwidereProject/Twidere-Android
synced 2025-01-31 17:04:59 +01:00
Fix #1251
This commit is contained in:
parent
1ecd3acdba
commit
aab797dae7
@ -25,6 +25,7 @@ import android.content.DialogInterface;
|
||||
import android.content.DialogInterface.OnClickListener;
|
||||
import android.content.DialogInterface.OnMultiChoiceClickListener;
|
||||
import android.content.DialogInterface.OnShowListener;
|
||||
import android.net.Uri;
|
||||
import android.os.Bundle;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
@ -157,7 +158,7 @@ public final class DataExportImportTypeSelectorDialogFragment extends BaseDialog
|
||||
final FragmentActivity a = getActivity();
|
||||
final Bundle args = getArguments();
|
||||
if (args == null) return;
|
||||
final String path = args.getString(EXTRA_PATH);
|
||||
final Uri path = args.getParcelable(EXTRA_PATH);
|
||||
if (a instanceof Callback) {
|
||||
((Callback) a).onPositiveButtonClicked(path, flags);
|
||||
}
|
||||
@ -171,7 +172,7 @@ public final class DataExportImportTypeSelectorDialogFragment extends BaseDialog
|
||||
}
|
||||
|
||||
public interface Callback extends ISupportDialogFragmentCallback {
|
||||
void onPositiveButtonClicked(String path, int flags);
|
||||
void onPositiveButtonClicked(Uri path, int flags);
|
||||
}
|
||||
|
||||
private static class Type {
|
||||
|
@ -28,12 +28,14 @@ import android.database.Cursor;
|
||||
import android.net.Uri;
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.WorkerThread;
|
||||
import androidx.documentfile.provider.DocumentFile;
|
||||
|
||||
import com.bluelinelabs.logansquare.LoganSquare;
|
||||
import com.fasterxml.jackson.core.JsonGenerator;
|
||||
import com.fasterxml.jackson.core.JsonParser;
|
||||
import com.fasterxml.jackson.core.JsonToken;
|
||||
|
||||
import org.mariotaku.commons.logansquare.LoganSquareMapperFinder;
|
||||
import org.mariotaku.library.exportablepreferences.PreferencesExporter;
|
||||
import org.mariotaku.library.exportablepreferences.annotation.PreferenceType;
|
||||
import org.mariotaku.library.objectcursor.ObjectCursor;
|
||||
@ -44,20 +46,29 @@ import org.mariotaku.twidere.model.Tab;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Filters;
|
||||
import org.mariotaku.twidere.provider.TwidereDataStore.Tabs;
|
||||
import org.mariotaku.twidere.util.content.ContentResolverUtils;
|
||||
import org.osmdroid.tileprovider.modules.ZipFileArchive;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
import java.io.OutputStreamWriter;
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Objects;
|
||||
import java.util.Set;
|
||||
import java.util.zip.GZIPInputStream;
|
||||
import java.util.zip.ZipEntry;
|
||||
import java.util.zip.ZipFile;
|
||||
import java.util.zip.ZipInputStream;
|
||||
import java.util.zip.ZipOutputStream;
|
||||
|
||||
import javax.annotation.Nonnull;
|
||||
|
||||
public class DataImportExportUtils implements Constants {
|
||||
|
||||
public static final String ENTRY_PREFERENCES = "preferences.json";
|
||||
@ -79,9 +90,8 @@ public class DataImportExportUtils implements Constants {
|
||||
| FLAG_HOST_MAPPING | FLAG_KEYBOARD_SHORTCUTS | FLAG_FILTERS | FLAG_TABS;
|
||||
|
||||
@WorkerThread
|
||||
public static void exportData(final Context context, @NonNull final File dst, final int flags) throws IOException {
|
||||
dst.delete();
|
||||
try (FileOutputStream fos = new FileOutputStream(dst);
|
||||
public static void exportData(final Context context, @NonNull final DocumentFile dst, final int flags) throws IOException {
|
||||
try (OutputStream fos = context.getContentResolver().openOutputStream(dst.getUri());
|
||||
ZipOutputStream zos = new ZipOutputStream(fos)) {
|
||||
if (hasFlag(flags, FLAG_PREFERENCES)) {
|
||||
exportSharedPreferencesData(zos, context, SHARED_PREFERENCES_NAME, ENTRY_PREFERENCES,
|
||||
@ -161,104 +171,122 @@ public class DataImportExportUtils implements Constants {
|
||||
}
|
||||
|
||||
@WorkerThread
|
||||
public static int getImportedSettingsFlags(@NonNull final File src) throws IOException {
|
||||
try (ZipFile zipFile = new ZipFile(src)) {
|
||||
public static int getImportedSettingsFlags(@NonNull final Context context, @NonNull final DocumentFile src) throws IOException {
|
||||
try (InputStream inputStream = context.getContentResolver().openInputStream(src.getUri());
|
||||
ZipInputStream zipInputStream = new ZipInputStream(inputStream)) {
|
||||
int flags = 0;
|
||||
if (zipFile.getEntry(ENTRY_PREFERENCES) != null) {
|
||||
List<String> entryNames = new ArrayList<>();
|
||||
ZipEntry entry = null;
|
||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||
entryNames.add(entry.getName());
|
||||
}
|
||||
if (entryNames.contains(ENTRY_PREFERENCES)) {
|
||||
flags |= FLAG_PREFERENCES;
|
||||
}
|
||||
if (zipFile.getEntry(ENTRY_NICKNAMES) != null) {
|
||||
if (entryNames.contains(ENTRY_NICKNAMES)) {
|
||||
flags |= FLAG_NICKNAMES;
|
||||
}
|
||||
if (zipFile.getEntry(ENTRY_USER_COLORS) != null) {
|
||||
if (entryNames.contains(ENTRY_USER_COLORS)) {
|
||||
flags |= FLAG_USER_COLORS;
|
||||
}
|
||||
if (zipFile.getEntry(ENTRY_HOST_MAPPING) != null) {
|
||||
if (entryNames.contains(ENTRY_HOST_MAPPING)) {
|
||||
flags |= FLAG_HOST_MAPPING;
|
||||
}
|
||||
if (zipFile.getEntry(ENTRY_KEYBOARD_SHORTCUTS) != null) {
|
||||
if (entryNames.contains(ENTRY_KEYBOARD_SHORTCUTS)) {
|
||||
flags |= FLAG_KEYBOARD_SHORTCUTS;
|
||||
}
|
||||
if (zipFile.getEntry(ENTRY_FILTERS) != null) {
|
||||
if (entryNames.contains(ENTRY_FILTERS)) {
|
||||
flags |= FLAG_FILTERS;
|
||||
}
|
||||
if (zipFile.getEntry(ENTRY_TABS) != null) {
|
||||
if (entryNames.contains(ENTRY_TABS)) {
|
||||
flags |= FLAG_TABS;
|
||||
}
|
||||
return flags;
|
||||
}
|
||||
}
|
||||
|
||||
public static void importData(final Context context, final File src, final int flags) throws IOException {
|
||||
public static void importData(final Context context, final DocumentFile src, final int flags) throws IOException {
|
||||
if (src == null) throw new FileNotFoundException();
|
||||
try (ZipFile zipFile = new ZipFile(src)) {
|
||||
if (hasFlag(flags, FLAG_PREFERENCES)) {
|
||||
importSharedPreferencesData(zipFile, context, SHARED_PREFERENCES_NAME, ENTRY_PREFERENCES,
|
||||
new PreferencesExporterStrategy(SharedPreferenceConstants.class));
|
||||
}
|
||||
if (hasFlag(flags, FLAG_NICKNAMES)) {
|
||||
importSharedPreferencesData(zipFile, context, USER_NICKNAME_PREFERENCES_NAME, ENTRY_NICKNAMES,
|
||||
ConvertToStringProcessStrategy.SINGLETON);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_USER_COLORS)) {
|
||||
importSharedPreferencesData(zipFile, context, USER_COLOR_PREFERENCES_NAME, ENTRY_USER_COLORS,
|
||||
ConvertToIntProcessStrategy.SINGLETON);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_HOST_MAPPING)) {
|
||||
importSharedPreferencesData(zipFile, context, HOST_MAPPING_PREFERENCES_NAME, ENTRY_HOST_MAPPING,
|
||||
ConvertToStringProcessStrategy.SINGLETON);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_KEYBOARD_SHORTCUTS)) {
|
||||
importSharedPreferencesData(zipFile, context, KEYBOARD_SHORTCUTS_PREFERENCES_NAME,
|
||||
ENTRY_KEYBOARD_SHORTCUTS, ConvertToStringProcessStrategy.SINGLETON);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_FILTERS)) {
|
||||
importItem(context, zipFile, ENTRY_FILTERS, FiltersData.class, new ContentResolverProcessStrategy<FiltersData>() {
|
||||
@Override
|
||||
public boolean importItem(ContentResolver cr, FiltersData filtersData) throws IOException {
|
||||
if (filtersData == null) return false;
|
||||
insertBase(cr, Filters.Keywords.CONTENT_URI, filtersData.getKeywords());
|
||||
insertBase(cr, Filters.Sources.CONTENT_URI, filtersData.getSources());
|
||||
insertBase(cr, Filters.Links.CONTENT_URI, filtersData.getLinks());
|
||||
insertUser(cr, Filters.Users.CONTENT_URI, filtersData.getUsers());
|
||||
try (InputStream inputStream = context.getContentResolver().openInputStream(src.getUri());
|
||||
ZipInputStream zipInputStream = new ZipInputStream(inputStream)
|
||||
) {
|
||||
ZipEntry entry = null;
|
||||
while ((entry = zipInputStream.getNextEntry()) != null) {
|
||||
StringBuilder stringBuilder = new StringBuilder();
|
||||
byte[] buffer = new byte[1024];
|
||||
int read = 0;
|
||||
while ((read = zipInputStream.read(buffer, 0, 1024)) >= 0) {
|
||||
stringBuilder.append(new String(buffer, 0, read));
|
||||
}
|
||||
String data = stringBuilder.toString();
|
||||
if (hasFlag(flags, FLAG_PREFERENCES)) {
|
||||
importSharedPreferencesData(entry, context, SHARED_PREFERENCES_NAME, ENTRY_PREFERENCES,
|
||||
new PreferencesExporterStrategy(SharedPreferenceConstants.class), data);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_NICKNAMES)) {
|
||||
importSharedPreferencesData(entry, context, USER_NICKNAME_PREFERENCES_NAME, ENTRY_NICKNAMES,
|
||||
ConvertToStringProcessStrategy.SINGLETON, data);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_USER_COLORS)) {
|
||||
importSharedPreferencesData(entry, context, USER_COLOR_PREFERENCES_NAME, ENTRY_USER_COLORS,
|
||||
ConvertToIntProcessStrategy.SINGLETON, data);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_HOST_MAPPING)) {
|
||||
importSharedPreferencesData(entry, context, HOST_MAPPING_PREFERENCES_NAME, ENTRY_HOST_MAPPING,
|
||||
ConvertToStringProcessStrategy.SINGLETON, data);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_KEYBOARD_SHORTCUTS)) {
|
||||
importSharedPreferencesData(entry, context, KEYBOARD_SHORTCUTS_PREFERENCES_NAME,
|
||||
ENTRY_KEYBOARD_SHORTCUTS, ConvertToStringProcessStrategy.SINGLETON, data);
|
||||
}
|
||||
if (hasFlag(flags, FLAG_FILTERS)) {
|
||||
importItem(context, entry, ENTRY_FILTERS, FiltersData.class, data, new ContentResolverProcessStrategy<FiltersData>() {
|
||||
@Override
|
||||
public boolean importItem(ContentResolver cr, FiltersData filtersData) throws IOException {
|
||||
if (filtersData == null) return false;
|
||||
insertBase(cr, Filters.Keywords.CONTENT_URI, filtersData.getKeywords());
|
||||
insertBase(cr, Filters.Sources.CONTENT_URI, filtersData.getSources());
|
||||
insertBase(cr, Filters.Links.CONTENT_URI, filtersData.getLinks());
|
||||
insertUser(cr, Filters.Users.CONTENT_URI, filtersData.getUsers());
|
||||
return true;
|
||||
}
|
||||
|
||||
void insertBase(ContentResolver cr, Uri uri, List<FiltersData.BaseItem> items) throws IOException {
|
||||
if (items == null) return;
|
||||
final ObjectCursor.ValuesCreator<FiltersData.BaseItem> baseItemCreator =
|
||||
ObjectCursor.valuesCreatorFrom(FiltersData.BaseItem.class);
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (FiltersData.BaseItem item : items) {
|
||||
values.add(baseItemCreator.create(item));
|
||||
}
|
||||
ContentResolverUtils.bulkInsert(cr, uri, values);
|
||||
}
|
||||
|
||||
void insertUser(ContentResolver cr, Uri uri, List<FiltersData.UserItem> items) throws IOException {
|
||||
if (items == null) return;
|
||||
final ObjectCursor.ValuesCreator<FiltersData.UserItem> userItemCreator =
|
||||
ObjectCursor.valuesCreatorFrom(FiltersData.UserItem.class);
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (FiltersData.UserItem item : items) {
|
||||
values.add(userItemCreator.create(item));
|
||||
}
|
||||
ContentResolverUtils.bulkInsert(cr, uri, values);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (hasFlag(flags, FLAG_TABS)) {
|
||||
final ObjectCursor.ValuesCreator<Tab> creator = ObjectCursor.valuesCreatorFrom(Tab.class);
|
||||
importItemsList(context, entry, ENTRY_TABS, Tab.class, data, (cr, items) -> {
|
||||
if (items == null) return false;
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (Tab item : items) {
|
||||
values.add(creator.create(item));
|
||||
}
|
||||
cr.delete(Tabs.CONTENT_URI, null, null);
|
||||
ContentResolverUtils.bulkInsert(cr, Tabs.CONTENT_URI, values);
|
||||
return true;
|
||||
}
|
||||
|
||||
void insertBase(ContentResolver cr, Uri uri, List<FiltersData.BaseItem> items) throws IOException {
|
||||
if (items == null) return;
|
||||
final ObjectCursor.ValuesCreator<FiltersData.BaseItem> baseItemCreator =
|
||||
ObjectCursor.valuesCreatorFrom(FiltersData.BaseItem.class);
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (FiltersData.BaseItem item : items) {
|
||||
values.add(baseItemCreator.create(item));
|
||||
}
|
||||
ContentResolverUtils.bulkInsert(cr, uri, values);
|
||||
}
|
||||
|
||||
void insertUser(ContentResolver cr, Uri uri, List<FiltersData.UserItem> items) throws IOException {
|
||||
if (items == null) return;
|
||||
final ObjectCursor.ValuesCreator<FiltersData.UserItem> userItemCreator =
|
||||
ObjectCursor.valuesCreatorFrom(FiltersData.UserItem.class);
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (FiltersData.UserItem item : items) {
|
||||
values.add(userItemCreator.create(item));
|
||||
}
|
||||
ContentResolverUtils.bulkInsert(cr, uri, values);
|
||||
}
|
||||
});
|
||||
}
|
||||
if (hasFlag(flags, FLAG_TABS)) {
|
||||
final ObjectCursor.ValuesCreator<Tab> creator = ObjectCursor.valuesCreatorFrom(Tab.class);
|
||||
importItemsList(context, zipFile, ENTRY_TABS, Tab.class, (cr, items) -> {
|
||||
if (items == null) return false;
|
||||
List<ContentValues> values = new ArrayList<>(items.size());
|
||||
for (Tab item : items) {
|
||||
values.add(creator.create(item));
|
||||
}
|
||||
cr.delete(Tabs.CONTENT_URI, null, null);
|
||||
ContentResolverUtils.bulkInsert(cr, Tabs.CONTENT_URI, values);
|
||||
return true;
|
||||
});
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -267,12 +295,12 @@ public class DataImportExportUtils implements Constants {
|
||||
return (flags & flag) != 0;
|
||||
}
|
||||
|
||||
private static void importSharedPreferencesData(@NonNull final ZipFile zipFile, @NonNull final Context context,
|
||||
private static void importSharedPreferencesData(@NonNull final ZipEntry entry, @NonNull final Context context,
|
||||
@NonNull final String preferencesName, @NonNull final String entryName,
|
||||
@NonNull final SharedPreferencesProcessStrategy strategy) throws IOException {
|
||||
final ZipEntry entry = zipFile.getEntry(entryName);
|
||||
if (entry == null) return;
|
||||
final JsonParser jsonParser = LoganSquare.JSON_FACTORY.createParser(zipFile.getInputStream(entry));
|
||||
@NonNull final SharedPreferencesProcessStrategy strategy,
|
||||
@NonNull final String data) throws IOException {
|
||||
if (!Objects.equals(entry.getName(), entryName)) return;
|
||||
final JsonParser jsonParser = LoganSquare.JSON_FACTORY.createParser(data);
|
||||
if (jsonParser.getCurrentToken() == null) {
|
||||
jsonParser.nextToken();
|
||||
}
|
||||
@ -300,14 +328,14 @@ public class DataImportExportUtils implements Constants {
|
||||
}
|
||||
|
||||
private static <T> void importItemsList(@NonNull final Context context,
|
||||
@NonNull final ZipFile zipFile,
|
||||
@NonNull final ZipEntry entry,
|
||||
@NonNull final String entryName,
|
||||
@NonNull final Class<T> itemCls,
|
||||
@NonNull final String data,
|
||||
@NonNull final ContentResolverProcessStrategy<List<T>> strategy)
|
||||
throws IOException {
|
||||
final ZipEntry entry = zipFile.getEntry(entryName);
|
||||
if (entry == null) return;
|
||||
List<T> itemsList = JsonSerializer.parseList(zipFile.getInputStream(entry), itemCls);
|
||||
if (!Objects.equals(entry.getName(), entryName)) return;
|
||||
List<T> itemsList = JsonSerializer.parseList(data, itemCls);
|
||||
strategy.importItem(context.getContentResolver(), itemsList);
|
||||
}
|
||||
|
||||
@ -317,19 +345,22 @@ public class DataImportExportUtils implements Constants {
|
||||
@NonNull final Class<T> itemCls,
|
||||
@NonNull final List<T> itemList) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(entryName));
|
||||
JsonSerializer.serialize(itemList, zos, itemCls);
|
||||
String json = LoganSquare.serialize(itemList);
|
||||
OutputStreamWriter writer = new OutputStreamWriter(zos);
|
||||
writer.write(json);
|
||||
writer.flush();
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
private static <T> void importItem(@NonNull final Context context,
|
||||
@NonNull final ZipFile zipFile,
|
||||
@NonNull final ZipEntry entry,
|
||||
@NonNull final String entryName,
|
||||
@NonNull final Class<T> itemCls,
|
||||
@NonNull final String data,
|
||||
@NonNull final ContentResolverProcessStrategy<T> strategy)
|
||||
throws IOException {
|
||||
final ZipEntry entry = zipFile.getEntry(entryName);
|
||||
if (entry == null) return;
|
||||
T item = JsonSerializer.parse(zipFile.getInputStream(entry), itemCls);
|
||||
if (!Objects.equals(entry.getName(), entryName)) return;
|
||||
T item = JsonSerializer.parse(data, itemCls);
|
||||
strategy.importItem(context.getContentResolver(), item);
|
||||
}
|
||||
|
||||
@ -339,7 +370,10 @@ public class DataImportExportUtils implements Constants {
|
||||
@NonNull final Class<T> itemCls,
|
||||
@NonNull final T item) throws IOException {
|
||||
zos.putNextEntry(new ZipEntry(entryName));
|
||||
JsonSerializer.serialize(item, zos, itemCls);
|
||||
String json = LoganSquare.serialize(item);
|
||||
OutputStreamWriter writer = new OutputStreamWriter(zos);
|
||||
writer.write(json);
|
||||
writer.flush();
|
||||
zos.closeEntry();
|
||||
}
|
||||
|
||||
|
@ -2,10 +2,12 @@ package org.mariotaku.twidere.activity
|
||||
|
||||
import android.app.Activity
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import android.util.Log
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import org.mariotaku.ktextension.dismissDialogFragment
|
||||
import org.mariotaku.twidere.Constants.*
|
||||
import org.mariotaku.twidere.R
|
||||
@ -13,7 +15,6 @@ import org.mariotaku.twidere.constant.IntentConstants
|
||||
import org.mariotaku.twidere.fragment.DataExportImportTypeSelectorDialogFragment
|
||||
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
||||
import org.mariotaku.twidere.util.DataImportExportUtils
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
import java.text.SimpleDateFormat
|
||||
import java.util.*
|
||||
@ -39,10 +40,10 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||
REQUEST_PICK_DIRECTORY -> {
|
||||
executeAfterFragmentResumed {
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
val path = data.data?.path
|
||||
val path = data.data
|
||||
val df = DataExportImportTypeSelectorDialogFragment()
|
||||
val args = Bundle()
|
||||
args.putString(EXTRA_PATH, path)
|
||||
args.putParcelable(EXTRA_PATH, path)
|
||||
args.putString(EXTRA_TITLE, getString(R.string.export_settings_type_dialog_title))
|
||||
df.arguments = args
|
||||
df.show(supportFragmentManager, "select_export_type")
|
||||
@ -58,13 +59,13 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
}
|
||||
|
||||
override fun onPositiveButtonClicked(path: String?, flags: Int) {
|
||||
override fun onPositiveButtonClicked(path: Uri?, flags: Int) {
|
||||
if (path == null || flags == 0) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
if (task == null || task!!.status != AsyncTask.Status.RUNNING) {
|
||||
task = ExportSettingsTask(this, path, flags)
|
||||
task = ExportSettingsTask(this, DocumentFile.fromTreeUri(this, path), flags)
|
||||
task!!.execute()
|
||||
}
|
||||
}
|
||||
@ -85,16 +86,18 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||
|
||||
internal class ExportSettingsTask(
|
||||
private val activity: DataExportActivity,
|
||||
private val path: String?,
|
||||
private val folder: DocumentFile?,
|
||||
private val flags: Int
|
||||
) : AsyncTask<Any, Any, Boolean>() {
|
||||
|
||||
override fun doInBackground(vararg params: Any): Boolean? {
|
||||
if (path == null) return false
|
||||
if (folder == null || !folder.isDirectory) return false
|
||||
val sdf = SimpleDateFormat("yyyy-MM-dd_HH-mm-ss", Locale.US)
|
||||
val fileName = String.format("Twidere_Settings_%s.zip", sdf.format(Date()))
|
||||
val file = File(path, fileName)
|
||||
file.delete()
|
||||
val file = folder.findFile(fileName) ?: folder.createFile("application/zip", fileName)
|
||||
?: return false
|
||||
// val file = File(folder, fileName)
|
||||
// file.delete()
|
||||
try {
|
||||
DataImportExportUtils.exportData(activity, file, flags)
|
||||
return true
|
||||
|
@ -1,17 +1,18 @@
|
||||
package org.mariotaku.twidere.activity
|
||||
|
||||
import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.AsyncTask
|
||||
import android.os.Bundle
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import android.util.Log
|
||||
import androidx.documentfile.provider.DocumentFile
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import org.mariotaku.ktextension.dismissDialogFragment
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants.*
|
||||
import org.mariotaku.twidere.fragment.DataExportImportTypeSelectorDialogFragment
|
||||
import org.mariotaku.twidere.fragment.ProgressDialogFragment
|
||||
import org.mariotaku.twidere.util.DataImportExportUtils
|
||||
import java.io.File
|
||||
import java.io.IOException
|
||||
|
||||
class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFragment.Callback {
|
||||
@ -37,9 +38,9 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||
REQUEST_PICK_FILE -> {
|
||||
resumeFragmentsRunnable = Runnable {
|
||||
if (resultCode == RESULT_OK && data != null) {
|
||||
val path = data.data?.path
|
||||
val path = data.data!!
|
||||
if (openImportTypeTask == null || openImportTypeTask!!.status != AsyncTask.Status.RUNNING) {
|
||||
openImportTypeTask = OpenImportTypeTask(this@DataImportActivity, path)
|
||||
openImportTypeTask = OpenImportTypeTask(this@DataImportActivity, DocumentFile.fromSingleUri(this, path))
|
||||
openImportTypeTask!!.execute()
|
||||
}
|
||||
} else {
|
||||
@ -62,13 +63,13 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||
}
|
||||
}
|
||||
|
||||
override fun onPositiveButtonClicked(path: String?, flags: Int) {
|
||||
override fun onPositiveButtonClicked(path: Uri?, flags: Int) {
|
||||
if (path == null || flags == 0) {
|
||||
finish()
|
||||
return
|
||||
}
|
||||
if (importSettingsTask == null || importSettingsTask!!.status != AsyncTask.Status.RUNNING) {
|
||||
importSettingsTask = ImportSettingsTask(this, path, flags)
|
||||
importSettingsTask = ImportSettingsTask(this, DocumentFile.fromSingleUri(this, path), flags)
|
||||
importSettingsTask!!.execute()
|
||||
}
|
||||
}
|
||||
@ -89,13 +90,14 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||
|
||||
internal class ImportSettingsTask(
|
||||
private val activity: DataImportActivity,
|
||||
private val path: String?,
|
||||
private val file: DocumentFile?,
|
||||
private val flags: Int
|
||||
) : AsyncTask<Any, Any, Boolean>() {
|
||||
|
||||
override fun doInBackground(vararg params: Any): Boolean? {
|
||||
if (path == null) return false
|
||||
val file = File(path)
|
||||
if (file == null) {
|
||||
return false
|
||||
}
|
||||
if (!file.isFile) return false
|
||||
try {
|
||||
DataImportExportUtils.importData(activity, file, flags)
|
||||
@ -131,14 +133,15 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||
|
||||
}
|
||||
|
||||
internal class OpenImportTypeTask(private val activity: DataImportActivity, private val path: String?) : AsyncTask<Any, Any, Int>() {
|
||||
internal class OpenImportTypeTask(private val activity: DataImportActivity, private val file: DocumentFile?) : AsyncTask<Any, Any, Int>() {
|
||||
|
||||
override fun doInBackground(vararg params: Any): Int? {
|
||||
if (path == null) return 0
|
||||
val file = File(path)
|
||||
if (file == null) {
|
||||
return 0
|
||||
}
|
||||
if (!file.isFile) return 0
|
||||
try {
|
||||
return DataImportExportUtils.getImportedSettingsFlags(file)
|
||||
return DataImportExportUtils.getImportedSettingsFlags(activity, file)
|
||||
} catch (e: IOException) {
|
||||
return 0
|
||||
}
|
||||
@ -151,7 +154,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
|
||||
}
|
||||
val df = DataExportImportTypeSelectorDialogFragment()
|
||||
val args = Bundle()
|
||||
args.putString(EXTRA_PATH, path)
|
||||
args.putParcelable(EXTRA_PATH, file?.uri)
|
||||
args.putString(EXTRA_TITLE, activity.getString(R.string.import_settings_type_dialog_title))
|
||||
if (flags != null) {
|
||||
args.putInt(EXTRA_FLAGS, flags)
|
||||
|
@ -24,22 +24,22 @@ import android.content.Intent
|
||||
import android.net.Uri
|
||||
import android.os.Build
|
||||
import android.os.Bundle
|
||||
import android.os.Environment.getExternalStorageDirectory
|
||||
import android.widget.Toast
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import android.widget.Toast
|
||||
import org.mariotaku.ktextension.Bundle
|
||||
import org.mariotaku.ktextension.checkAllSelfPermissionsGranted
|
||||
import org.mariotaku.ktextension.set
|
||||
import org.mariotaku.twidere.R
|
||||
import org.mariotaku.twidere.TwidereConstants.REQUEST_REQUEST_PERMISSIONS
|
||||
import org.mariotaku.twidere.constant.IntentConstants.*
|
||||
import org.mariotaku.twidere.constant.IntentConstants.INTENT_ACTION_PICK_DIRECTORY
|
||||
import org.mariotaku.twidere.constant.IntentConstants.INTENT_ACTION_PICK_FILE
|
||||
import org.mariotaku.twidere.fragment.FileSelectorDialogFragment
|
||||
import java.io.File
|
||||
import android.Manifest.permission as AndroidPermissions
|
||||
|
||||
class FileSelectorActivity : BaseActivity(), FileSelectorDialogFragment.Callback {
|
||||
|
||||
private val PICKER_REQUEST_CODE: Int = 54837
|
||||
|
||||
override fun onCancelled(df: DialogFragment) {
|
||||
if (!isFinishing) {
|
||||
finish()
|
||||
@ -101,15 +101,41 @@ class FileSelectorActivity : BaseActivity(), FileSelectorDialogFragment.Callback
|
||||
finish()
|
||||
}
|
||||
|
||||
private fun showPickFileDialog() {
|
||||
val initialDirectory = intent?.data?.path?.let(::File) ?: getExternalStorageDirectory() ?: File("/")
|
||||
val f = FileSelectorDialogFragment()
|
||||
f.arguments = Bundle {
|
||||
this[EXTRA_ACTION] = intent.action
|
||||
this[EXTRA_PATH] = initialDirectory.absolutePath
|
||||
this[EXTRA_FILE_EXTENSIONS] = intent.getStringArrayExtra(EXTRA_FILE_EXTENSIONS)
|
||||
override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
|
||||
super.onActivityResult(requestCode, resultCode, data)
|
||||
if (requestCode == PICKER_REQUEST_CODE && resultCode == Activity.RESULT_OK && data != null) {
|
||||
setResult(Activity.RESULT_OK, Intent().also { it.data = data.data })
|
||||
finish()
|
||||
} else {
|
||||
if (!isFinishing) {
|
||||
finish()
|
||||
}
|
||||
}
|
||||
f.show(supportFragmentManager, "select_file")
|
||||
}
|
||||
|
||||
private fun showPickFileDialog() {
|
||||
Intent().apply {
|
||||
if (intent.action == INTENT_ACTION_PICK_FILE) {
|
||||
action = Intent.ACTION_GET_CONTENT
|
||||
type = "*/*"
|
||||
} else if (intent.action == INTENT_ACTION_PICK_DIRECTORY) {
|
||||
action = Intent.ACTION_OPEN_DOCUMENT_TREE
|
||||
}
|
||||
}.also {
|
||||
startActivityForResult(
|
||||
Intent.createChooser(it, getString(R.string.pick_file)),
|
||||
PICKER_REQUEST_CODE
|
||||
)
|
||||
}
|
||||
|
||||
// val initialDirectory = intent?.data?.path?.let(::File) ?: getExternalStorageDirectory() ?: File("/")
|
||||
// val f = FileSelectorDialogFragment()
|
||||
// f.arguments = Bundle {
|
||||
// this[EXTRA_ACTION] = intent.action
|
||||
// this[EXTRA_PATH] = initialDirectory.absolutePath
|
||||
// this[EXTRA_FILE_EXTENSIONS] = intent.getStringArrayExtra(EXTRA_FILE_EXTENSIONS)
|
||||
// }
|
||||
// f.show(supportFragmentManager, "select_file")
|
||||
}
|
||||
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user