如何处理 Activity 和 Fragment 之外的权限请求?
Posted
技术标签:
【中文标题】如何处理 Activity 和 Fragment 之外的权限请求?【英文标题】:How to handle permission requests outside Activity and Fragment? 【发布时间】:2016-07-28 20:00:31 【问题描述】:我正在开发一个需要访问外部存储的自定义复合视图。如何在不涉及外部方(即 Activity 或 Fragment)的情况下实现权限处理?
我知道我可以使用视图的上下文请求权限,但是如何在视图中处理onRequestPermissionsResult()
?甚至可能吗?
如果不可能,那么处理此类事情的最优雅的解决方案是什么?
【问题讨论】:
我知道你的帖子已经过时了,你可能已经从这个问题上移开了。有几个库可以让你做到这一点。 【参考方案1】:我正在开发一个需要访问外部存储的自定义复合视图
恕我直言,这是一个架构错误。 View
用于向用户显示内容,有时用于收集低级输入事件并将它们转换为更高阶的构造(例如,点击、滑动)。 View
不应与文件、数据库等建立任何连接。请参阅 MVC、MVP、MVVM 和类似的 GUI 架构模式。
WebView
不遵守这一点,结果会导致问题(例如,在主应用程序线程上进行磁盘 I/O)。
如何在不涉及外部方(即 Activity 或 Fragment)的情况下实现权限处理?
你不能。请求权限是 Activity 或 Fragment 的责任,大概在您的视图需要这些数据之前。
处理这样的事情最优雅的解决方案是什么?
将此View
的数据访问部分提取到由活动或片段管理的其他内容中,其中可以管理与该数据访问相关的线程、权限和其他工作。
【讨论】:
【参考方案2】:如果没有 Activity 的实例,您将无法使用权限,但您可以让您的代码更漂亮。如果你想发送一个请求并在一个地方处理它,那么你可以使用下面的例子。
只需创建一个看起来像 BaseActivity 的东西并把这样的代码放在那里
public class PermActivity extends Activity
interface OnPermissionCallback
void requestResult(String[] permissions, int[] grantResults);
private SparseArray<OnPermissionCallback> permissionCallback = new SparseArray<>();
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
permissionCallback.get(requestCode).requestResult(permissions, grantResults);
public void addPermissionCallback(int requestCode, OnPermissionCallback callback)
permissionCallback.put(requestCode, callback);
现在在我们的客户端代码中,我们可以做类似的事情
class SomeClasThatWorksWithPerms
private PermActivity activity;
public SomeClasWorksWithPerms(PermActivity activity)
this.activity = activity;
void foo()
if (ContextCompat.checkSelfPermission(activity, WRITE_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED)
// do something
else
activity.addPermissionCallback(0, (perms, grantResults) ->
if (grantResults[0] == PackageManager.PERMISSION_GRANTED)
foo(); // try one more
);
activity.requestPermissions(new String[]WRITE_EXTERNAL_STORAGE, 0);
我已经通过请求代码使用了备用数组和索引,但您可以使用另一种存储回调的方式。
这是一个非常简单的例子,你可以在那里看到更严重的东西 https://github.com/mrizyver/Fl_Launcher/blob/master/app/src/main/java/com/izyver/fllauncher/presentation/activity/FlActivity.kt - 如您所见,这是活动 https://github.com/mrizyver/Fl_Launcher/blob/master/app/src/main/java/com/izyver/fllauncher/presentation/loaders/WallpaperLoader.kt - 使用权限的客户端代码
【讨论】:
【参考方案3】:假设您需要在用户单击“确定”或其他按钮时从对话框片段中调用 requestPermissionLauncher。这是在 MainActivity 中找到的 requestPermissionLauncher,或者您可以将其放在调用对话框片段的任何其他活动中。
public ActivityResultLauncher<String> requestPermissionLauncher =
registerForActivityResult(new ActivityResultContracts.RequestPermission(), isGranted ->
if (isGranted)
// Permission is granted. Continue the action or workflow in your
// app.
else
// Explain to the user that the feature is unavailable because the
// features requires a permission that the user has denied. At the
// same time, respect the user's decision. Don't link to system
// settings in an effort to convince the user to change their
// decision.
);
这里是代码源,如果你想参考https://developer.android.com/training/permissions/requesting
然后在您的对话框片段中使用以下代码调用实例 requestPermissionLauncher
((MainActivity)getContext()).requestPermissionLauncher.launch(Manifest.permission.[*your permission goes here*]);
【讨论】:
【参考方案4】:只有在活动和片段中才有可能。
您可以做的是在您的视图中复制public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
,并在上下文所在的活动或片段中的相应方法中调用该方法。
【讨论】:
以上是关于如何处理 Activity 和 Fragment 之外的权限请求?的主要内容,如果未能解决你的问题,请参考以下文章