@@ -23,6 +23,8 @@ import androidx.core.app.NotificationManagerCompat;
import com.google.common.base.Charsets;
import com.google.common.base.Stopwatch;
import com.google.common.io.CountingInputStream;
+import com.google.common.util.concurrent.Futures;
+import com.google.common.util.concurrent.ListenableFuture;
import com.google.gson.stream.JsonReader;
import com.google.gson.stream.JsonToken;
@@ -64,6 +66,8 @@ import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.WeakHashMap;
+import java.util.concurrent.ExecutorService;
+import java.util.concurrent.Executors;
import java.util.concurrent.atomic.AtomicBoolean;
import java.util.regex.Pattern;
import java.util.zip.GZIPInputStream;
@@ -73,6 +77,9 @@ import javax.crypto.BadPaddingException;
public class ImportBackupService extends Service {
+ private static final ExecutorService BACKUP_FILE_READER_EXECUTOR =
+ Executors.newSingleThreadExecutor();
+
private static final int NOTIFICATION_ID = 21;
private static final AtomicBoolean running = new AtomicBoolean(false);
private final ImportBackupServiceBinder binder = new ImportBackupServiceBinder();
@@ -433,6 +440,10 @@ public class ImportBackupService extends Service {
}
}
+ public static ListenableFuture<BackupFile> read(final Context context, final Uri uri) {
+ return Futures.submit(() -> BackupFile.read(context, uri), BACKUP_FILE_READER_EXECUTOR);
+ }
+
@Override
public IBinder onBind(Intent intent) {
return this.binder;
@@ -475,7 +486,7 @@ public class ImportBackupService extends Service {
throw new FileNotFoundException();
}
final DataInputStream dataInputStream = new DataInputStream(inputStream);
- BackupFileHeader backupFileHeader = BackupFileHeader.read(dataInputStream);
+ final BackupFileHeader backupFileHeader = BackupFileHeader.read(dataInputStream);
inputStream.close();
return new BackupFile(uri, backupFileHeader);
}
@@ -19,6 +19,7 @@ import android.view.View;
import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
+import androidx.annotation.NonNull;
import androidx.appcompat.app.AlertDialog;
import androidx.core.content.ContextCompat;
import androidx.databinding.DataBindingUtil;
@@ -27,6 +28,8 @@ import com.google.android.material.dialog.MaterialAlertDialogBuilder;
import com.google.android.material.snackbar.Snackbar;
import com.google.common.collect.ImmutableList;
import com.google.common.collect.ImmutableSet;
+import com.google.common.util.concurrent.FutureCallback;
+import com.google.common.util.concurrent.Futures;
import eu.siacs.conversations.Config;
import eu.siacs.conversations.R;
@@ -34,6 +37,7 @@ import eu.siacs.conversations.databinding.ActivityImportBackupBinding;
import eu.siacs.conversations.databinding.DialogEnterPasswordBinding;
import eu.siacs.conversations.services.ImportBackupService;
import eu.siacs.conversations.ui.adapter.BackupFileAdapter;
+import eu.siacs.conversations.ui.util.MainThreadExecutor;
import eu.siacs.conversations.utils.BackupFileHeader;
import java.io.IOException;
@@ -182,21 +186,36 @@ public class ImportBackupActivity extends ActionBarActivity
}
private void openBackupFileFromUri(final Uri uri, final boolean finishOnCancel) {
- try {
- final ImportBackupService.BackupFile backupFile =
- ImportBackupService.BackupFile.read(this, uri);
- showEnterPasswordDialog(backupFile, finishOnCancel);
- } catch (final BackupFileHeader.OutdatedBackupFileVersion e) {
+ final var backupFileFuture = ImportBackupService.read(this, uri);
+ Futures.addCallback(
+ backupFileFuture,
+ new FutureCallback<>() {
+ @Override
+ public void onSuccess(final ImportBackupService.BackupFile backupFile) {
+ showEnterPasswordDialog(backupFile, finishOnCancel);
+ }
+
+ @Override
+ public void onFailure(@NonNull final Throwable throwable) {
+ Log.d(Config.LOGTAG, "could not open backup file " + uri, throwable);
+ showBackupThrowable(throwable);
+ }
+ },
+ MainThreadExecutor.getInstance());
+ }
+
+ private void showBackupThrowable(final Throwable throwable) {
+ if (throwable instanceof BackupFileHeader.OutdatedBackupFileVersion) {
Snackbar.make(
binding.coordinator,
R.string.outdated_backup_file_format,
Snackbar.LENGTH_LONG)
.show();
- } catch (final IOException | IllegalArgumentException e) {
- Log.d(Config.LOGTAG, "unable to open backup file " + uri, e);
+ } else if (throwable instanceof IOException
+ || throwable instanceof IllegalArgumentException) {
Snackbar.make(binding.coordinator, R.string.not_a_backup_file, Snackbar.LENGTH_LONG)
.show();
- } catch (final SecurityException e) {
+ } else if (throwable instanceof SecurityException e) {
Snackbar.make(
binding.coordinator,
R.string.sharing_application_not_grant_permission,
@@ -243,16 +262,7 @@ public class ImportBackupActivity extends ActionBarActivity
getString(R.string.please_enter_password));
return;
}
- final Uri uri = backupFile.getUri();
- Intent intent = new Intent(this, ImportBackupService.class);
- intent.setAction(Intent.ACTION_SEND);
- intent.putExtra("password", password);
- if ("file".equals(uri.getScheme())) {
- intent.putExtra("file", uri.getPath());
- } else {
- intent.setData(uri);
- intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
- }
+ final Intent intent = getIntent(backupFile, password);
setLoadingState(true);
ContextCompat.startForegroundService(this, intent);
d.dismiss();
@@ -261,6 +271,21 @@ public class ImportBackupActivity extends ActionBarActivity
dialog.show();
}
+ @NonNull
+ private Intent getIntent(ImportBackupService.BackupFile backupFile, String password) {
+ final Uri uri = backupFile.getUri();
+ Intent intent = new Intent(this, ImportBackupService.class);
+ intent.setAction(Intent.ACTION_SEND);
+ intent.putExtra("password", password);
+ if ("file".equals(uri.getScheme())) {
+ intent.putExtra("file", uri.getPath());
+ } else {
+ intent.setData(uri);
+ intent.addFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION);
+ }
+ return intent;
+ }
+
private void setLoadingState(final boolean loadingState) {
binding.coordinator.setVisibility(loadingState ? View.GONE : View.VISIBLE);
binding.inProgress.setVisibility(loadingState ? View.VISIBLE : View.GONE);