diff options
4 files changed, 104 insertions, 32 deletions
diff --git a/src/main/java/de/pixart/messenger/services/ExportBackupService.java b/src/main/java/de/pixart/messenger/services/ExportBackupService.java index 5ffae41a9..90bb25452 100644 --- a/src/main/java/de/pixart/messenger/services/ExportBackupService.java +++ b/src/main/java/de/pixart/messenger/services/ExportBackupService.java @@ -2,6 +2,7 @@ package de.pixart.messenger.services; import android.app.Notification; import android.app.NotificationManager; +import android.app.PendingIntent; import android.app.Service; import android.content.Context; import android.content.Intent; @@ -9,6 +10,8 @@ import android.content.SharedPreferences; import android.database.Cursor; import android.database.DatabaseUtils; import android.database.sqlite.SQLiteDatabase; +import android.net.Uri; +import android.os.Bundle; import android.os.IBinder; import android.os.PowerManager; import android.preference.PreferenceManager; @@ -73,6 +76,30 @@ public class ExportBackupService extends Service { private List<Account> mAccounts; private NotificationManager notificationManager; + private static List<Intent> getPossibleFileOpenIntents(final Context context, final String path) { + + //http://www.openintents.org/action/android-intent-action-view/file-directory + //do not use 'vnd.android.document/directory' since this will trigger system file manager + Intent openIntent = new Intent(Intent.ACTION_VIEW); + openIntent.addCategory(Intent.CATEGORY_DEFAULT); + if (Compatibility.runsAndTargetsTwentyFour(context)) { + openIntent.setType("resource/folder"); + } else { + openIntent.setDataAndType(Uri.parse("file://" + path), "resource/folder"); + } + openIntent.putExtra("org.openintents.extra.ABSOLUTE_PATH", path); + + Intent amazeIntent = new Intent(Intent.ACTION_VIEW); + amazeIntent.setDataAndType(Uri.parse("com.amaze.filemanager:" + path), "resource/folder"); + + //will open a file manager at root and user can navigate themselves + Intent systemFallBack = new Intent(Intent.ACTION_VIEW); + systemFallBack.addCategory(Intent.CATEGORY_DEFAULT); + systemFallBack.setData(Uri.parse("content://com.android.externalstorage.documents/root/primary")); + + return Arrays.asList(openIntent, amazeIntent, systemFallBack); + } + private static void accountExport(SQLiteDatabase db, String uuid, PrintWriter writer) { final StringBuilder builder = new StringBuilder(); final Cursor accountCursor = db.query(Account.TABLENAME, null, Account.UUID + "=?", new String[]{uuid}, null, null, null); @@ -197,9 +224,19 @@ public class ExportBackupService extends Service { public int onStartCommand(Intent intent, int flags, int startId) { if (running.compareAndSet(false, true)) { new Thread(() -> { - export(); + final Bundle extras = intent.getExtras(); + boolean notify = false; + if (extras != null & extras.containsKey("NOTIFY_ON_BACKUP_COMPLETE")) { + notify = extras.getBoolean("NOTIFY_ON_BACKUP_COMPLETE"); + } + final boolean success = export(); stopForeground(true); running.set(false); + if (success) { + notifySuccess(notify); + } else { + notifyError(); + } WakeLockHelper.release(wakeLock); stopSelf(); }).start(); @@ -232,7 +269,7 @@ public class ExportBackupService extends Service { } } - private void export() { + private boolean export() { wakeLock.acquire(15 * 60 * 1000L /*15 minutes*/); NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); mBuilder.setContentTitle(getString(R.string.notification_create_backup_title)) @@ -291,11 +328,48 @@ public class ExportBackupService extends Service { Log.d(Config.LOGTAG, "written backup to " + file.getAbsoluteFile()); count++; } + return true; } catch (Exception e) { Log.d(Config.LOGTAG, "unable to create backup ", e); + return false; } } + private void notifySuccess(final boolean notify) { + if (!notify) { + return; + } + final String path = FileBackend.getBackupDirectory(); + PendingIntent pendingIntent = null; + for (Intent intent : getPossibleFileOpenIntents(this, path)) { + if (intent.resolveActivityInfo(getPackageManager(), 0) != null) { + pendingIntent = PendingIntent.getActivity(this, 189, intent, PendingIntent.FLAG_UPDATE_CURRENT); + break; + } + } + + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); + mBuilder.setContentTitle(getString(R.string.notification_backup_created_title)) + .setContentText(getString(R.string.notification_backup_created_subtitle, path)) + .setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.notification_backup_created_subtitle, FileBackend.getBackupDirectory()))) + .setAutoCancel(true) + .setContentIntent(pendingIntent) + .setSmallIcon(R.drawable.ic_archive_white_24dp); + notificationManager.notify(NOTIFICATION_ID, mBuilder.build()); + } + + private void notifyError() { + final String path = FileBackend.getBackupDirectory(); + + NotificationCompat.Builder mBuilder = new NotificationCompat.Builder(getBaseContext(), "backup"); + mBuilder.setContentTitle(getString(R.string.notification_backup_failed_title)) + .setContentText(getString(R.string.notification_backup_failed_subtitle, path)) + .setStyle(new NotificationCompat.BigTextStyle().bigText(getString(R.string.notification_backup_failed_subtitle, FileBackend.getBackupDirectory()))) + .setAutoCancel(true) + .setSmallIcon(R.drawable.ic_warning_white_24dp); + notificationManager.notify(NOTIFICATION_ID, mBuilder.build()); + } + private void writeToFile(Conversation conversation) { Jid accountJid = resolveAccountUuid(conversation.getAccountUuid()); Jid contactJid = conversation.getJid(); diff --git a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java index a7076f4c5..7d6f32dd8 100644 --- a/src/main/java/de/pixart/messenger/ui/SettingsActivity.java +++ b/src/main/java/de/pixart/messenger/ui/SettingsActivity.java @@ -253,7 +253,7 @@ public class SettingsActivity extends XmppActivity implements createBackupPreference.setSummary(getString(R.string.pref_create_backup_summary, FileBackend.getBackupDirectory())); createBackupPreference.setOnPreferenceClickListener(preference -> { if (hasStoragePermission(REQUEST_CREATE_BACKUP)) { - createBackup(); + createBackup(true); } return true; }); @@ -475,7 +475,7 @@ public class SettingsActivity extends XmppActivity implements if (grantResults.length > 0) { if (grantResults[0] == PackageManager.PERMISSION_GRANTED) { if (requestCode == REQUEST_CREATE_BACKUP) { - createBackup(); + createBackup(true); } } else { Toast.makeText(this, R.string.no_storage_permission, Toast.LENGTH_SHORT).show(); @@ -483,8 +483,10 @@ public class SettingsActivity extends XmppActivity implements } } - private void createBackup() { - ContextCompat.startForegroundService(this, new Intent(this, ExportBackupService.class)); + private void createBackup(boolean notify) { + final Intent intent = new Intent(this, ExportBackupService.class); + intent.putExtra("NOTIFY_ON_BACKUP_COMPLETE", notify); + ContextCompat.startForegroundService(this, intent); } private void displayToast(final String msg) { @@ -501,32 +503,6 @@ public class SettingsActivity extends XmppActivity implements public void refreshUiReal() { recreate(); - //handleMultiAccountChanges(); - } - - private void handleMultiAccountChanges() { - multiAccountPreference = mSettingsFragment.findPreference("enable_multi_accounts"); - if (multiAccountPreference != null) { - //check if password = null - final SharedPreferences multiaccount_prefs = getApplicationContext().getSharedPreferences(USE_MULTI_ACCOUNTS, Context.MODE_PRIVATE); - if (multiaccount_prefs != null && multiaccount_prefs.getString("BackupPW", null) == null) { - Log.d(Config.LOGTAG, "uncheck multiaccount because password = null"); - if (multiAccountPreference != null) { - ((CheckBoxPreference) multiAccountPreference).setChecked(false); - } - } - //if multiAccountDisabled reset password - final Preference enableMultiAccountsPreference = mSettingsFragment.findPreference("enable_multi_accounts"); - if (enableMultiAccountsPreference != null && !isMultiAccountChecked) { - SharedPreferences.Editor editor = multiaccount_prefs.edit(); - editor.putString("BackupPW", null); - if (editor.commit()) { - Log.d(Config.LOGTAG, "resetting multiaccount password because multiaccount = unchecked"); - } else { - Log.d(Config.LOGTAG, "resetting multiaccount password failed"); - } - } - } } private int getNumberOfAccounts() { diff --git a/src/main/java/de/pixart/messenger/utils/Compatibility.java b/src/main/java/de/pixart/messenger/utils/Compatibility.java index c8922e18b..728c6298a 100644 --- a/src/main/java/de/pixart/messenger/utils/Compatibility.java +++ b/src/main/java/de/pixart/messenger/utils/Compatibility.java @@ -42,6 +42,10 @@ public class Compatibility { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.O; } + public static boolean runsTwentyFour() { + return Build.VERSION.SDK_INT >= Build.VERSION_CODES.N; + } + public static boolean twentyEight() { return Build.VERSION.SDK_INT >= Build.VERSION_CODES.P; } @@ -66,10 +70,24 @@ public class Compatibility { } } + private static boolean targetsTwentyFour(Context context) { + try { + final PackageManager packageManager = context.getPackageManager(); + final ApplicationInfo applicationInfo = packageManager.getApplicationInfo(context.getPackageName(), 0); + return applicationInfo == null || applicationInfo.targetSdkVersion >= 24; + } catch (PackageManager.NameNotFoundException | RuntimeException e) { + return true; //when in doubt… + } + } + public static boolean runsAndTargetsTwentySix(Context context) { return runsTwentySix() && targetsTwentySix(context); } + public static boolean runsAndTargetsTwentyFour(Context context) { + return runsTwentyFour() && targetsTwentyFour(context); + } + public static boolean keepForegroundService(Context context) { return runsTwentySix() || getBooleanPreference(context, SettingsActivity.SHOW_FOREGROUND_SERVICE, R.bool.show_foreground_service); } diff --git a/src/main/res/values/strings.xml b/src/main/res/values/strings.xml index 0003bdd34..dee4f8be5 100644 --- a/src/main/res/values/strings.xml +++ b/src/main/res/values/strings.xml @@ -881,4 +881,8 @@ <string name="action_end_conversation_channel">Leave channel</string> <string name="autojoin_channel">Automatically join this channel</string> <string name="no_attachments">There are no attachments</string> + <string name="notification_backup_created_title">Backup was successful</string> + <string name="notification_backup_created_subtitle">The backup files were stored in %s</string> + <string name="notification_backup_failed_title">Backup failed</string> + <string name="notification_backup_failed_subtitle">The backup files could not be stored in %s</string> </resources> |