我正在开发一个需要访问外部存储的自定义复合视图。如何在不涉及外部各方(即活动或片段)的情况下实施权限处理?
我知道我可以使用View的上下文请求权限,但是如何在View中处理onRequestPermissionsResult()
?它甚至可能吗?
如果不可能,处理这样的事情最优雅的解决方案是什么?
答案 0 :(得分:6)
恕我直言,这是一个架构错误。我正在开发一个需要访问外部存储的自定义复合视图
View
用于向用户显示内容,有时用于收集低级输入事件并将其转换为更高阶的构造(例如,点击,滑动)。 View
不应与文件,数据库等有任何连接。请参阅MVC,MVP,MVVM和类似的GUI架构模式。
不遵守此规则的 WebView
会导致问题(例如,在主应用程序线程上执行磁盘I / O)。
如何在不涉及外部各方的情况下实施权限处理,即活动或片段?
你做不到。活动或片段负责请求许可,大概是在您的视图需要此数据之前。
处理这样的事情最优雅的解决方案是什么?
将此View
的数据访问部分提取到由活动或片段管理的其他内容中,其中可以管理与该数据访问相关联的线程,权限和其他工作。
答案 1 :(得分:0)
没有活动实例,就无法使用权限,但可以使代码更漂亮。如果要发送请求并在一个地方处理,则可以使用以下示例。
只需创建类似于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);
}
}
}
我在请求代码中使用了spareArray和索引,但是您可以使用另一种存储回调的方式。
这是一个非常简单的示例,您可以在那里看到更严重的内容 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-具有权限的客户代码
答案 2 :(得分:0)
让我们假设您需要在用户单击“确定”或其他按钮时从对话框片段调用 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*]);
答案 3 :(得分:-2)
只有在活动和碎片中才有可能。
您可以在视图中复制public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults)
,并在上下文所在的活动或片段中的相应方法中调用该方法。