如果在片段和活动中都定义了 onRequestPermissionsResult,则不会在片段中调用
Posted
技术标签:
【中文标题】如果在片段和活动中都定义了 onRequestPermissionsResult,则不会在片段中调用【英文标题】:onRequestPermissionsResult not being called in fragment if defined in both fragment and activity 【发布时间】:2016-06-29 14:16:17 【问题描述】:我有一个片段,其中我有 recyclerview 并使用 recyclerview 适配器在这个 recyclerview 中设置数据。
现在,我在适配器的列表项中点击了一个按钮,我需要在 android 中检查 READ_EXTERNAL_STORAGE 权限以获取 android 中的新权限模型。
我在这个适配器的片段中创建了一个新函数来检查是否授予权限,如果尚未授予权限,则请求权限。
我已将 MyFragment.this 作为适配器中的参数传递,并在适配器中单击按钮时调用片段的方法。
我已经使用下面的代码在片段中调用 requestPermission。
if(ContextCompat.checkSelfPermission(mContext, Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)
requestPermissions(new String[]Manifest.permission.READ_EXTERNAL_STORAGE,
ConstantVariables.READ_EXTERNAL_STORAGE);
我已经使用以下代码覆盖了片段中的onRequestPermissionsResult
方法:
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults)
switch (requestCode)
case ConstantVariables.READ_EXTERNAL_STORAGE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
// permission was granted, proceed to the normal flow.
startImageUploading();
else
但它并没有被调用,而是被调用了这个 Activity 的 onRequestPermissionsResult 方法。
我也在片段的父活动中定义了相同的 onRequestPermissionsResult 方法,并且它被调用了。
我无法移除 Activity 的 onRequestPermissionsResult 方法,但想在我向 Fragment 请求权限时调用 Fragment 的 onRequestPermissionsResult 方法。 我怎样才能做到这一点?我在这里做错了什么吗,如果有人在这里有想法,请帮助我。
【问题讨论】:
参考这个链接run time permissions in fragment这是确切的解决方案 【参考方案1】:编辑答案以涵盖更广泛的问题
我认为您混淆了片段和活动的方法。上个月我的项目也有类似的问题。请检查您是否最终有以下内容:
-
在 AppCompatActivity 中使用方法 ActivityCompat.requestpermissions
在 v4 支持片段中,您应该使用 requestpermissions
关键是如果您在片段中调用 AppcompatActivity.requestpermissions 则回调将进入活动而不是片段
确保从活动的
onRequestPermissionsResult
调用super.onRequestPermissionsResult
。
看看有没有帮助。
【讨论】:
只是仔细检查确保您的活动中设置了 super.onrequestpermissionresult 当我使用requestpermissions
请求权限时,在活动的onrequestpermissionresult中添加super.onrequestpermissionresult
会调用片段的onrequestpermissionresult。现在工作正常,非常感谢.. :)
活动回调中缺少 super.onrequestpermissionresult,导致我的片段回调没有被调用
requestPermissions() 需要 API 级别 23。是否有其他解决方案向后兼容 API 级别 21?
@msc87 1.在onRequestPermissionsResult的activity和fragment中,第一行应该是:super.onRequestPermissionsResult(requestCode, permissions, grantResults); 2.in你所在的fragment识别未授予的权限,只需像这样调用 requestPermission 方法:requestPermissions(new String[]Manifest.permission.CALL_PHONE, MY_PERMISSIONS_REQUEST_CALL_PHONE);【参考方案2】:
这个问题实际上是由 NestedFragments 引起的。基本上,我们扩展了 HostedFragment 的大多数片段,而 HostedFragment 又扩展了 CompatFragment。拥有这些嵌套片段会导致问题,最终由该项目的另一位开发人员解决。
他正在做一些低级的事情,比如位切换来让它工作,所以我不太确定实际的最终解决方案
【讨论】:
您可以提供一个链接,而不是复制答案 - ***.com/a/33081173/630833【参考方案3】:private void showContacts()
if (getActivity().checkSelfPermission(Manifest.permission.READ_EXTERNAL_STORAGE)
!= PackageManager.PERMISSION_GRANTED)
requestPermissions(new String[]Manifest.permission.READ_EXTERNAL_STORAGE,
PERMISSIONS_REQUEST_READ_STORAGE);
else
doShowContacts();
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions,
int[] grantResults)
if (requestCode == PERMISSIONS_REQUEST_READ_STORAGE
&& grantResults[0] == PackageManager.PERMISSION_GRANTED)
doShowContacts();
更改权限
【讨论】:
您好 user2002721;您的代码可能是正确的,但在某些上下文中它会做出更好的答案;例如,您可以解释这个提议的更改如何以及为什么会解决提问者的问题,可能包括指向相关文档的链接。这将使它对他们更有用,对正在寻找类似问题的解决方案的其他网站读者也更有用。 如果您尝试访问 grantResults 的索引 0 而不先检查长度,程序可能会抛出数组越界异常。它发生在我的程序中。我将 grantResults 的 if 语句分隔为内部 if 语句以防止这种情况发生,现在它工作正常。【参考方案4】:验证PERMISSION_REQUEST_CODE
inonRequestPermissionsResult
和 yourFragment
内部是否包含相同的值。
【讨论】:
【参考方案5】:片段上的方法 requestPermissions
需要 API 级别 23 或更高。
如果您的应用面向较低版本,您可以使用
FragmentCompat.requestPermissions(this,
new String[]Manifest.permission.READ_EXTERNAL_STORAGE,
ConstantVariables.READ_EXTERNAL_STORAGE);
首先需要添加 support-v13 依赖:
implementation "com.android.support:support-v13:$supportLibVersion"
【讨论】:
FragmentCompat 已从 27.1.0 版本中弃用【参考方案6】:我向片段请求位置许可,在片段中,我需要更改:
ActivityCompat.requestPermissions(getActivity(), new String[]
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_REQ_CODE);
到这里:
requestPermissions(new String[]
Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_REQ_CODE);
然后在片段中调用了 onRequestPermissionsResult。
【讨论】:
像魅力一样工作:) 它不能与 kotlin 一起工作,你能帮我吗?这里也使用了这个 requestPermissions(context as Activity ,permissionList.toTypedArray(), MY_PERMISSIONS_REQUEST) 谢谢 :),你节省了我的时间【参考方案7】:对于 tragetSDK 28,SDK 检查 (>23) 和从片段请求权限将起作用。 ActivityCompat.requestPermissions 失败(如果您将请求代码设置为低于 65536,则会出现权限对话框,如果用户允许该权限,则提供权限,但不会发生回调。但如果您设置高于 65536,则 ActivityCompat.requestPermissions 将立即失败。我不知道这个逻辑背后的原因。可能是错误或故意的)。
工作代码:
if (Build.VERSION.SDK_INT >= 23)
requestPermissions(new String[]Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION, LOCATION_ACCESS_REQUEST);
【讨论】:
你不需要做版本检查。在 23 以下的版本中,它只会返回“授予的权限”值。此处开发人员的选择:为简单起见避免使用“if”块或在不需要时避免请求调用【参考方案8】:这个接受的答案对我不起作用,所以我找到了自己的解决方案,解释如下:
1.首先我在片段中创建了一个方法:
public static void MyOnRequestPermissionResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
if (requestCode == 1 && grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED)
Log.d(TAG, "Permission: true");
else
Log.d(TAG, "permission: false");
2.然后从它的底层活动中调用它:
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
if(requestCode ==1)
SignupFragment.MyOnRequestPermissionResult(requestCode, permissions, grantResults);
它正在工作......
【讨论】:
【参考方案9】:如果您使用 Kotlin,您应该明确指定您正在调用片段方法,而不是活动
fragment.requestPermissions(permissions, PERMISSIONS_CODE);
Android M Permissions: onRequestPermissionsResult() not being called
Request runtime permissions from v4.Fragment and have callback go to Fragment?
【讨论】:
【参考方案10】:这是人们在编写棉花糖时常犯的错误。
在 AppCompatActivity 中,应该使用 ActivityCompat.requestPermissions; 在 android.support.v4.app.Fragment 中,你应该简单地使用 requestPermissions(这是 android.support.v4.app.Fragment 的一个实例方法) 如果你在片段中调用 ActivityCompat.requestPermissions,onRequestPermissionsResult 回调会在 Activity 而不是片段上调用。
requestPermissions(permissions, PERMISSIONS_CODE);
如果您从片段中调用此代码,它有自己的 requestPermissions 方法。
所以基本概念是,如果你在一个 Activity 中,那么调用
ActivityCompat.requestPermissions(this,
new String[]Manifest.permission.CAMERA,
MY_PERMISSIONS_REQUEST_CAMERA);
如果在 Fragment 中,只需调用
requestPermissions(new String[]Manifest.permission.CAMERA,
MY_PERMISSIONS_REQUEST_CAMERA);
作为参考,我已经从这个链接https://www.coderzheaven.com/2016/10/12/onrequestpermissionsresult-not-called-on-fragments/得到了答案
【讨论】:
【参考方案11】:我有同样的问题。您的片段可以从活动布局初始化。 像这样:
main_activty.xml
<fragment
android:id="@+id/fragment"
android:name="com.exampe.SomeFragment"
android:layout_
android:layout_ />
当我改用FragmentTransaction
时,这个问题已经解决了
【讨论】:
【参考方案12】:在低于 23 的 API 中,您可以在 Activity 中创建一个接口,然后在子 Fragment 中实现它,当您获得权限请求结果时,Activity 将其传递给 Fragment 中实现的接口。 就这么简单:)
【讨论】:
【参考方案13】:改变这个:
ActivityCompat.requestPermissions(
activity,
arrayOf(Manifest.permission.READ_CONTACTS),
PERMISSIONS_REQUEST_READ_CONTACTS
)
到这个:
requestPermissions(
arrayOf(Manifest.permission.READ_CONTACTS),
PERMISSIONS_REQUEST_READ_CONTACTS
)
【讨论】:
下一个是在fragment中使用(onRequestPermissionsResult在fragment中调用),ActivityCompat版本是在onRequestPermissionsResult在Activity中时使用的。【参考方案14】:你可以调用下面的 Fragment 方法
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
switch (requestCode)
case REQUEST_CODE:
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0 &&
grantResults[0] == PackageManager.PERMISSION_GRANTED)
// Permission is granted. Continue the action or workflow
// in your app.
doActionBecauseNowYouCanBro();
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.
showWhyRequestPermissionsAndDontBlockUserItsCalledManners();
return;
// Other 'case' lines to check for other
// permissions this app might request.
【讨论】:
【参考方案15】:在片段中,您不应将 ActivityCompat 用于 requestPermissions,您只需使用 requestPermissions 并在方法中传递两个参数。
-
权限字符串
请求代码。
对于经验:
requestPermissions(new String[]android.Manifest.permission.READ_EXTERNAL_STORAGE, STORAGE_PERMISSION_CODE);
【讨论】:
【参考方案16】:当我们从片段中请求权限时,android会更改我们的requestCode
requestPermissionsFromFragment
这是来自 FragmetActivity 的代码:
void requestPermissionsFromFragment(@NonNull Fragment fragment, @NonNull String[] permissions,
int requestCode)
if (requestCode == -1)
ActivityCompat.requestPermissions(this, permissions, requestCode);
return;
checkForValidRequestCode(requestCode);
try
mRequestedPermissionsFromFragment = true;
int requestIndex = allocateRequestIndex(fragment);
ActivityCompat.requestPermissions(this, permissions,
((requestIndex + 1) << 16) + (requestCode & 0xffff));
finally
mRequestedPermissionsFromFragment = false;
你可以看到 (requestIndex + 1) 以及何时
onRequestPermissionsResult
android 检查请求代码是否是从 Fragment 发送的,它将结果传递给 Fragment 否则它不会将它传递给 Fragment 这是来自 FragmentActivity 的代码:
enter code here@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults)
mFragments.noteStateNotSaved();
int index = (requestCode >> 16) & 0xffff;
if (index != 0)
index--;
String who = mPendingFragmentActivityResults.get(index);
mPendingFragmentActivityResults.remove(index);
if (who == null)
Log.w(TAG, "Activity result delivered for unknown Fragment.");
return;
Fragment frag = mFragments.findFragmentByWho(who);
if (frag == null)
Log.w(TAG, "Activity result no fragment exists for who: " + who);
else
frag.onRequestPermissionsResult(requestCode & 0xffff, permissions, grantResults);
总结
因此,如果您调用 activity.requestPermission() 或 ActivityCompat.requestPermission,它会将结果传递给您的 Activity,如果您调用 fragment.requestPermission(),它会将结果传递给您的 Activity AND片段
【讨论】:
【参考方案17】:如果你想进入你的 Fragment 的onPermissionResult
,你必须调用Fragment.requestPermission()
。
【讨论】:
以上是关于如果在片段和活动中都定义了 onRequestPermissionsResult,则不会在片段中调用的主要内容,如果未能解决你的问题,请参考以下文章