NotificationsSettingsFragment.java

  1package eu.siacs.conversations.ui.fragment.settings;
  2
  3import android.app.NotificationChannel;
  4import android.media.RingtoneManager;
  5import android.net.Uri;
  6import android.os.Build;
  7import android.os.Bundle;
  8import android.util.Log;
  9
 10import androidx.activity.result.ActivityResultLauncher;
 11import androidx.annotation.NonNull;
 12import androidx.annotation.Nullable;
 13import androidx.preference.Preference;
 14
 15import com.google.common.base.Optional;
 16
 17import eu.siacs.conversations.AppSettings;
 18import eu.siacs.conversations.Config;
 19import eu.siacs.conversations.R;
 20import eu.siacs.conversations.services.NotificationService;
 21import eu.siacs.conversations.ui.activity.result.PickRingtone;
 22import eu.siacs.conversations.utils.Compatibility;
 23
 24public class NotificationsSettingsFragment extends XmppPreferenceFragment {
 25
 26    private final ActivityResultLauncher<Uri> pickNotificationToneLauncher =
 27            registerForActivityResult(
 28                    new PickRingtone(RingtoneManager.TYPE_NOTIFICATION),
 29                    result -> {
 30                        if (result == null) {
 31                            // do nothing. user aborted
 32                            return;
 33                        }
 34                        final Uri uri = PickRingtone.noneToNull(result);
 35                        appSettings().setNotificationTone(uri);
 36                        Log.i(Config.LOGTAG, "User set notification tone to " + uri);
 37                    });
 38    private final ActivityResultLauncher<Uri> pickRingtoneLauncher =
 39            registerForActivityResult(
 40                    new PickRingtone(RingtoneManager.TYPE_RINGTONE),
 41                    result -> {
 42                        if (result == null) {
 43                            // do nothing. user aborted
 44                            return;
 45                        }
 46                        final Uri uri = PickRingtone.noneToNull(result);
 47                        appSettings().setRingtone(uri);
 48                        Log.i(Config.LOGTAG, "User set ringtone to " + uri);
 49                        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
 50                            NotificationService.recreateIncomingCallChannel(requireContext(), uri);
 51                        }
 52                    });
 53
 54    @Override
 55    public void onCreatePreferences(
 56            @Nullable final Bundle savedInstanceState, final @Nullable String rootKey) {
 57        setPreferencesFromResource(R.xml.preferences_notifications, rootKey);
 58        final var messageNotificationSettings = findPreference("message_notification_settings");
 59        final var notificationRingtone = findPreference(AppSettings.NOTIFICATION_RINGTONE);
 60        final var notificationHeadsUp = findPreference(AppSettings.NOTIFICATION_HEADS_UP);
 61        final var notificationVibrate = findPreference(AppSettings.NOTIFICATION_VIBRATE);
 62        final var notificationLed = findPreference(AppSettings.NOTIFICATION_LED);
 63        final var foregroundService = findPreference(AppSettings.KEEP_FOREGROUND_SERVICE);
 64        if (messageNotificationSettings == null
 65                || notificationRingtone == null
 66                || notificationHeadsUp == null
 67                || notificationVibrate == null
 68                || notificationLed == null
 69                || foregroundService == null) {
 70            throw new IllegalStateException("The preference resource file is missing preferences");
 71        }
 72        if (Compatibility.runsTwentySix()) {
 73            notificationRingtone.setVisible(false);
 74            notificationHeadsUp.setVisible(false);
 75            notificationVibrate.setVisible(false);
 76            notificationLed.setVisible(false);
 77            foregroundService.setVisible(false);
 78        } else {
 79            messageNotificationSettings.setVisible(false);
 80        }
 81    }
 82
 83    @Override
 84    protected void onSharedPreferenceChanged(@NonNull String key) {
 85        super.onSharedPreferenceChanged(key);
 86        if (key.equals(AppSettings.KEEP_FOREGROUND_SERVICE)) {
 87            requireService().toggleForegroundService();
 88        }
 89    }
 90
 91    @Override
 92    public void onStart() {
 93        super.onStart();
 94        requireActivity().setTitle(R.string.notifications);
 95    }
 96
 97    @Override
 98    public void onBackendConnected() {
 99        boolean diallerIntegrationPossible = false;
100
101        if (Build.VERSION.SDK_INT >= 23) {
102            outer:
103            for (final var account : requireService().getAccounts()) {
104                for (final var contact : account.getRoster().getContacts()) {
105                    if (contact.getPresences().anyIdentity("gateway", "pstn")) {
106                        diallerIntegrationPossible = true;
107                        break outer;
108                    }
109                }
110            }
111        }
112        if (!diallerIntegrationPossible) {
113            final var pref = findPreference("dialler_integration_incoming");
114            pref.setVisible(false);
115        }
116    }
117
118    @Override
119    public boolean onPreferenceTreeClick(final Preference preference) {
120        final var key = preference.getKey();
121        if (AppSettings.RINGTONE.equals(key)) {
122            pickRingtone();
123            return true;
124        }
125        if (AppSettings.NOTIFICATION_RINGTONE.equals(key)) {
126            pickNotificationTone();
127            return true;
128        }
129        return super.onPreferenceTreeClick(preference);
130    }
131
132    private void pickNotificationTone() {
133        final Uri uri = appSettings().getNotificationTone();
134        Log.i(Config.LOGTAG, "current notification tone: " + uri);
135        this.pickNotificationToneLauncher.launch(uri);
136    }
137
138    private void pickRingtone() {
139        final Optional<Uri> channelRingtone;
140        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) {
141            channelRingtone =
142                    NotificationService.getCurrentIncomingCallChannel(requireContext())
143                            .transform(NotificationChannel::getSound);
144        } else {
145            channelRingtone = Optional.absent();
146        }
147        final Uri uri;
148        if (channelRingtone.isPresent()) {
149            uri = channelRingtone.get();
150            Log.d(Config.LOGTAG, "ringtone came from channel");
151        } else {
152            uri = appSettings().getRingtone();
153        }
154        Log.i(Config.LOGTAG, "current ringtone: " + uri);
155        this.pickRingtoneLauncher.launch(uri);
156    }
157
158    private AppSettings appSettings() {
159        return new AppSettings(requireContext());
160    }
161}