SettingsActivity.java

  1package eu.siacs.conversations.ui;
  2
  3import android.app.FragmentManager;
  4import android.content.Context;
  5import android.content.DialogInterface;
  6import android.content.Intent;
  7import android.content.SharedPreferences;
  8import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
  9import android.content.pm.PackageManager;
 10import android.net.Uri;
 11import android.os.Build;
 12import android.os.Bundle;
 13import android.os.storage.StorageManager;
 14import android.preference.CheckBoxPreference;
 15import android.preference.ListPreference;
 16import android.preference.Preference;
 17import android.preference.PreferenceCategory;
 18import android.preference.PreferenceManager;
 19import android.preference.PreferenceScreen;
 20import android.provider.MediaStore;
 21import android.util.Log;
 22import android.widget.Toast;
 23
 24import androidx.annotation.NonNull;
 25import androidx.appcompat.app.AlertDialog;
 26import androidx.core.content.ContextCompat;
 27
 28import com.cheogram.android.DownloadDefaultStickers;
 29
 30import com.google.common.base.Strings;
 31import com.google.common.collect.ImmutableList;
 32import com.google.common.collect.Lists;
 33
 34import java.io.File;
 35import java.security.KeyStoreException;
 36import java.util.ArrayList;
 37import java.util.Arrays;
 38import java.util.Collections;
 39import java.util.List;
 40
 41import eu.siacs.conversations.Config;
 42import eu.siacs.conversations.R;
 43import eu.siacs.conversations.crypto.OmemoSetting;
 44import eu.siacs.conversations.entities.Account;
 45import eu.siacs.conversations.entities.Contact;
 46import eu.siacs.conversations.persistance.FileBackend;
 47import eu.siacs.conversations.services.ExportBackupService;
 48import eu.siacs.conversations.services.MemorizingTrustManager;
 49import eu.siacs.conversations.services.QuickConversationsService;
 50import eu.siacs.conversations.services.UnifiedPushDistributor;
 51import eu.siacs.conversations.ui.util.SettingsUtils;
 52import eu.siacs.conversations.ui.util.StyledAttributes;
 53import eu.siacs.conversations.utils.GeoHelper;
 54import eu.siacs.conversations.utils.ThemeHelper;
 55import eu.siacs.conversations.utils.TimeFrameUtils;
 56import eu.siacs.conversations.xmpp.Jid;
 57
 58public class SettingsActivity extends XmppActivity implements OnSharedPreferenceChangeListener {
 59
 60    public static final String KEEP_FOREGROUND_SERVICE = "enable_foreground_service";
 61    public static final String AWAY_WHEN_SCREEN_IS_OFF = "away_when_screen_off";
 62    public static final String TREAT_VIBRATE_AS_SILENT = "treat_vibrate_as_silent";
 63    public static final String DND_ON_SILENT_MODE = "dnd_on_silent_mode";
 64    public static final String MANUALLY_CHANGE_PRESENCE = "manually_change_presence";
 65    public static final String BLIND_TRUST_BEFORE_VERIFICATION = "btbv";
 66    public static final String AUTOMATIC_MESSAGE_DELETION = "automatic_message_deletion";
 67    public static final String BROADCAST_LAST_ACTIVITY = "last_activity";
 68    public static final String THEME = "theme";
 69    public static final String SHOW_DYNAMIC_TAGS = "show_dynamic_tags";
 70    public static final String OMEMO_SETTING = "omemo";
 71    public static final String PREVENT_SCREENSHOTS = "prevent_screenshots";
 72
 73    public static final int REQUEST_CREATE_BACKUP = 0xbf8701;
 74    public static final int REQUEST_DOWNLOAD_STICKERS = 0xbf8702;
 75
 76    private SettingsFragment mSettingsFragment;
 77
 78    @Override
 79    protected void onCreate(Bundle savedInstanceState) {
 80        super.onCreate(savedInstanceState);
 81        setContentView(R.layout.activity_settings);
 82        FragmentManager fm = getFragmentManager();
 83        mSettingsFragment = (SettingsFragment) fm.findFragmentById(R.id.settings_content);
 84        if (mSettingsFragment == null
 85                || !mSettingsFragment.getClass().equals(SettingsFragment.class)) {
 86            mSettingsFragment = new SettingsFragment();
 87            fm.beginTransaction().replace(R.id.settings_content, mSettingsFragment).commit();
 88        }
 89        mSettingsFragment.setActivityIntent(getIntent());
 90        this.mTheme = findTheme();
 91        setTheme(this.mTheme);
 92        ThemeHelper.applyCustomColors(this);
 93        getWindow()
 94                .getDecorView()
 95                .setBackgroundColor(
 96                        StyledAttributes.getColor(this, R.attr.color_background_primary));
 97        setSupportActionBar(findViewById(R.id.toolbar));
 98        configureActionBar(getSupportActionBar());
 99    }
100
101    @Override
102    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
103        if (data == null || data.getData() == null) return;
104
105        SharedPreferences p = PreferenceManager.getDefaultSharedPreferences(this);
106        p.edit().putString("sticker_directory", data.getData().toString()).commit();
107    }
108
109    @Override
110    void onBackendConnected() {
111        boolean diallerIntegrationPossible = false;
112
113        if (Build.VERSION.SDK_INT >= 23) {
114            outer:
115            for (Account account : xmppConnectionService.getAccounts()) {
116                for (Contact contact : account.getRoster().getContacts()) {
117                    if (contact.getPresences().anyIdentity("gateway", "pstn")) {
118                        diallerIntegrationPossible = true;
119                        break outer;
120                    }
121                }
122            }
123        }
124        if (!diallerIntegrationPossible) {
125            PreferenceCategory cat = (PreferenceCategory) mSettingsFragment.findPreference("notification_category");
126            Preference pref = mSettingsFragment.findPreference("dialler_integration_incoming");
127            if (cat != null && pref != null) cat.removePreference(pref);
128        }
129        final Preference accountPreference =
130                mSettingsFragment.findPreference(UnifiedPushDistributor.PREFERENCE_ACCOUNT);
131        reconfigureUpAccountPreference(accountPreference);
132    }
133
134    private void reconfigureUpAccountPreference(final Preference preference) {
135        final ListPreference listPreference;
136        if (preference instanceof ListPreference) {
137            listPreference = (ListPreference) preference;
138        } else {
139            return;
140        }
141        final List<CharSequence> accounts =
142                ImmutableList.copyOf(
143                        Lists.transform(
144                                xmppConnectionService.getAccounts(),
145                                a -> a.getJid().asBareJid().toEscapedString()));
146        final ImmutableList.Builder<CharSequence> entries = new ImmutableList.Builder<>();
147        final ImmutableList.Builder<CharSequence> entryValues = new ImmutableList.Builder<>();
148        entries.add(getString(R.string.no_account_deactivated));
149        entryValues.add("none");
150        entries.addAll(accounts);
151        entryValues.addAll(accounts);
152        listPreference.setEntries(entries.build().toArray(new CharSequence[0]));
153        listPreference.setEntryValues(entryValues.build().toArray(new CharSequence[0]));
154        if (!accounts.contains(listPreference.getValue())) {
155            listPreference.setValue("none");
156        }
157    }
158
159    @Override
160    public void onStart() {
161        super.onStart();
162        PreferenceManager.getDefaultSharedPreferences(this)
163                .registerOnSharedPreferenceChangeListener(this);
164
165        changeOmemoSettingSummary();
166
167        if (QuickConversationsService.isQuicksy()
168                || Strings.isNullOrEmpty(Config.CHANNEL_DISCOVERY)) {
169            final PreferenceCategory groupChats =
170                    (PreferenceCategory) mSettingsFragment.findPreference("group_chats");
171            final Preference channelDiscoveryMethod =
172                    mSettingsFragment.findPreference("channel_discovery_method");
173            if (groupChats != null && channelDiscoveryMethod != null) {
174                groupChats.removePreference(channelDiscoveryMethod);
175            }
176        }
177
178        if (QuickConversationsService.isQuicksy()) {
179            final PreferenceCategory connectionOptions =
180                    (PreferenceCategory) mSettingsFragment.findPreference("connection_options");
181            PreferenceScreen expert = (PreferenceScreen) mSettingsFragment.findPreference("expert");
182            if (connectionOptions != null) {
183                expert.removePreference(connectionOptions);
184            }
185        }
186
187        PreferenceScreen mainPreferenceScreen =
188                (PreferenceScreen) mSettingsFragment.findPreference("main_screen");
189
190        PreferenceCategory attachmentsCategory =
191                (PreferenceCategory) mSettingsFragment.findPreference("attachments");
192        CheckBoxPreference locationPlugin =
193                (CheckBoxPreference) mSettingsFragment.findPreference("use_share_location_plugin");
194        if (attachmentsCategory != null && locationPlugin != null) {
195            if (!GeoHelper.isLocationPluginInstalled(this)) {
196                attachmentsCategory.removePreference(locationPlugin);
197            }
198        }
199
200        // this feature is only available on Huawei Android 6.
201        PreferenceScreen huaweiPreferenceScreen =
202                (PreferenceScreen) mSettingsFragment.findPreference("huawei");
203        if (huaweiPreferenceScreen != null) {
204            Intent intent = huaweiPreferenceScreen.getIntent();
205            // remove when Api version is above M (Version 6.0) or if the intent is not callable
206            if (Build.VERSION.SDK_INT > Build.VERSION_CODES.M || !isCallable(intent)) {
207                PreferenceCategory generalCategory =
208                        (PreferenceCategory) mSettingsFragment.findPreference("general");
209                generalCategory.removePreference(huaweiPreferenceScreen);
210                if (generalCategory.getPreferenceCount() == 0) {
211                    if (mainPreferenceScreen != null) {
212                        mainPreferenceScreen.removePreference(generalCategory);
213                    }
214                }
215            }
216        }
217
218        ListPreference automaticMessageDeletionList =
219                (ListPreference) mSettingsFragment.findPreference(AUTOMATIC_MESSAGE_DELETION);
220        if (automaticMessageDeletionList != null) {
221            final int[] choices =
222                    getResources().getIntArray(R.array.automatic_message_deletion_values);
223            CharSequence[] entries = new CharSequence[choices.length];
224            CharSequence[] entryValues = new CharSequence[choices.length];
225            for (int i = 0; i < choices.length; ++i) {
226                entryValues[i] = String.valueOf(choices[i]);
227                if (choices[i] == 0) {
228                    entries[i] = getString(R.string.never);
229                } else {
230                    entries[i] = TimeFrameUtils.resolve(this, 1000L * choices[i]);
231                }
232            }
233            automaticMessageDeletionList.setEntries(entries);
234            automaticMessageDeletionList.setEntryValues(entryValues);
235        }
236
237        boolean removeLocation =
238                new Intent("eu.siacs.conversations.location.request")
239                                .resolveActivity(getPackageManager())
240                        == null;
241        boolean removeVoice =
242                new Intent(MediaStore.Audio.Media.RECORD_SOUND_ACTION)
243                                .resolveActivity(getPackageManager())
244                        == null;
245
246        ListPreference quickAction =
247                (ListPreference) mSettingsFragment.findPreference("quick_action");
248        if (quickAction != null && (removeLocation || removeVoice)) {
249            ArrayList<CharSequence> entries =
250                    new ArrayList<>(Arrays.asList(quickAction.getEntries()));
251            ArrayList<CharSequence> entryValues =
252                    new ArrayList<>(Arrays.asList(quickAction.getEntryValues()));
253            int index = entryValues.indexOf("location");
254            if (index > 0 && removeLocation) {
255                entries.remove(index);
256                entryValues.remove(index);
257            }
258            index = entryValues.indexOf("voice");
259            if (index > 0 && removeVoice) {
260                entries.remove(index);
261                entryValues.remove(index);
262            }
263            quickAction.setEntries(entries.toArray(new CharSequence[entries.size()]));
264            quickAction.setEntryValues(entryValues.toArray(new CharSequence[entryValues.size()]));
265        }
266
267        final Preference removeCertsPreference =
268                mSettingsFragment.findPreference("remove_trusted_certificates");
269        if (removeCertsPreference != null) {
270            removeCertsPreference.setOnPreferenceClickListener(
271                    preference -> {
272                        final MemorizingTrustManager mtm =
273                                xmppConnectionService.getMemorizingTrustManager();
274                        final ArrayList<String> aliases = Collections.list(mtm.getCertificates());
275                        if (aliases.size() == 0) {
276                            displayToast(getString(R.string.toast_no_trusted_certs));
277                            return true;
278                        }
279                        final ArrayList<Integer> selectedItems = new ArrayList<>();
280                        final AlertDialog.Builder dialogBuilder =
281                                new AlertDialog.Builder(SettingsActivity.this);
282                        dialogBuilder.setTitle(
283                                getResources().getString(R.string.dialog_manage_certs_title));
284                        dialogBuilder.setMultiChoiceItems(
285                                aliases.toArray(new CharSequence[aliases.size()]),
286                                null,
287                                (dialog, indexSelected, isChecked) -> {
288                                    if (isChecked) {
289                                        selectedItems.add(indexSelected);
290                                    } else if (selectedItems.contains(indexSelected)) {
291                                        selectedItems.remove(Integer.valueOf(indexSelected));
292                                    }
293                                    ((AlertDialog) dialog)
294                                            .getButton(DialogInterface.BUTTON_POSITIVE)
295                                            .setEnabled(selectedItems.size() > 0);
296                                });
297
298                        dialogBuilder.setPositiveButton(
299                                getResources()
300                                        .getString(R.string.dialog_manage_certs_positivebutton),
301                                (dialog, which) -> {
302                                    int count = selectedItems.size();
303                                    if (count > 0) {
304                                        for (int i = 0; i < count; i++) {
305                                            try {
306                                                Integer item =
307                                                        Integer.valueOf(
308                                                                selectedItems.get(i).toString());
309                                                String alias = aliases.get(item);
310                                                mtm.deleteCertificate(alias);
311                                            } catch (KeyStoreException e) {
312                                                e.printStackTrace();
313                                                displayToast("Error: " + e.getLocalizedMessage());
314                                            }
315                                        }
316                                        if (xmppConnectionServiceBound) {
317                                            reconnectAccounts();
318                                        }
319                                        displayToast(
320                                                getResources()
321                                                        .getQuantityString(
322                                                                R.plurals.toast_delete_certificates,
323                                                                count,
324                                                                count));
325                                    }
326                                });
327                        dialogBuilder.setNegativeButton(
328                                getResources()
329                                        .getString(R.string.dialog_manage_certs_negativebutton),
330                                null);
331                        AlertDialog removeCertsDialog = dialogBuilder.create();
332                        removeCertsDialog.show();
333                        removeCertsDialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
334                        return true;
335                    });
336        }
337
338        final Preference createBackupPreference = mSettingsFragment.findPreference("create_backup");
339        if (createBackupPreference != null) {
340            createBackupPreference.setSummary(
341                    getString(
342                            R.string.pref_create_backup_summary,
343                            FileBackend.getBackupDirectory(this).getAbsolutePath()));
344            createBackupPreference.setOnPreferenceClickListener(
345                    preference -> {
346                        if (hasStoragePermission(REQUEST_CREATE_BACKUP)) {
347                            createBackup();
348                        }
349                        return true;
350                    });
351        }
352
353        if (Config.ONLY_INTERNAL_STORAGE) {
354            final Preference cleanCachePreference = mSettingsFragment.findPreference("clean_cache");
355            if (cleanCachePreference != null) {
356                cleanCachePreference.setOnPreferenceClickListener(preference -> cleanCache());
357            }
358
359            final Preference cleanPrivateStoragePreference =
360                    mSettingsFragment.findPreference("clean_private_storage");
361            if (cleanPrivateStoragePreference != null) {
362                cleanPrivateStoragePreference.setOnPreferenceClickListener(
363                        preference -> cleanPrivateStorage());
364            }
365        }
366
367        final Preference deleteOmemoPreference =
368                mSettingsFragment.findPreference("delete_omemo_identities");
369        if (deleteOmemoPreference != null) {
370            deleteOmemoPreference.setOnPreferenceClickListener(
371                    preference -> deleteOmemoIdentities());
372        }
373        if (Config.omemoOnly()) {
374            final PreferenceCategory privacyCategory =
375                    (PreferenceCategory) mSettingsFragment.findPreference("privacy");
376            final Preference omemoPreference =mSettingsFragment.findPreference(OMEMO_SETTING);
377            if (omemoPreference != null) {
378                privacyCategory.removePreference(omemoPreference);
379            }
380        }
381
382        final Preference stickerDir = mSettingsFragment.findPreference("sticker_directory");
383        if (stickerDir != null) {
384            if (Build.VERSION.SDK_INT >= 24) {
385                stickerDir.setOnPreferenceClickListener((p) -> {
386                    Intent intent = ((StorageManager) getSystemService(Context.STORAGE_SERVICE)).getPrimaryStorageVolume().createOpenDocumentTreeIntent();
387                    startActivityForResult(Intent.createChooser(intent, "Choose sticker location"), 0);
388                    return true;
389                });
390            } else {
391                PreferenceCategory expertMedia = (PreferenceCategory) mSettingsFragment.findPreference("expert_media");
392                expertMedia.removePreference(stickerDir);
393            }
394        }
395
396        final Preference downloadDefaultStickers = mSettingsFragment.findPreference("download_default_stickers");
397        if (downloadDefaultStickers != null) {
398            downloadDefaultStickers.setOnPreferenceClickListener(
399                    preference -> {
400                        if (hasStoragePermission(REQUEST_DOWNLOAD_STICKERS)) {
401                            downloadStickers();
402                        }
403                        return true;
404                    });
405        }
406
407        final Preference clearBlockedMedia = mSettingsFragment.findPreference("clear_blocked_media");
408        if (clearBlockedMedia != null) {
409            clearBlockedMedia.setOnPreferenceClickListener((p) -> {
410                xmppConnectionService.clearBlockedMedia();
411                displayToast("Blocked media will be displayed again.");
412                return true;
413            });
414        }
415
416        final String theTheme = PreferenceManager.getDefaultSharedPreferences(this).getString(THEME, "");
417        if (Build.VERSION.SDK_INT < 30 || !theTheme.equals("custom")) {
418            final PreferenceCategory uiCategory = (PreferenceCategory) mSettingsFragment.findPreference("ui");
419            final Preference customTheme = mSettingsFragment.findPreference("custom_theme");
420            if (customTheme != null) uiCategory.removePreference(customTheme);
421        }
422    }
423
424    private void changeOmemoSettingSummary() {
425        final ListPreference omemoPreference =
426                (ListPreference) mSettingsFragment.findPreference(OMEMO_SETTING);
427        if (omemoPreference == null) {
428            return;
429        }
430        final String value = omemoPreference.getValue();
431        switch (value) {
432            case "always":
433                omemoPreference.setSummary(R.string.pref_omemo_setting_summary_always);
434                break;
435            case "default_on":
436                omemoPreference.setSummary(R.string.pref_omemo_setting_summary_default_on);
437                break;
438            case "default_off":
439                omemoPreference.setSummary(R.string.pref_omemo_setting_summary_default_off);
440                break;
441        }
442    }
443
444    private boolean isCallable(final Intent i) {
445        return i != null
446                && getPackageManager()
447                                .queryIntentActivities(i, PackageManager.MATCH_DEFAULT_ONLY)
448                                .size()
449                        > 0;
450    }
451
452    private boolean cleanCache() {
453        Intent intent = new Intent(android.provider.Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
454        intent.setData(Uri.parse("package:" + getPackageName()));
455        startActivity(intent);
456        return true;
457    }
458
459    private boolean cleanPrivateStorage() {
460        for (String type : Arrays.asList("Images", "Videos", "Files", "Recordings")) {
461            cleanPrivateFiles(type);
462        }
463        return true;
464    }
465
466    private void cleanPrivateFiles(final String type) {
467        try {
468            File dir = new File(getFilesDir().getAbsolutePath(), "/" + type + "/");
469            File[] array = dir.listFiles();
470            if (array != null) {
471                for (int b = 0; b < array.length; b++) {
472                    String name = array[b].getName().toLowerCase();
473                    if (name.equals(".nomedia")) {
474                        continue;
475                    }
476                    if (array[b].isFile()) {
477                        array[b].delete();
478                    }
479                }
480            }
481        } catch (Throwable e) {
482            Log.e("CleanCache", e.toString());
483        }
484    }
485
486    private boolean deleteOmemoIdentities() {
487        AlertDialog.Builder builder = new AlertDialog.Builder(this);
488        builder.setTitle(R.string.pref_delete_omemo_identities);
489        final List<CharSequence> accounts = new ArrayList<>();
490        for (Account account : xmppConnectionService.getAccounts()) {
491            if (account.isEnabled()) {
492                accounts.add(account.getJid().asBareJid().toString());
493            }
494        }
495        final boolean[] checkedItems = new boolean[accounts.size()];
496        builder.setMultiChoiceItems(
497                accounts.toArray(new CharSequence[accounts.size()]),
498                checkedItems,
499                (dialog, which, isChecked) -> {
500                    checkedItems[which] = isChecked;
501                    final AlertDialog alertDialog = (AlertDialog) dialog;
502                    for (boolean item : checkedItems) {
503                        if (item) {
504                            alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(true);
505                            return;
506                        }
507                    }
508                    alertDialog.getButton(DialogInterface.BUTTON_POSITIVE).setEnabled(false);
509                });
510        builder.setNegativeButton(R.string.cancel, null);
511        builder.setPositiveButton(
512                R.string.delete_selected_keys,
513                (dialog, which) -> {
514                    for (int i = 0; i < checkedItems.length; ++i) {
515                        if (checkedItems[i]) {
516                            try {
517                                Jid jid = Jid.of(accounts.get(i).toString());
518                                Account account = xmppConnectionService.findAccountByJid(jid);
519                                if (account != null) {
520                                    account.getAxolotlService().regenerateKeys(true);
521                                }
522                            } catch (IllegalArgumentException e) {
523                                //
524                            }
525                        }
526                    }
527                });
528        AlertDialog dialog = builder.create();
529        dialog.show();
530        dialog.getButton(AlertDialog.BUTTON_POSITIVE).setEnabled(false);
531        return true;
532    }
533
534    @Override
535    public void onStop() {
536        super.onStop();
537        PreferenceManager.getDefaultSharedPreferences(this)
538                .unregisterOnSharedPreferenceChangeListener(this);
539    }
540
541    @Override
542    public void onSharedPreferenceChanged(SharedPreferences preferences, String name) {
543        final List<String> resendPresence =
544                Arrays.asList(
545                        "confirm_messages",
546                        DND_ON_SILENT_MODE,
547                        AWAY_WHEN_SCREEN_IS_OFF,
548                        "allow_message_correction",
549                        TREAT_VIBRATE_AS_SILENT,
550                        MANUALLY_CHANGE_PRESENCE,
551                        BROADCAST_LAST_ACTIVITY);
552        if (name.equals(OMEMO_SETTING)) {
553            OmemoSetting.load(this, preferences);
554            changeOmemoSettingSummary();
555        } else if (name.equals(KEEP_FOREGROUND_SERVICE)) {
556            xmppConnectionService.toggleForegroundService();
557        } else if (resendPresence.contains(name)) {
558            if (xmppConnectionServiceBound) {
559                if (name.equals(AWAY_WHEN_SCREEN_IS_OFF) || name.equals(MANUALLY_CHANGE_PRESENCE)) {
560                    xmppConnectionService.toggleScreenEventReceiver();
561                }
562                xmppConnectionService.refreshAllPresences();
563            }
564        } else if (name.equals("dont_trust_system_cas")) {
565            xmppConnectionService.updateMemorizingTrustmanager();
566            reconnectAccounts();
567        } else if (name.equals("use_tor")) {
568            if (preferences.getBoolean(name, false)) {
569                displayToast(getString(R.string.audio_video_disabled_tor));
570            }
571            reconnectAccounts();
572            xmppConnectionService.reinitializeMuclumbusService();
573        } else if (name.equals(AUTOMATIC_MESSAGE_DELETION)) {
574            xmppConnectionService.expireOldMessages(true);
575        } else if (name.equals(THEME) || name.equals("custom_theme_primary") || name.equals("custom_theme_primary_dark") || name.equals("custom_theme_accent") || name.equals("custom_theme_dark")) {
576            final int theme = findTheme();
577            xmppConnectionService.setTheme(theme);
578            ThemeHelper.applyCustomColors(xmppConnectionService);
579            recreate();
580        } else if (name.equals(PREVENT_SCREENSHOTS)) {
581            SettingsUtils.applyScreenshotPreventionSetting(this);
582        } else if (UnifiedPushDistributor.PREFERENCES.contains(name)) {
583            if (xmppConnectionService.reconfigurePushDistributor()) {
584                xmppConnectionService.renewUnifiedPushEndpoints();
585            }
586        }
587    }
588
589    @Override
590    public void onResume() {
591        super.onResume();
592        SettingsUtils.applyScreenshotPreventionSetting(this);
593    }
594
595    @Override
596    public void onRequestPermissionsResult(
597            int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
598        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
599        if (grantResults.length > 0)
600            if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
601                if (requestCode == REQUEST_CREATE_BACKUP) {
602                    createBackup();
603                }
604                if (requestCode == REQUEST_DOWNLOAD_STICKERS) {
605                    downloadStickers();
606                }
607            } else {
608                Toast.makeText(
609                                this,
610                                getString(
611                                        R.string.no_storage_permission,
612                                        getString(R.string.app_name)),
613                                Toast.LENGTH_SHORT)
614                        .show();
615            }
616    }
617
618    private void createBackup() {
619        new AlertDialog.Builder(this)
620            .setTitle("Create Backup")
621            .setMessage("Export extra Cheogram-only data (backup will not import into other apps then)?")
622            .setPositiveButton(R.string.yes, (dialog, whichButton) -> {
623                createBackup(true);
624            })
625            .setNegativeButton(R.string.no, (dialog, whichButton) -> {
626                createBackup(false);
627            }).show();
628    }
629
630    private void createBackup(boolean withCheogramDb) {
631        Intent intent = new Intent(this, ExportBackupService.class);
632        intent.putExtra("cheogram_db", withCheogramDb);
633        ContextCompat.startForegroundService(this, intent);
634        final AlertDialog.Builder builder = new AlertDialog.Builder(this);
635        builder.setMessage(R.string.backup_started_message);
636        builder.setPositiveButton(R.string.ok, null);
637        builder.create().show();
638    }
639
640    private void downloadStickers() {
641        Intent intent = new Intent(this, DownloadDefaultStickers.class);
642        ContextCompat.startForegroundService(this, intent);
643        displayToast("Sticker download started");
644    }
645
646    private void displayToast(final String msg) {
647        runOnUiThread(() -> Toast.makeText(SettingsActivity.this, msg, Toast.LENGTH_LONG).show());
648    }
649
650    private void reconnectAccounts() {
651        for (Account account : xmppConnectionService.getAccounts()) {
652            if (account.isEnabled()) {
653                xmppConnectionService.reconnectAccountInBackground(account);
654            }
655        }
656    }
657
658    public void refreshUiReal() {
659        // nothing to do. This Activity doesn't implement any listeners
660    }
661}