我已经开始研究Android M运行时权限了。在这里,我面临的问题是,如果从requestPermissions
类调用Dialog Fragment
,则onRequestPermissionsResult
不会在同一Dialog fragment
类中调用requestPermissions
。但是,如果从Activity
类或Fragment
类调用onRequestPermissionsResult
,则会在同一个类中调用public class ContactPickerDialog extends DialogFragment {
private static final int READ_CONTACTS_REQUEST_CODE = 12;
private Context mContext;
private void loadContact() {
if(hasPermission(mContext, Manifest.permission.READ_CONTACTS)){
new ContactSyncTask().execute();
} else {
this.requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, READ_CONTACTS_REQUEST_CODE);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
Logger.d("TAG", "dialog onRequestPermissionsResult");
switch (requestCode) {
case READ_CONTACTS_REQUEST_CODE:
// Check Permissions Granted or not
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
new ContactSyncTask().execute();
} else {
// Permission Denied
Toast.makeText(getActivity(), "Read contact permission is denied", Toast.LENGTH_SHORT).show();
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
private static boolean hasPermission(Context context, String permission){
return ContextCompat.checkSelfPermission(context, permission) == PackageManager.PERMISSION_GRANTED;
}
}
方法。
以下是我的示例代码:
requestPermissions
在代码中,我调用Dialog Fragment
类的ContactPickerDialog dialog = new ContactPickerDialog();
dialog.show(getChildFragmentManager(), "Contact Picker");
方法。所以我期待在同一个班级得到结果。
感谢任何帮助。提前谢谢!
修改 在这里,我将添加更多细节,以便对其他人更有帮助。 以前我使用getChildFragmentManager()来显示DialogFragment。
ContactPickerDialog dialog = new ContactPickerDialog();
dialog.show(getActivity().getSupportFragmentManager(), "Contact Picker");
但是 @CommonWare 要求我使用activity来显示DialogFragment。我做了以下更改并且有效。
JComboBox execBrokerCombobox = new JComboBox();
String[] obj = new String[5];
for (i = 0; i < 5; i++) {
obj[i] = "Option" + (i+1);
}
AutoCompleteSupport.install(jexecBrokerCombobox, GlazedLists.eventListOf(obj));
答案 0 :(得分:106)
如果您位于支持库的Fragment
内,请直接致电requestPermissions()
,系统会回复您的片段onRequestPermissionsResult()
。
如果您致电ActivityCompat.requestPermissions()
,那么它将会被回拨Activity
onRequestPermissionsResult()
。
答案 1 :(得分:54)
似乎有a bug in Android,其中嵌套片段不支持onRequestPermissionsResult()
回调。对于DialogFragment
,解决方法似乎是让片段想要显示对话框调用托管活动的方法,并且活动显示DialogFragment
本身。
答案 2 :(得分:13)
此issue似乎已修复Android Support Library 23.3.0及以上版本。
如果您正在使用Support v4 Fragments,则现在将嵌套片段 接收onRequestPermissionsResult()的回调。
编辑:@AndrewS,这里有你可以更新的方式。
在build.gradle(app)文件中,更改以下行以使用最新版本的最新支持库24.0.0:
dependencies {
compile 'com.android.support:appcompat-v7:24.0.0'
}
答案 3 :(得分:5)
修改强>
我建议使用新版本的支持库23.3.0,因为Google fixed issue with not calling onRequestPermissionsResult
,但如果由于某些原因需要使用旧版本,请参阅下面的原始答案。
原始答案:
我正在使用下一个解决方法(与easyPermissions库一起使用):
<强> BaseFragment:强>
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
/** child v4.fragments aren't receiving this due to bug. So forward to child fragments manually
* https://code.google.com/p/android/issues/detail?id=189121
*/
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
// it is possible that fragment might be null in FragmentManager
for (Fragment fragment : fragments) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
}
}
<强> BaseActivity:强>
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
Fragment fragment = getSupportFragmentManager().findFragmentById(getFragmentContainer())
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode&0xff, permissions, grantResults);
}
}
<强>用法:强>
public class SomeFragment extends BaseFragment implements EasyPermissions.PermissionCallbacks {
private static final int PICK_CONTACT = 1;
private static final int READ_CONTACTS_PERM = 2;
// some code
@AfterPermissionGranted(READ_CONTACTS_PERM)
private void pickContactWithPermissionsCheck() {
if (EasyPermissions.hasPermissions(getContext(), Manifest.permission.READ_CONTACTS)) {
// Have permission
pickContactForResult();
} else {
// Request one permission
EasyPermissions.requestPermissions(this, getString(R.string.read_contacts_permission_explanation),
READ_CONTACTS_PERM, Manifest.permission.READ_CONTACTS);
}
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
// FIXME problem with incorrect requestCode coming to callback for Nested fragments
// More information here - https://code.google.com/p/android/issues/detail?id=189121
if (isVisible() && Arrays.asList(permissions).contains(Manifest.permission.READ_CONTACTS)) {
requestCode = READ_CONTACTS_PERM;
}
// EasyPermissions handles the request result.
EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
}
}
答案 4 :(得分:4)
有一件事对我有帮助。 当您从嵌套片段请求权限时,请使用getParent,如此
fragment.getParentFragment().requestPermissions((new String[]
{Manifest.permission.READ_CONTACTS}), requestCode);
然后覆盖父片段onRequestPermissionResult并检查相应的requestCode。
希望它也能帮到你。
答案 5 :(得分:4)
如果嵌套片段有问题,可以从父片段
请求权限getParentFragment().requestPermissions(new String[]{permission}, requestCode);
然后将回调转发给子片段
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grants) {
List<Fragment> fragments = getChildFragmentManager().getFragments();
if (fragments != null) {
for (Fragment fragment : fragments) {
if (fragment != null) {
fragment.onRequestPermissionsResult(requestCode, permissions, grants);
}
}
}
}
答案 6 :(得分:4)
我遇到了没有嵌套片段的问题,其中活动显示了对话框片段,结果未通过。
添加
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
活动的onRequestPermissionsResult()
解决了这个问题。
答案 7 :(得分:1)
如果您查看该片段的requestPermissions
方法的文档,您会发现仍然需要在清单中声明权限:
如果不是这种情况,则不会调用该片段自己的onRequestPermissionsResult
。
相反,活动的onRequestPermissionsResult
被调用,但没有任何效果。
因此,应按照以下步骤在片段内划分权限:
1。在清单中声明权限
<uses-permission android:name="android.permission.CAMERA"/>
在应用程序标签之前输入此内容。
2。检查片段中的权限
if (ActivityCompat.checkSelfPermission(context, permission)
!= PackageManager.PERMISSION_GRANTED) {
requestPermissions(
arrayOf(Manifest.permission.CAMERA),
REQUEST_CODE_CAMERA_PERMISSION)
}
3。等待片段中的权限结果
override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
when (requestCode) {
REQUEST_CODE_CAMERA_PERMISSION -> {
val granted = grantResults.isNotEmpty()
&& permissions.isNotEmpty()
&& grantResults[0] == PackageManager.PERMISSION_GRANTED
&& !ActivityCompat.shouldShowRequestPermissionRationale(activity, permissions[0])
when (granted) {
true -> openCamera()
else -> proceedWithoutPermission()
}
}
}
4。确保您不覆盖活动的 onRequestPermissionsResult
覆盖活动的onRequestPermissionsResult
将导致片段的片段不响应。
答案 8 :(得分:0)
我这样做了
public class DialogFragmentSMS extends DialogFragment implements View.OnClickListener {
public static DialogFragmentSMS frag;
private static View view;
private static ViewGroup parent;
private EditText editTextMensagem;
private String celular;
private final static int SMS_REQUEST = 20;
public DialogFragmentSMS() {
}
public static DialogFragmentSMS newInstance(String celular)
{
Bundle args = new Bundle();
args.putString("celular", celular);
frag = new DialogFragmentSMS();
frag.setArguments(args);
return frag;
}
@Override
public void onCreate(Bundle saveInstaceState)
{
super.onCreate(saveInstaceState);
}
@Override
public void onClick(View v) {
if (!PermissaoUtils.hasPermission(getActivity(), Manifest.permission.SEND_SMS)) {
//PermissaoUtils.requestPermissions(getActivity(), new String[]{Manifest.permission.SEND_SMS}, SMS_REQUEST);
frag.requestPermissions(new String[]{Manifest.permission.SEND_SMS}, SMS_REQUEST);
}else{
if (validaCampos()) {
SmsManager smsManager = SmsManager.getDefault();
smsManager.sendTextMessage("0" + celular, null, editTextMensagem.getText().toString(), null, null);
Toast.makeText(getActivity(), R.string.sms_enviado, Toast.LENGTH_SHORT).show();
getDialog().getWindow().setSoftInputMode(WindowManager.LayoutParams.SOFT_INPUT_STATE_HIDDEN);
frag.dismiss();
}
}
}
我的班级许可
public class PermissaoUtils
{
public static boolean useRunTimePermissions() {
return Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1;
}
public static boolean hasPermission(Activity activity, String permission) {
if (useRunTimePermissions()) {
return activity.checkSelfPermission(permission) == PackageManager.PERMISSION_GRANTED;
}
return true;
}
public static void requestPermissions(Activity activity, String[] permission, int requestCode) {
if (useRunTimePermissions()) {
activity.requestPermissions(permission, requestCode);
}
}
}
答案 9 :(得分:0)
除了Nino Handler的答案的结尾部分以及对于仍然对此有疑问的任何人,请确保如果您确实在对话框片段的父活动/片段中覆盖了onRequestPermissionsResult,请在此处调用super.onRequestPermissionsResult。< / p>
我在对话框片段的父活动中重写onRequestPermissionsResult,但忽略了在那里调用super方法。一旦将其更改为调用super方法,它将正确地委派给对话框片段中的onRequestPermissionsResult。
答案 10 :(得分:0)
我在Android Manifest中添加了composer.lock
,它对我有用,我不知道它如何影响其他功能。