deltachat/src/main/java/org/thoughtcrime/securesms/preferences/NotificationsPreferenceFragment.java

245 lines
9.8 KiB
Java

package org.thoughtcrime.securesms.preferences;
import android.Manifest;
import android.content.Context;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.media.Ringtone;
import android.media.RingtoneManager;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.PowerManager;
import android.provider.Settings;
import androidx.annotation.Nullable;
import androidx.appcompat.app.AlertDialog;
import androidx.core.app.NotificationManagerCompat;
import androidx.core.content.ContextCompat;
import androidx.preference.CheckBoxPreference;
import androidx.preference.ListPreference;
import androidx.preference.Preference;
import android.text.TextUtils;
import org.thoughtcrime.securesms.ApplicationPreferencesActivity;
import org.thoughtcrime.securesms.BuildConfig;
import org.thoughtcrime.securesms.R;
import org.thoughtcrime.securesms.connect.DcHelper;
import org.thoughtcrime.securesms.connect.KeepAliveService;
import org.thoughtcrime.securesms.notifications.FcmReceiveService;
import org.thoughtcrime.securesms.util.Prefs;
import static android.app.Activity.RESULT_OK;
import static org.thoughtcrime.securesms.connect.DcHelper.CONFIG_ONLY_FETCH_MVBOX;
public class NotificationsPreferenceFragment extends ListSummaryPreferenceFragment {
private static final int REQUEST_CODE_NOTIFICATION_SELECTED = 1;
private CheckBoxPreference ignoreBattery;
@Override
public void onCreate(Bundle paramBundle) {
super.onCreate(paramBundle);
this.findPreference(Prefs.LED_COLOR_PREF)
.setOnPreferenceChangeListener(new ListSummaryListener());
this.findPreference(Prefs.RINGTONE_PREF)
.setOnPreferenceChangeListener(new RingtoneSummaryListener());
this.findPreference(Prefs.NOTIFICATION_PRIVACY_PREF)
.setOnPreferenceChangeListener(new ListSummaryListener());
this.findPreference(Prefs.NOTIFICATION_PRIORITY_PREF)
.setOnPreferenceChangeListener(new ListSummaryListener());
this.findPreference(Prefs.RINGTONE_PREF)
.setOnPreferenceClickListener(preference -> {
Uri current = Prefs.getNotificationRingtone(getContext());
if (current.toString().isEmpty()) current = null; // silent
Intent intent = new Intent(RingtoneManager.ACTION_RINGTONE_PICKER);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_DEFAULT, true);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_SHOW_SILENT, true);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_TYPE, RingtoneManager.TYPE_NOTIFICATION);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_DEFAULT_URI, Settings.System.DEFAULT_NOTIFICATION_URI);
intent.putExtra(RingtoneManager.EXTRA_RINGTONE_EXISTING_URI, current);
startActivityForResult(intent, REQUEST_CODE_NOTIFICATION_SELECTED);
return true;
});
initializeListSummary((ListPreference) findPreference(Prefs.LED_COLOR_PREF));
initializeListSummary((ListPreference) findPreference(Prefs.NOTIFICATION_PRIVACY_PREF));
initializeListSummary((ListPreference) findPreference(Prefs.NOTIFICATION_PRIORITY_PREF));
initializeRingtoneSummary(findPreference(Prefs.RINGTONE_PREF));
CheckBoxPreference usePushService = this.findPreference("pref_push_enabled");
usePushService.setChecked(Prefs.isPushEnabled(getContext()));
usePushService.setEnabled(BuildConfig.USE_PLAY_SERVICES);
usePushService.setOnPreferenceChangeListener((preference, newValue) -> {
final boolean enabled = (Boolean) newValue;
if (!enabled) {
new AlertDialog.Builder(getContext())
.setMessage(R.string.pref_push_ask_disable)
.setPositiveButton(R.string.ok, (dialogInterface, i) -> {
((CheckBoxPreference)preference).setChecked(false);
})
.setNegativeButton(R.string.cancel, null)
.setNeutralButton(R.string.learn_more, (dialogInterface, i) -> {
DcHelper.openHelp(getActivity(), "#instant-delivery");
})
.show();
return false;
}
return true;
});
ignoreBattery = this.findPreference("pref_ignore_battery_optimizations");
ignoreBattery.setVisible(needsIgnoreBatteryOptimizations());
ignoreBattery.setOnPreferenceChangeListener((preference, newValue) -> {
requestToggleIgnoreBatteryOptimizations();
return true;
});
CheckBoxPreference reliableService = this.findPreference("pref_reliable_service");
reliableService.setOnPreferenceChangeListener((preference, newValue) -> {
Context context = getContext();
boolean enabled = (Boolean) newValue; // Prefs.reliableService() still has the old value
if (enabled && Prefs.isNotificationsEnabled(context)) {
KeepAliveService.startSelf(context);
} else {
context.stopService(new Intent(context, KeepAliveService.class));
}
return true;
});
CheckBoxPreference notificationsEnabled = this.findPreference("pref_key_enable_notifications");
notificationsEnabled.setOnPreferenceChangeListener((preference, newValue) -> {
Context context = getContext();
boolean enabled = (Boolean) newValue; // Prefs.isNotificationsEnabled() still has the old value
if (enabled && Prefs.reliableService(context)) {
KeepAliveService.startSelf(context);
} else {
context.stopService(new Intent(context, KeepAliveService.class));
}
return true;
});
}
@Override
public void onCreatePreferences(@Nullable Bundle savedInstanceState, String rootKey) {
addPreferencesFromResource(R.xml.preferences_notifications);
}
@Override
public void onResume() {
super.onResume();
((ApplicationPreferencesActivity) getActivity()).getSupportActionBar().setTitle(R.string.pref_notifications);
// update ignoreBattery in onResume() to reflects changes done in the system settings
ignoreBattery.setChecked(isIgnoringBatteryOptimizations());
}
@Override
public void onPause() {
super.onPause();
// we delay applying token changes to avoid changes and races if the user is just playing around
if (Prefs.isPushEnabled(getContext()) && FcmReceiveService.getToken() == null) {
FcmReceiveService.register(getContext());
} else if(!Prefs.isPushEnabled(getContext()) && FcmReceiveService.getToken() != null) {
FcmReceiveService.deleteToken();
}
}
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CODE_NOTIFICATION_SELECTED && resultCode == RESULT_OK && data != null) {
Uri uri = data.getParcelableExtra(RingtoneManager.EXTRA_RINGTONE_PICKED_URI);
if (Settings.System.DEFAULT_NOTIFICATION_URI.equals(uri)) {
Prefs.removeNotificationRingtone(getContext());
} else {
Prefs.setNotificationRingtone(getContext(), uri != null ? uri : Uri.EMPTY);
}
initializeRingtoneSummary(findPreference(Prefs.RINGTONE_PREF));
}
}
private class RingtoneSummaryListener implements Preference.OnPreferenceChangeListener {
@Override
public boolean onPreferenceChange(Preference preference, Object newValue) {
Uri value = (Uri) newValue;
if (value == null || TextUtils.isEmpty(value.toString())) {
preference.setSummary(R.string.pref_silent);
} else {
Ringtone tone = RingtoneManager.getRingtone(getActivity(), value);
if (tone != null) {
preference.setSummary(tone.getTitle(getActivity()));
}
}
return true;
}
}
private boolean needsIgnoreBatteryOptimizations() {
return Build.VERSION.SDK_INT >= Build.VERSION_CODES.M;
}
private boolean isIgnoringBatteryOptimizations() {
if (!needsIgnoreBatteryOptimizations()) {
return true;
}
PowerManager pm = (PowerManager)getActivity().getSystemService(Context.POWER_SERVICE);
if(pm.isIgnoringBatteryOptimizations(getActivity().getPackageName())) {
return true;
}
return false;
}
private void requestToggleIgnoreBatteryOptimizations() {
Context context = getActivity();
boolean openManualSettings = true;
try {
if (needsIgnoreBatteryOptimizations()
&& !isIgnoringBatteryOptimizations()
&& ContextCompat.checkSelfPermission(context, Manifest.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS) == PackageManager.PERMISSION_GRANTED) {
Intent intent = new Intent(Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS, Uri.parse("package:" + context.getPackageName()));
context.startActivity(intent);
openManualSettings = false;
}
} catch (Exception e) {
e.printStackTrace();
}
if (openManualSettings && needsIgnoreBatteryOptimizations()) {
// fire ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS if ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS fails
// or if isIgnoringBatteryOptimizations() is already true (there is no intent to re-enable battery optimizations)
Intent intent = new Intent(Settings.ACTION_IGNORE_BATTERY_OPTIMIZATION_SETTINGS);
context.startActivity(intent);
}
}
private void initializeRingtoneSummary(Preference pref) {
RingtoneSummaryListener listener = (RingtoneSummaryListener) pref.getOnPreferenceChangeListener();
Uri uri = Prefs.getNotificationRingtone(getContext());
listener.onPreferenceChange(pref, uri);
}
public static CharSequence getSummary(Context context) {
NotificationManagerCompat notificationManager = NotificationManagerCompat.from(context);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.TIRAMISU || notificationManager.areNotificationsEnabled()) {
return context.getString(Prefs.isNotificationsEnabled(context) ? R.string.on : R.string.off);
} else {
return context.getString(R.string.disabled_in_system_settings);
}
}
}