NotificationsSettingsFragment.java

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