package org.thoughtcrime.securesms; import android.Manifest; import android.annotation.SuppressLint; import android.app.ProgressDialog; import android.content.Context; import android.content.Intent; import android.os.AsyncTask; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.v4.app.Fragment; import android.support.v7.app.AlertDialog; import android.util.Log; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.Toast; import org.thoughtcrime.securesms.database.NoExternalStorageException; import org.thoughtcrime.securesms.database.PlaintextBackupImporter; import org.thoughtcrime.securesms.permissions.Permissions; import org.thoughtcrime.securesms.service.ApplicationMigrationService; import java.io.IOException; public class ImportExportFragment extends Fragment { @SuppressWarnings("unused") private static final String TAG = ImportExportFragment.class.getSimpleName(); private static final int SUCCESS = 0; private static final int NO_SD_CARD = 1; private static final int ERROR_IO = 2; private ProgressDialog progressDialog; @Override public void onCreate(Bundle bundle) { super.onCreate(bundle); } @Override public View onCreateView(@NonNull LayoutInflater inflater, ViewGroup container, Bundle bundle) { View layout = inflater.inflate(R.layout.import_export_fragment, container, false); View importSmsView = layout.findViewById(R.id.import_sms ); View importPlaintextView = layout.findViewById(R.id.import_plaintext_backup); importSmsView.setOnClickListener(v -> handleImportSms()); importPlaintextView.setOnClickListener(v -> handleImportPlaintextBackup()); return layout; } @Override public void onDestroy() { super.onDestroy(); if (progressDialog != null && progressDialog.isShowing()) { progressDialog.dismiss(); progressDialog = null; } } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { Permissions.onRequestPermissionsResult(this, requestCode, permissions, grantResults); } @SuppressWarnings("CodeBlock2Expr") private void handleImportSms() { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setIconAttribute(R.attr.dialog_info_icon); builder.setTitle(getActivity().getString(R.string.ImportFragment_import_system_sms_database)); builder.setMessage(getActivity().getString(R.string.ImportFragment_this_will_import_messages_from_the_system)); builder.setPositiveButton(getActivity().getString(R.string.ImportFragment_import), (dialog, which) -> { Permissions.with(this) .request(Manifest.permission.READ_SMS) .ifNecessary() .withPermanentDenialDialog(getString(R.string.ImportExportFragment_signal_needs_the_sms_permission_in_order_to_import_sms_messages)) .onAllGranted(() -> { Intent intent = new Intent(getActivity(), ApplicationMigrationService.class); intent.setAction(ApplicationMigrationService.MIGRATE_DATABASE); getActivity().startService(intent); Intent nextIntent = new Intent(getActivity(), ConversationListActivity.class); Intent activityIntent = new Intent(getActivity(), DatabaseMigrationActivity.class); activityIntent.putExtra("next_intent", nextIntent); getActivity().startActivity(activityIntent); }) .onAnyDenied(() -> Toast.makeText(getContext(), R.string.ImportExportFragment_signal_needs_the_sms_permission_in_order_to_import_sms_messages_toast, Toast.LENGTH_LONG).show()) .execute(); }); builder.setNegativeButton(getActivity().getString(R.string.ImportFragment_cancel), null); builder.show(); } @SuppressWarnings("CodeBlock2Expr") @SuppressLint("InlinedApi") private void handleImportPlaintextBackup() { AlertDialog.Builder builder = new AlertDialog.Builder(getActivity()); builder.setIconAttribute(R.attr.dialog_alert_icon); builder.setTitle(getActivity().getString(R.string.ImportFragment_import_plaintext_backup)); builder.setMessage(getActivity().getString(R.string.ImportFragment_this_will_import_messages_from_a_plaintext_backup)); builder.setPositiveButton(getActivity().getString(R.string.ImportFragment_import), (dialog, which) -> { Permissions.with(ImportExportFragment.this) .request(Manifest.permission.WRITE_EXTERNAL_STORAGE, Manifest.permission.READ_EXTERNAL_STORAGE) .ifNecessary() .withPermanentDenialDialog(getString(R.string.ImportExportFragment_signal_needs_the_storage_permission_in_order_to_read_from_external_storage_but_it_has_been_permanently_denied)) .onAllGranted(() -> new ImportPlaintextBackupTask().executeOnExecutor(AsyncTask.THREAD_POOL_EXECUTOR)) .onAnyDenied(() -> Toast.makeText(getContext(), R.string.ImportExportFragment_signal_needs_the_storage_permission_in_order_to_read_from_external_storage, Toast.LENGTH_LONG).show()) .execute(); }); builder.setNegativeButton(getActivity().getString(R.string.ImportFragment_cancel), null); builder.show(); } @SuppressLint("StaticFieldLeak") private class ImportPlaintextBackupTask extends AsyncTask { @Override protected void onPreExecute() { progressDialog = ProgressDialog.show(getActivity(), getActivity().getString(R.string.ImportFragment_importing), getActivity().getString(R.string.ImportFragment_import_plaintext_backup_elipse), true, false); } protected void onPostExecute(Integer result) { Context context = getActivity(); if (progressDialog != null) progressDialog.dismiss(); if (context == null) return; switch (result) { case NO_SD_CARD: Toast.makeText(context, context.getString(R.string.ImportFragment_no_plaintext_backup_found), Toast.LENGTH_LONG).show(); break; case ERROR_IO: Toast.makeText(context, context.getString(R.string.ImportFragment_error_importing_backup), Toast.LENGTH_LONG).show(); break; case SUCCESS: Toast.makeText(context, context.getString(R.string.ImportFragment_import_complete), Toast.LENGTH_LONG).show(); break; } } @Override protected Integer doInBackground(Void... params) { try { PlaintextBackupImporter.importPlaintextFromSd(getActivity()); return SUCCESS; } catch (NoExternalStorageException e) { Log.w("ImportFragment", e); return NO_SD_CARD; } catch (IOException e) { Log.w("ImportFragment", e); return ERROR_IO; } } } }