Move Android permission handling out of K9Activity
This commit is contained in:
parent
4cb7e46494
commit
f393c3a00f
6 changed files with 117 additions and 71 deletions
|
@ -1,28 +1,17 @@
|
|||
package com.fsck.k9.activity;
|
||||
|
||||
|
||||
import android.Manifest;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Bundle;
|
||||
|
||||
import androidx.annotation.LayoutRes;
|
||||
import androidx.annotation.StringRes;
|
||||
import androidx.core.app.ActivityCompat;
|
||||
import androidx.core.content.ContextCompat;
|
||||
import androidx.appcompat.app.AppCompatActivity;
|
||||
import androidx.appcompat.widget.Toolbar;
|
||||
|
||||
import android.view.View;
|
||||
import com.fsck.k9.ui.R;
|
||||
import com.fsck.k9.ui.ThemeManager;
|
||||
import com.fsck.k9.ui.permissions.PermissionRationaleDialogFragment;
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
public abstract class K9Activity extends AppCompatActivity {
|
||||
public static final int PERMISSIONS_REQUEST_READ_CONTACTS = 1;
|
||||
private static final String FRAGMENT_TAG_RATIONALE = "rationale";
|
||||
|
||||
|
||||
private final K9ActivityCommon base = new K9ActivityCommon(this, ThemeType.DEFAULT);
|
||||
|
||||
public ThemeManager getThemeManager() {
|
||||
|
@ -49,47 +38,4 @@ public abstract class K9Activity extends AppCompatActivity {
|
|||
}
|
||||
setSupportActionBar(toolbar);
|
||||
}
|
||||
|
||||
public boolean hasPermission(Permission permission) {
|
||||
return ContextCompat.checkSelfPermission(this, permission.permission) == PackageManager.PERMISSION_GRANTED;
|
||||
}
|
||||
|
||||
public void requestPermissionOrShowRationale(Permission permission) {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(this, permission.permission)) {
|
||||
PermissionRationaleDialogFragment dialogFragment =
|
||||
PermissionRationaleDialogFragment.newInstance(permission);
|
||||
|
||||
dialogFragment.show(getSupportFragmentManager(), FRAGMENT_TAG_RATIONALE);
|
||||
} else {
|
||||
requestPermission(permission);
|
||||
}
|
||||
}
|
||||
|
||||
public void requestPermission(Permission permission) {
|
||||
Timber.i("Requesting permission: " + permission.permission);
|
||||
ActivityCompat.requestPermissions(this, new String[] { permission.permission }, permission.requestCode);
|
||||
}
|
||||
|
||||
|
||||
public enum Permission {
|
||||
READ_CONTACTS(
|
||||
Manifest.permission.READ_CONTACTS,
|
||||
PERMISSIONS_REQUEST_READ_CONTACTS,
|
||||
R.string.permission_contacts_rationale_title,
|
||||
R.string.permission_contacts_rationale_message
|
||||
);
|
||||
|
||||
|
||||
public final String permission;
|
||||
public final int requestCode;
|
||||
public final int rationaleTitle;
|
||||
public final int rationaleMessage;
|
||||
|
||||
Permission(String permission, int requestCode, @StringRes int rationaleTitle, @StringRes int rationaleMessage) {
|
||||
this.permission = permission;
|
||||
this.requestCode = requestCode;
|
||||
this.rationaleTitle = rationaleTitle;
|
||||
this.rationaleMessage = rationaleMessage;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -110,7 +110,11 @@ import com.fsck.k9.ui.compose.QuotedMessageMvpView;
|
|||
import com.fsck.k9.ui.compose.QuotedMessagePresenter;
|
||||
import com.fsck.k9.ui.helper.SizeFormatter;
|
||||
import com.fsck.k9.ui.messagelist.DefaultFolderProvider;
|
||||
import com.fsck.k9.ui.permissions.K9PermissionUiHelper;
|
||||
import com.fsck.k9.ui.permissions.Permission;
|
||||
import com.fsck.k9.ui.permissions.PermissionUiHelper;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
import org.openintents.openpgp.OpenPgpApiManager;
|
||||
import org.openintents.openpgp.util.OpenPgpApi;
|
||||
import timber.log.Timber;
|
||||
|
@ -120,7 +124,7 @@ import timber.log.Timber;
|
|||
public class MessageCompose extends K9Activity implements OnClickListener,
|
||||
CancelListener, AttachmentDownloadCancelListener, OnFocusChangeListener,
|
||||
OnOpenPgpInlineChangeListener, OnOpenPgpSignOnlyChangeListener, MessageBuilder.Callback,
|
||||
AttachmentPresenter.AttachmentsChangedListener, OnOpenPgpDisableListener {
|
||||
AttachmentPresenter.AttachmentsChangedListener, OnOpenPgpDisableListener, PermissionUiHelper {
|
||||
|
||||
private static final int DIALOG_SAVE_OR_DISCARD_DRAFT_MESSAGE = 1;
|
||||
private static final int DIALOG_CONFIRM_DISCARD_ON_BACK = 2;
|
||||
|
@ -177,6 +181,8 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
private final MessageLoaderHelperFactory messageLoaderHelperFactory = DI.get(MessageLoaderHelperFactory.class);
|
||||
private final DefaultFolderProvider defaultFolderProvider = DI.get(DefaultFolderProvider.class);
|
||||
|
||||
private final PermissionUiHelper permissionUiHelper = new K9PermissionUiHelper(this);
|
||||
|
||||
private QuotedMessagePresenter quotedMessagePresenter;
|
||||
private MessageLoaderHelper messageLoaderHelper;
|
||||
private AttachmentPresenter attachmentPresenter;
|
||||
|
@ -1883,4 +1889,20 @@ public class MessageCompose extends K9Activity implements OnClickListener,
|
|||
return titleResource;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NotNull Permission permission) {
|
||||
return permissionUiHelper.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPermissionOrShowRationale(@NotNull Permission permission) {
|
||||
permissionUiHelper.requestPermissionOrShowRationale(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPermission(@NotNull Permission permission) {
|
||||
permissionUiHelper.requestPermission(permission);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -60,9 +60,15 @@ import com.fsck.k9.ui.messageview.MessageViewFragment;
|
|||
import com.fsck.k9.ui.messageview.MessageViewFragment.MessageViewFragmentListener;
|
||||
import com.fsck.k9.ui.messageview.PlaceholderFragment;
|
||||
import com.fsck.k9.ui.onboarding.OnboardingActivity;
|
||||
import com.fsck.k9.ui.permissions.K9PermissionUiHelper;
|
||||
import com.fsck.k9.ui.permissions.Permission;
|
||||
import com.fsck.k9.ui.permissions.PermissionUiHelper;
|
||||
import com.fsck.k9.view.ViewSwitcher;
|
||||
import com.fsck.k9.view.ViewSwitcher.OnSwitchCompleteListener;
|
||||
import com.mikepenz.materialdrawer.Drawer.OnDrawerListener;
|
||||
|
||||
import org.jetbrains.annotations.NotNull;
|
||||
|
||||
import timber.log.Timber;
|
||||
|
||||
|
||||
|
@ -72,7 +78,7 @@ import timber.log.Timber;
|
|||
* From this Activity the user can perform all standard message operations.
|
||||
*/
|
||||
public class MessageList extends K9Activity implements MessageListFragmentListener,
|
||||
MessageViewFragmentListener, OnBackStackChangedListener, OnSwitchCompleteListener {
|
||||
MessageViewFragmentListener, OnBackStackChangedListener, OnSwitchCompleteListener, PermissionUiHelper {
|
||||
|
||||
private static final String EXTRA_SEARCH = "search_bytes";
|
||||
private static final String EXTRA_NO_THREADING = "no_threading";
|
||||
|
@ -178,6 +184,8 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
|
|||
private final NotificationChannelManager channelUtils = DI.get(NotificationChannelManager.class);
|
||||
private final DefaultFolderProvider defaultFolderProvider = DI.get(DefaultFolderProvider.class);
|
||||
|
||||
private final PermissionUiHelper permissionUiHelper = new K9PermissionUiHelper(this);
|
||||
|
||||
private ActionBar actionBar;
|
||||
private ActionBarDrawerToggle drawerToggle;
|
||||
private K9Drawer drawer;
|
||||
|
@ -1622,4 +1630,19 @@ public class MessageList extends K9Activity implements MessageListFragmentListen
|
|||
drawer.deselect();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasPermission(@NotNull Permission permission) {
|
||||
return permissionUiHelper.hasPermission(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPermissionOrShowRationale(@NotNull Permission permission) {
|
||||
permissionUiHelper.requestPermissionOrShowRationale(permission);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void requestPermission(@NotNull Permission permission) {
|
||||
permissionUiHelper.requestPermission(permission);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,21 @@
|
|||
package com.fsck.k9.ui.permissions
|
||||
|
||||
import android.Manifest
|
||||
import androidx.annotation.StringRes
|
||||
import com.fsck.k9.ui.R
|
||||
|
||||
private const val PERMISSIONS_REQUEST_READ_CONTACTS = 1
|
||||
|
||||
enum class Permission(
|
||||
val permission: String,
|
||||
val requestCode: Int,
|
||||
@param:StringRes val rationaleTitle: Int,
|
||||
@param:StringRes val rationaleMessage: Int
|
||||
) {
|
||||
READ_CONTACTS(
|
||||
Manifest.permission.READ_CONTACTS,
|
||||
PERMISSIONS_REQUEST_READ_CONTACTS,
|
||||
R.string.permission_contacts_rationale_title,
|
||||
R.string.permission_contacts_rationale_message
|
||||
);
|
||||
}
|
|
@ -5,15 +5,13 @@ import android.app.Dialog
|
|||
import android.os.Bundle
|
||||
import androidx.core.os.bundleOf
|
||||
import androidx.fragment.app.DialogFragment
|
||||
import com.fsck.k9.activity.K9Activity
|
||||
import com.fsck.k9.activity.K9Activity.Permission
|
||||
import com.fsck.k9.ui.R
|
||||
|
||||
/**
|
||||
* A dialog displaying a message to explain why the app requests a certain permission.
|
||||
*
|
||||
* Closing the dialog triggers a permission request. For this to work the Activity needs to be a subclass of
|
||||
* [K9Activity].
|
||||
* Closing the dialog triggers a permission request. For this to work the Activity needs to implement
|
||||
* [PermissionUiHelper].
|
||||
*/
|
||||
class PermissionRationaleDialogFragment : DialogFragment() {
|
||||
override fun onCreateDialog(savedInstanceState: Bundle?): Dialog {
|
||||
|
@ -22,22 +20,21 @@ class PermissionRationaleDialogFragment : DialogFragment() {
|
|||
|
||||
val permission = Permission.valueOf(permissionName)
|
||||
|
||||
return AlertDialog.Builder(requireContext()).apply {
|
||||
setTitle(permission.rationaleTitle)
|
||||
setMessage(permission.rationaleMessage)
|
||||
setPositiveButton(R.string.okay_action) { _, _ ->
|
||||
val activity = requireActivity() as? K9Activity
|
||||
?: throw AssertionError("PermissionRationaleDialogFragment can only be used with K9Activity")
|
||||
return AlertDialog.Builder(requireContext())
|
||||
.setTitle(permission.rationaleTitle)
|
||||
.setMessage(permission.rationaleMessage)
|
||||
.setPositiveButton(R.string.okay_action) { _, _ ->
|
||||
val permissionUiHelper = requireActivity() as? PermissionUiHelper
|
||||
?: throw AssertionError("Activities using PermissionRationaleDialogFragment need to " +
|
||||
"implement PermissionUiHelper")
|
||||
|
||||
activity.requestPermission(permission)
|
||||
}
|
||||
}.create()
|
||||
permissionUiHelper.requestPermission(permission)
|
||||
}.create()
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val ARG_PERMISSION = "permission"
|
||||
|
||||
@JvmStatic
|
||||
fun newInstance(permission: Permission): PermissionRationaleDialogFragment {
|
||||
return PermissionRationaleDialogFragment().apply {
|
||||
arguments = bundleOf(ARG_PERMISSION to permission.name)
|
||||
|
|
|
@ -0,0 +1,37 @@
|
|||
package com.fsck.k9.ui.permissions
|
||||
|
||||
import android.content.pm.PackageManager
|
||||
import androidx.appcompat.app.AppCompatActivity
|
||||
import androidx.core.app.ActivityCompat
|
||||
import androidx.core.content.ContextCompat
|
||||
import timber.log.Timber
|
||||
|
||||
interface PermissionUiHelper {
|
||||
fun hasPermission(permission: Permission): Boolean
|
||||
fun requestPermissionOrShowRationale(permission: Permission)
|
||||
fun requestPermission(permission: Permission)
|
||||
}
|
||||
|
||||
class K9PermissionUiHelper(private val activity: AppCompatActivity) : PermissionUiHelper {
|
||||
override fun hasPermission(permission: Permission): Boolean {
|
||||
return ContextCompat.checkSelfPermission(activity, permission.permission) == PackageManager.PERMISSION_GRANTED
|
||||
}
|
||||
|
||||
override fun requestPermissionOrShowRationale(permission: Permission) {
|
||||
if (ActivityCompat.shouldShowRequestPermissionRationale(activity, permission.permission)) {
|
||||
val dialogFragment = PermissionRationaleDialogFragment.newInstance(permission)
|
||||
dialogFragment.show(activity.supportFragmentManager, FRAGMENT_TAG_RATIONALE)
|
||||
} else {
|
||||
requestPermission(permission)
|
||||
}
|
||||
}
|
||||
|
||||
override fun requestPermission(permission: Permission) {
|
||||
Timber.i("Requesting permission: " + permission.permission)
|
||||
ActivityCompat.requestPermissions(activity, arrayOf(permission.permission), permission.requestCode)
|
||||
}
|
||||
|
||||
companion object {
|
||||
private const val FRAGMENT_TAG_RATIONALE = "rationale"
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue