Move more logic from SettingsActivity to settings fragments

This commit is contained in:
xynngh 2020-11-02 19:46:56 +04:00
parent a2d0ba5cd5
commit 7c2f12edd9
3 changed files with 136 additions and 109 deletions

View File

@ -22,6 +22,7 @@ import androidx.annotation.Nullable;
import androidx.annotation.RequiresApi;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;
import androidx.fragment.app.Fragment;
import com.android.settings.applications.PreferredSettingsUtils;
@ -65,29 +66,46 @@ public class PermissionHelper {
CONTACTS_PERMISSIONS.add(Manifest.permission.READ_CONTACTS);
}
public static void checkPermissions(Activity activity, boolean info,
boolean block, boolean contacts) {
public static List<String> getMissingPermissions(Context context, boolean info,
boolean block, boolean contacts) {
Set<String> requiredPermissions = new HashSet<>();
if (info) requiredPermissions.addAll(INFO_PERMISSIONS);
if (block) requiredPermissions.addAll(BLOCKING_PERMISSIONS);
if (contacts) requiredPermissions.addAll(CONTACTS_PERMISSIONS);
List<String> missingPermissions = new ArrayList<>(requiredPermissions.size());
List<String> missingPermissions = new ArrayList<>();
for (String permission : requiredPermissions) {
if (ContextCompat.checkSelfPermission(activity, permission)
if (ContextCompat.checkSelfPermission(context, permission)
!= PackageManager.PERMISSION_GRANTED) {
missingPermissions.add(permission);
}
}
return missingPermissions;
}
public static void checkPermissions(Activity activity, boolean info,
boolean block, boolean contacts) {
List<String> missingPermissions = getMissingPermissions(activity, info, block, contacts);
if (!missingPermissions.isEmpty()) {
ActivityCompat.requestPermissions(activity,
missingPermissions.toArray(new String[0]), REQUEST_CODE_PERMISSIONS);
}
}
public static void checkPermissions(Context context, Fragment fragment,
boolean info, boolean block, boolean contacts) {
List<String> missingPermissions = getMissingPermissions(context, info, block, contacts);
if (!missingPermissions.isEmpty()) {
fragment.requestPermissions(
missingPermissions.toArray(new String[0]), REQUEST_CODE_PERMISSIONS);
}
}
public static void handlePermissionsResult(@NonNull Context context, int requestCode,
@NonNull String[] permissions,
@NonNull int[] grantResults,
@ -166,11 +184,15 @@ public class PermissionHelper {
}
public static RequestToken requestCallScreening(Activity activity) {
return requestCallScreening(activity, null);
}
public static RequestToken requestCallScreening(Activity activity, Fragment fragment) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
RoleManagerHelper.requestCallScreeningRole(activity);
RoleManagerHelper.requestCallScreeningRole(activity, fragment);
return null;
} else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
return setAsDefaultDialer(activity);
return setAsDefaultDialer(activity, fragment);
}
return null;
}
@ -183,36 +205,36 @@ public class PermissionHelper {
return isDefaultDialer(context);
}
public static void disableCallScreening(Context context) {
public static void disableCallScreening(Activity activity) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (RoleManagerHelper.hasCallScreeningRole(context)) {
new AlertDialog.Builder(context)
if (RoleManagerHelper.hasCallScreeningRole(activity)) {
new AlertDialog.Builder(activity)
.setTitle(R.string.default_caller_id_app)
.setMessage(R.string.default_caller_id_app_unset)
.setPositiveButton(R.string.open_system_settings,
(d, w) -> openDefaultAppsSettings(context))
(d, w) -> openDefaultAppsSettings(activity))
.show();
return;
}
}
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.N) {
if (isDefaultDialer(context)) {
showDefaultDialerDialog(context, false);
if (isDefaultDialer(activity)) {
showDefaultDialerDialog(activity, false);
}
}
}
public static boolean handleCallScreeningResult(Context context,
public static boolean handleCallScreeningResult(Activity activity,
int requestCode, int resultCode,
RequestToken requestToken) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
if (RoleManagerHelper.handleCallScreeningResult(context, requestCode, resultCode)) {
if (RoleManagerHelper.handleCallScreeningResult(activity, requestCode, resultCode)) {
return true;
}
}
return handleDefaultDialerResult(context, requestCode, resultCode, requestToken);
return handleDefaultDialerResult(activity, requestCode, resultCode, requestToken);
}
public static boolean isDefaultDialer(Context context) {
@ -226,6 +248,11 @@ public class PermissionHelper {
@RequiresApi(Build.VERSION_CODES.N)
public static RequestToken setAsDefaultDialer(Activity activity) {
return setAsDefaultDialer(activity, null);
}
@RequiresApi(Build.VERSION_CODES.N)
public static RequestToken setAsDefaultDialer(Activity activity, Fragment fragment) {
if (isDefaultDialer(activity)) return null;
Intent intent = new Intent(TelecomManager.ACTION_CHANGE_DEFAULT_DIALER);
@ -233,7 +260,12 @@ public class PermissionHelper {
BuildConfig.APPLICATION_ID);
try {
activity.startActivityForResult(intent, REQUEST_CODE_DEFAULT_DIALER);
if (fragment != null) {
fragment.startActivityForResult(intent, REQUEST_CODE_DEFAULT_DIALER);
} else {
activity.startActivityForResult(intent, REQUEST_CODE_DEFAULT_DIALER);
}
return new RequestToken(System.nanoTime());
} catch (Exception e) {
LOG.warn("setAsDefaultDialer()", e);
@ -245,17 +277,17 @@ public class PermissionHelper {
}
@RequiresApi(Build.VERSION_CODES.N)
private static void setAsDefaultDialerFallback(Context context) {
showDefaultDialerDialog(context, true);
private static void setAsDefaultDialerFallback(Activity activity) {
showDefaultDialerDialog(activity, true);
}
@RequiresApi(Build.VERSION_CODES.N)
private static void showDefaultDialerDialog(Context context, boolean set) {
new AlertDialog.Builder(context)
private static void showDefaultDialerDialog(Activity activity, boolean set) {
new AlertDialog.Builder(activity)
.setTitle(R.string.default_phone_app)
.setMessage(set ? R.string.default_phone_app_set : R.string.default_phone_app_unset)
.setPositiveButton(R.string.open_system_settings,
(d, w) -> openDefaultDialerSettings(context))
(d, w) -> openDefaultDialerSettings(activity))
.show();
}
@ -333,7 +365,7 @@ public class PermissionHelper {
return intent;
}
public static boolean handleDefaultDialerResult(Context context,
public static boolean handleDefaultDialerResult(Activity activity,
int requestCode, int resultCode,
RequestToken requestToken) {
if (requestCode != REQUEST_CODE_DEFAULT_DIALER) return false;
@ -343,9 +375,9 @@ public class PermissionHelper {
if (requestToken != null && System.nanoTime() - requestToken.timestamp
< TimeUnit.MILLISECONDS.toNanos(500)) {
// probably the request is not supported, try workarounds
setAsDefaultDialerFallback(context);
setAsDefaultDialerFallback(activity);
} else {
Toast.makeText(context, R.string.denied_default_dialer_message, Toast.LENGTH_LONG)
Toast.makeText(activity, R.string.denied_default_dialer_message, Toast.LENGTH_LONG)
.show();
}

View File

@ -9,6 +9,7 @@ import android.os.Build;
import android.widget.Toast;
import androidx.annotation.RequiresApi;
import androidx.fragment.app.Fragment;
import static android.content.Context.ROLE_SERVICE;
import static java.util.Objects.requireNonNull;
@ -25,10 +26,19 @@ public class RoleManagerHelper {
public static void requestCallScreeningRole(Activity activity) {
if (hasCallScreeningRole(activity)) return;
Intent intent = getRoleManager(activity)
.createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
activity.startActivityForResult(
getCallScreeningRequestIntent(activity), REQUEST_CODE_CALL_SCREENING);
}
activity.startActivityForResult(intent, REQUEST_CODE_CALL_SCREENING);
public static void requestCallScreeningRole(Context context, Fragment fragment) {
if (hasCallScreeningRole(context)) return;
fragment.startActivityForResult(
getCallScreeningRequestIntent(context), REQUEST_CODE_CALL_SCREENING);
}
private static Intent getCallScreeningRequestIntent(Context context) {
return getRoleManager(context).createRequestRoleIntent(RoleManager.ROLE_CALL_SCREENING);
}
public static boolean handleCallScreeningResult(Context context,

View File

@ -14,7 +14,6 @@ import androidx.appcompat.app.ActionBar;
import androidx.appcompat.app.AlertDialog;
import androidx.appcompat.app.AppCompatActivity;
import androidx.fragment.app.Fragment;
import androidx.fragment.app.FragmentActivity;
import androidx.preference.Preference;
import androidx.preference.PreferenceFragmentCompat;
import androidx.preference.PreferenceGroup;
@ -37,19 +36,12 @@ import dummydomain.yetanothercallblocker.work.UpdateScheduler;
public class SettingsActivity extends AppCompatActivity
implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
private static final String STATE_REQUEST_TOKEN = "STATE_REQUEST_TOKEN";
private PermissionHelper.RequestToken requestToken;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.settings_activity);
if (savedInstanceState != null) {
requestToken = PermissionHelper.RequestToken
.fromSavedInstanceState(savedInstanceState, STATE_REQUEST_TOKEN);
} else {
if (savedInstanceState == null) {
getSupportFragmentManager()
.beginTransaction()
.replace(R.id.settings, new RootSettingsFragment())
@ -62,22 +54,6 @@ public class SettingsActivity extends AppCompatActivity
}
}
@Override
protected void onResume() {
super.onResume();
updateCallScreeningPreference();
}
@Override
protected void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (requestToken != null) {
requestToken.onSaveInstanceState(outState, STATE_REQUEST_TOKEN);
}
}
@Override
public boolean onPreferenceStartScreen(PreferenceFragmentCompat preferenceFragmentCompat,
PreferenceScreen preferenceScreen) {
@ -93,36 +69,6 @@ public class SettingsActivity extends AppCompatActivity
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Settings settings = App.getSettings();
PermissionHelper.handlePermissionsResult(this, requestCode, permissions, grantResults,
settings.getIncomingCallNotifications(), settings.getCallBlockingEnabled(),
settings.getUseContacts());
}
@Override
protected void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (PermissionHelper.handleCallScreeningResult(
this, requestCode, resultCode, requestToken)) {
updateCallScreeningPreference();
}
}
private void updateCallScreeningPreference() {
for (Fragment fragment : getSupportFragmentManager().getFragments()) {
if (fragment instanceof BaseSettingsFragment) {
((RootSettingsFragment) fragment).updateCallScreeningPreference();
}
}
}
public static abstract class BaseSettingsFragment extends PreferenceFragmentCompat
implements PreferenceFragmentCompat.OnPreferenceStartScreenCallback {
@ -225,12 +171,61 @@ public class SettingsActivity extends AppCompatActivity
private static final String PREF_NOTIFICATIONS_BLOCKED_NON_PERSISTENT = "showNotificationsForBlockedCallsNonPersistent";
private static final String PREF_SCREEN_ADVANCED = "screenAdvanced";
private static final String STATE_REQUEST_TOKEN = "STATE_REQUEST_TOKEN";
private final UpdateScheduler updateScheduler = UpdateScheduler.get(App.getInstance());
private PermissionHelper.RequestToken requestToken;
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
Settings settings = App.getSettings();
PermissionHelper.handlePermissionsResult(requireContext(),
requestCode, permissions, grantResults,
settings.getIncomingCallNotifications(), settings.getCallBlockingEnabled(),
settings.getUseContacts());
}
@Override
public void onActivityResult(int requestCode, int resultCode, @Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (PermissionHelper.handleCallScreeningResult(
requireActivity(), requestCode, resultCode, requestToken)) {
updateCallScreeningPreference();
}
}
@Override
public void onCreatePreferences(Bundle savedInstanceState, String rootKey) {
super.onCreatePreferences(savedInstanceState, rootKey);
requestToken = PermissionHelper.RequestToken
.fromSavedInstanceState(savedInstanceState, STATE_REQUEST_TOKEN);
}
@Override
public void onSaveInstanceState(@NonNull Bundle outState) {
super.onSaveInstanceState(outState);
if (requestToken != null) {
requestToken.onSaveInstanceState(outState, STATE_REQUEST_TOKEN);
}
}
@Override
public void onStart() {
super.onStart();
// may be changed externally
updateCallScreeningPreference();
// needs to be updated after the confirmation dialog was closed
// due to activity recreation (orientation change, etc.)
updateBlockedCallNotificationsPreference();
}
@ -243,14 +238,16 @@ public class SettingsActivity extends AppCompatActivity
protected void initScreen() {
setPrefChangeListener(Settings.PREF_INCOMING_CALL_NOTIFICATIONS, (pref, newValue) -> {
if (Boolean.TRUE.equals(newValue)) {
PermissionHelper.checkPermissions(requireActivity(), true, false, false);
PermissionHelper.checkPermissions(requireContext(), this,
true, false, false);
}
return true;
});
Preference.OnPreferenceChangeListener callBlockingListener = (preference, newValue) -> {
if (Boolean.TRUE.equals(newValue)) {
PermissionHelper.checkPermissions(requireActivity(), false, true, false);
PermissionHelper.checkPermissions(requireContext(), this,
false, true, false);
}
return true;
};
@ -263,16 +260,9 @@ public class SettingsActivity extends AppCompatActivity
callScreeningPref.setChecked(PermissionHelper.isCallScreeningHeld(requireContext()));
callScreeningPref.setOnPreferenceChangeListener((preference, newValue) -> {
if (Boolean.TRUE.equals(newValue)) {
FragmentActivity activity = requireActivity();
PermissionHelper.RequestToken requestToken
= PermissionHelper.requestCallScreening(activity);
if (activity instanceof SettingsActivity) {
((SettingsActivity) activity).requestToken = requestToken;
}
requestToken = PermissionHelper.requestCallScreening(requireActivity(), this);
} else {
PermissionHelper.disableCallScreening(requireContext());
PermissionHelper.disableCallScreening(requireActivity());
return false;
}
return true;
@ -310,7 +300,8 @@ public class SettingsActivity extends AppCompatActivity
setPrefChangeListener(Settings.PREF_USE_CONTACTS, (preference, newValue) -> {
if (Boolean.TRUE.equals(newValue)) {
PermissionHelper.checkPermissions(requireActivity(), false, false, true);
PermissionHelper.checkPermissions(requireContext(), this,
false, false, true);
}
return true;
});
@ -357,24 +348,18 @@ public class SettingsActivity extends AppCompatActivity
}
}
private void updateCallScreeningPreference() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.N) return;
this.<SwitchPreferenceCompat>requirePreference(PREF_USE_CALL_SCREENING_SERVICE)
.setChecked(PermissionHelper.isCallScreeningHeld(requireContext()));
}
private void updateBlockedCallNotificationsPreference() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O) return;
SwitchPreferenceCompat notificationsForBlockedPref =
findPreference(PREF_NOTIFICATIONS_BLOCKED_NON_PERSISTENT);
if (notificationsForBlockedPref != null) {
notificationsForBlockedPref.setChecked(
App.getSettings().getNotificationsForBlockedCalls());
}
}
public void updateCallScreeningPreference() {
SwitchPreferenceCompat callScreeningPref
= findPreference(PREF_USE_CALL_SCREENING_SERVICE);
if (callScreeningPref != null) {
callScreeningPref.setChecked(PermissionHelper.isCallScreeningHeld(requireContext()));
}
this.<SwitchPreferenceCompat>requirePreference(PREF_NOTIFICATIONS_BLOCKED_NON_PERSISTENT)
.setChecked(App.getSettings().getNotificationsForBlockedCalls());
}
@Override