Merge pull request #1432 from dvalter/fix/Android-R-import-export

Fix import/export for Android R+
This commit is contained in:
Tlaster 2021-04-28 22:41:50 -07:00 committed by GitHub
commit f1ff56b8f5
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
3 changed files with 49 additions and 33 deletions

View File

@ -84,8 +84,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 DocumentFile dst, final int flags) throws IOException {
try (OutputStream fos = context.getContentResolver().openOutputStream(dst.getUri());
public static void exportData(final Context context, @NonNull final Uri dst, final int flags) throws IOException {
try (OutputStream fos = context.getContentResolver().openOutputStream(dst);
ZipOutputStream zos = new ZipOutputStream(fos)) {
if (hasFlag(flags, FLAG_PREFERENCES)) {
exportSharedPreferencesData(zos, context, SHARED_PREFERENCES_NAME, ENTRY_PREFERENCES,
@ -199,9 +199,9 @@ public class DataImportExportUtils implements Constants {
}
}
public static void importData(final Context context, final DocumentFile src, final int flags) throws IOException {
public static void importData(final Context context, final Uri src, final int flags) throws IOException {
if (src == null) throw new FileNotFoundException();
try (InputStream inputStream = context.getContentResolver().openInputStream(src.getUri());
try (InputStream inputStream = context.getContentResolver().openInputStream(src);
ZipInputStream zipInputStream = new ZipInputStream(inputStream)
) {
ZipEntry entry;

View File

@ -6,6 +6,7 @@ import android.net.Uri
import android.os.AsyncTask
import android.os.Build
import android.os.Bundle
import android.provider.DocumentsContract
import android.util.Log
import androidx.documentfile.provider.DocumentFile
import androidx.fragment.app.DialogFragment
@ -17,7 +18,6 @@ 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.*
@ -67,12 +67,7 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
return
}
if (task == null || task!!.status != AsyncTask.Status.RUNNING) {
val folder = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
DocumentFile.fromTreeUri(this, path)
} else {
DocumentFile.fromFile(File(path.path))
}
task = ExportSettingsTask(this, folder, flags)
task = ExportSettingsTask(this, path, flags)
task!!.execute()
}
}
@ -85,30 +80,53 @@ class DataExportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
val intent = Intent(this, FileSelectorActivity::class.java)
intent.action = IntentConstants.INTENT_ACTION_PICK_DIRECTORY
val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val i = Intent(Intent.ACTION_OPEN_DOCUMENT_TREE)
i.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION
or Intent.FLAG_GRANT_PREFIX_URI_PERMISSION
or Intent.FLAG_GRANT_WRITE_URI_PERMISSION)
i
} else {
val i = Intent(this, FileSelectorActivity::class.java)
i.action = IntentConstants.INTENT_ACTION_PICK_DIRECTORY
i
}
startActivityForResult(intent, REQUEST_PICK_DIRECTORY)
}
}
internal class ExportSettingsTask(
private val activity: DataExportActivity,
private val folder: DocumentFile?,
private val folderUri: Uri?,
private val flags: Int
) : AsyncTask<Any, Any, Boolean>() {
override fun doInBackground(vararg params: Any): Boolean? {
if (folder == null || !folder.isDirectory) return false
if (folderUri == null) 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 = folder.findFile(fileName) ?: folder.createFile("application/zip", fileName)
?: return false
// val file = File(folder, fileName)
// file.delete()
return try {
DataImportExportUtils.exportData(activity, file, flags)
val createdDocumentUri = (if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val docId = DocumentsContract.getTreeDocumentId(folderUri)
val dirUri = DocumentsContract.buildDocumentUriUsingTree(folderUri, docId)
DocumentsContract.createDocument(
activity.contentResolver,
dirUri,
"application/zip",
fileName)
} else {
val folder = DocumentFile.fromFile(File(folderUri.path!!))
val file = folder.findFile(fileName)
?: folder.createFile("application/zip", fileName) ?: return false
file.uri
})
?: return false
DataImportExportUtils.exportData(activity, createdDocumentUri, flags)
true
} catch (e: IOException) {
} catch (e: Throwable) {
Log.w(LOGTAG, e)
false
}

View File

@ -76,12 +76,7 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
return
}
if (importSettingsTask == null || importSettingsTask!!.status != AsyncTask.Status.RUNNING) {
val file = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
DocumentFile.fromSingleUri(this, path)
} else {
DocumentFile.fromFile(File(path.path))
}
importSettingsTask = ImportSettingsTask(this, file, flags)
importSettingsTask = ImportSettingsTask(this, path, flags)
importSettingsTask!!.execute()
}
}
@ -94,25 +89,28 @@ class DataImportActivity : BaseActivity(), DataExportImportTypeSelectorDialogFra
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
if (savedInstanceState == null) {
val intent = Intent(this, FileSelectorActivity::class.java)
intent.action = INTENT_ACTION_PICK_FILE
val intent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
val i = Intent(Intent.ACTION_OPEN_DOCUMENT)
i.type = "*/*"
i
} else {
val i = Intent(this, FileSelectorActivity::class.java)
i.action = INTENT_ACTION_PICK_FILE
i
}
startActivityForResult(intent, REQUEST_PICK_FILE)
}
}
internal class ImportSettingsTask(
private val activity: DataImportActivity,
private val file: DocumentFile?,
private val uri: Uri?,
private val flags: Int
) : AsyncTask<Any, Any, Boolean>() {
override fun doInBackground(vararg params: Any): Boolean? {
if (file == null) {
return false
}
if (!file.isFile) return false
return try {
DataImportExportUtils.importData(activity, file, flags)
DataImportExportUtils.importData(activity, uri, flags)
true
} catch (e: IOException) {
Log.w(LOGTAG, e)