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