Android M Permissions: onRequestPermissionsResult() не вызывается
Я обновляю наше приложение, чтобы использовать новую систему разрешений M.
Это все работает помимо onRequestPermissionsResult (). Мне нужно проверить разрешение на нажатие кнопки, и если это успешно, отправить текстовое сообщение. Когда я даю разрешение на это, диалоговое окно закрывается, но оно не запускает отправку текста, пока я снова не нажму кнопку.
Я отладил и установил точки останова в методе onRequestPermissionsResult (), но он никогда не входит в него.
этот метод сначала вызывается:
private void askForPermission() {
String[] permissions = new String[]{Manifest.permission.SEND_SMS};
ActivityCompat.requestPermissions(getActivity(), permissions, PERMISSIONS_CODE);
}
и тогда мой ответ выглядит так:
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == PERMISSIONS_CODE) {
for (int i = 0; i < permissions.length; i++) {
String permission = permissions[i];
int grantResult = grantResults[i];
if (permission.equals(Manifest.permission.SEND_SMS)) {
if (grantResult == PackageManager.PERMISSION_GRANTED) {
onPPSButtonPress();
} else {
requestPermissions(new String[]{Manifest.permission.SEND_SMS}, PERMISSIONS_CODE);
}
}
}
}
}
кто-нибудь сталкивался с подобной проблемой?
Ценю любую помощь в этом.
Спасибо
22 ответов:
Я столкнулся с такой же проблемой и я нашел решение. При использовании библиотеки поддержки необходимо использовать правильные вызовы методов. Например:
- , когда в AppCompatActivity, вы должны использовать ActivityCompat.requestPermissions;
- , когда в android.поддержка.v4.приложение.Фрагмент, вы должны использовать просто requestPermissions (это метод экземпляра андроид.поддержка.v4.приложение.Фрагмент)
Если вы вызываете ActivityCompat.requestPermissions в фрагменте, the onRequestPermissionsResult обратный вызов вызывается для действия, а не для фрагмента.
надеюсь, что это помогает!
вы можете попробовать это:
requestPermissions(permissions, PERMISSIONS_CODE);Если вы вызываете этот код из фрагмента он имеет свой собственный метод requestPermissions. Я считаю, что проблема в том, что вы вызываете статический метод.
Pro совет, если вы хотите
onRequestPermissionsResult()В фрагмент:FragmentCompat.requestPermissions(Fragment fragment, String[] permissions, int requestCode)
Я надеюсь, что это работает штраф в размере
Деятельность :
ActivityCompat.requestPermissions(this,permissionsList,REQUEST_CODE);Для Фрагмент :
requestPermissions(permissionsList,REQUEST_CODE);
я тоже столкнулся с этой проблемой. Если вы хотите, чтобы действие, которое обрабатывает разрешения не в истории / последние, то вы будете испытывать соблазн изменить свой
AndroidManifest.xmlзапись.если вы установите действие, которое вы называете
requestPermissionsилиAppCompatActivity.requestPermissionsСandroid:noHistory="true" android:excludeFromRecents="true"в своем
AndroidManifest.xmlзатемonRequestPermissionsResult()не будет называться. Это верно, если ваша деятельность является производной отActivityилиAppCompatActivity.это можно исправить, удалив оба флага из ' AndroidManifest.формате XML и завершая свою деятельность с .
Если у вас
onRequestPermissionsResultв обоих активности и фрагмента, не забудьте позвонитьsuper.onRequestPermissionsResultв активности. Это не требуется во фрагменте, но это в деятельности.
внутри фрагмента, вам нужно позвонить:
FragmentCompat.requestPermissions(permissionsList, RequestCode)нет:
ActivityCompat.requestPermissions(Activity, permissionsList, RequestCode);
Если вы используете requestPermissions в фрагменте, он принимает 2 параметра вместо 3.
вы должны использовать
requestPermissions(permissions, PERMISSIONS_CODE);
Если по какой-то причине вы расширили пользовательское действие, расположенное в некоторой внешней библиотеке, которая не вызывает super, вам нужно будет вручную вызвать фрагмент super.onRequestPermissionsResult себя в своей деятельности onRequestPermissionsResult.
YourActivity extends SomeActivityNotCallingSuperOnRequestPermissionsResult{ Fragment requestingFragment;//the fragment requesting the permission ... @Override public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); if(requestingFragment!=null) requestingFragment.onRequestPermissionsResult(requestCode, permissions, grantResults); } ...
у вас checkPermissions функция для pre зефир устройств в FragmentCompat. Я использую вот так:
FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
я узнал, что важно, куда вы звоните
android.support.v4.app.Fragment.requestPermissions.если вы сделаете это в
onCreate(),onRequestPermissionsResult()- это никогда не называл.решение: позвоните в
onActivityCreated();@Override public void onActivityCreated(Bundle savedInstanceState) { super.onActivityCreated(savedInstanceState); if (ContextCompat.checkSelfPermission(context, Manifest.permission.READ_CONTACTS) == PackageManager.PERMISSION_DENIED) requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, 0); }
эта проблема на самом деле была вызвана NestedFragments. В основном большинство фрагментов мы расширяем HostedFragment, который в свою очередь расширяет CompatFragment. Наличие этих вложенных фрагментов вызвало проблемы, которые в конечном итоге были решены другим разработчиком в проекте.
Он делал некоторые вещи низкого уровня, такие как переключение бит, чтобы заставить это работать, поэтому я не слишком уверен в фактическом окончательном решении
/* use the object of your fragment to call the * onRequestPermissionsResult in fragment after * in activity and use different request Code for * both Activity and Fragment */ if (isFragment) mFragment.requestPermissions(permissions.toArray(new String[permissions.size()]),requestPermission); else ActivityCompat.requestPermissions(mActivity,permissions.toArray(new String[permissions.size()]),requestPermission);
Это будет работать..
@Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { super.onRequestPermissionsResult(requestCode, permissions, grantResults); }
Если вы вызываете этот код из фрагмента он имеет свой собственный метод requestPermissions.
Так что основная концепция, если вы находитесь в деятельности, то позвоните
ActivityCompat.requestPermissions(this, permissionsList, permissionscode);и если во фрагменте, просто позвоните
requestPermissions(permissionsList, permissionscode);
прежде чем вы проверите все в соответствии с приведенными выше ответами, убедитесь, что ваш код запроса не равен 0!!!
проверьте код onRequestPermissionsResult () в FragmentActivity.java:
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 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); } } }
на основе ответ goodgamerguy решение:
myFragment.this.requestPermissions(....)
private void showContacts() { if (getActivity().checkSelfPermission(Manifest.permission.READ_CONTACTS) != PackageManager.PERMISSION_GRANTED) { requestPermissions(new String[]{Manifest.permission.READ_CONTACTS}, PERMISSIONS_REQUEST_READ_CONTACTS); } else { doShowContacts(); } } @Override public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == PERMISSIONS_REQUEST_READ_CONTACTS && grantResults[0] == PackageManager.PERMISSION_GRANTED) { doShowContacts(); } }
можно использовать
requestPermissions(PERMISSIONS, MULTIPLE_PERMISSIONS_CODE);. Не используйте FragmentCompat, если вы используете v4.
обновление: видел чей-то ответ о вызове супер.onRequestPermissionResult () в Activity и это исправляет проблему с кодом запроса, о которой я упоминал, и вызывает фрагмент onRequestPermissionResult.
игнорировать этот материал:
для меня это был вызов onRequestPermissionResult активности, несмотря на то, что я вызывал фрагмент.requestPermission(...), Но он вернул результат с неправильным кодом запроса (111 превратился в 65647 почему ??? Я никогда не узнаю).
к счастью, это единственное разрешение, которое мы запрашиваем на этом экране, поэтому я просто игнорирую код запроса (не успеваю понять, почему это не правильно прямо сейчас)
у меня есть удивительное решение для достижения этого сделать BaseActivity такой.
public class BaseActivity extends AppCompatActivity { @Override protected void onCreate(@Nullable Bundle savedInstanceState) { super.onCreate(savedInstanceState); // Thread.setDefaultUncaughtExceptionHandler(new MyExceptionHandler(this)); } @Override public void onRequestPermissionsResult(int requestCode, @NonNull String permissions[], @NonNull int[] grantResults) { switch (requestCode) { case 1: { if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { CustomToast.getInstance().setCustomToast("Now you can share the Hack."); } else { Toast.makeText(this, "Permission denied to read your External storage", Toast.LENGTH_SHORT).show(); } } } }}
теперь вы можете вызвать код, чтобы попросить разрешения, как это
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);теперь каждый раз, когда это происходит в любом месте, будь то в вашем фрагменте или в любом действии, будет вызвана базовая активность.
спасибо
подробности
- Котлин 1.2.70
- проверено в minSdkVersion 19
- Android studio 3.1.4
алгоритм
модуль - камеры, расположение ....
- проверьте, если hasSystemFeature (если модуль в телефоне)
- проверьте, имеет ли пользователь доступ к модуль
- отправить запрос разрешения (попросите пользователя разрешить модуль использование)
особенности
- работа с действиями и фрагментами
- есть только один результат ответа
- можно проверить несколько модули в один запрос
решение
class PermissionType(val manifest_permission: String, val packageManager: String) { object Defined { val camera = PermissionType(Manifest.permission.CAMERA, PackageManager.FEATURE_CAMERA) val currentLocation = PermissionType(Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.FEATURE_LOCATION_GPS) } } class Permission { enum class PermissionResult { ACCESS_ALLOWED, ACCESS_DENIED, NO_SYSTEM_FEATURE; } interface ManagerDelegate { fun permissionManagerDelegate(result: Array<Pair<String, PermissionResult>>) } class Manager internal constructor(private val delegate: ManagerDelegate?) { private var context: Context? = null private var fragment: Fragment? = null private var activity: AppCompatActivity? = null private var permissionTypes: Array<PermissionType> = arrayOf() private val REQUEST_CODE = 999 private val semaphore = Semaphore(1, true) private var result: Array<Pair<String, PermissionResult>> = arrayOf() constructor(permissionType: PermissionType, delegate: ManagerDelegate?): this(delegate) { permissionTypes = arrayOf(permissionType) } constructor(permissionTypes: Array<PermissionType>, delegate: ManagerDelegate?): this(delegate) { this.permissionTypes = permissionTypes } init { when (delegate) { is Fragment -> { this.fragment = delegate this.context = delegate.context } is AppCompatActivity -> { this.activity = delegate this.context = delegate } } } private fun hasSystemFeature(permissionType: PermissionType) : Boolean { return context?.packageManager?.hasSystemFeature(permissionType.packageManager) ?: false } private fun hasAccess(permissionType: PermissionType) : Boolean { return if (Build.VERSION.SDK_INT < 23) true else { context?.checkSelfPermission(permissionType.manifest_permission) == PackageManager.PERMISSION_GRANTED } } private fun sendRequest(permissionTypes: Array<String>) { if (fragment != null) { fragment?.requestPermissions(permissionTypes, REQUEST_CODE) return } if (activity != null){ ActivityCompat.requestPermissions(activity!!, permissionTypes, REQUEST_CODE) } } fun check() { semaphore.acquire() AsyncTask.execute { var permissionsForSendingRequest: Array<String> = arrayOf() this.result = arrayOf() for (it in permissionTypes) { if (!hasSystemFeature(it)) { result += Pair(it.manifest_permission, PermissionResult.NO_SYSTEM_FEATURE) continue } if (hasAccess(it)) { result += Pair(it.manifest_permission, PermissionResult.ACCESS_ALLOWED) } else { permissionsForSendingRequest += it.manifest_permission } } if (permissionsForSendingRequest.isNotEmpty()) { sendRequest(permissionsForSendingRequest) } else { delegate?.permissionManagerDelegate(result) } } } fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { when (requestCode) { REQUEST_CODE -> { if (grantResults.isEmpty()) { return } for ((i,permission) in permissions.withIndex()) { for (item in this.permissionTypes) { if (permission == item.manifest_permission && i < grantResults.size) { result += if (grantResults[i] == PackageManager.PERMISSION_GRANTED) { Pair(item.manifest_permission, PermissionResult.ACCESS_ALLOWED) } else { Pair(item.manifest_permission, PermissionResult.ACCESS_DENIED) } break } } } delegate?.permissionManagerDelegate(result) } } semaphore.release() } } }использование в деятельности (во фрагменте то же самое)
class BaseActivity : AppCompatActivity(), Permission.ManagerDelegate { private lateinit var permissionManager: Permission.Manager override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.base_activity) permissionManager = Permission.Manager(arrayOf(PermissionType.Defined.camera, PermissionType.Defined.currentLocation), this) permissionManager.check() } override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) { super.onRequestPermissionsResult(requestCode, permissions, grantResults) permissionManager.onRequestPermissionsResult(requestCode, permissions, grantResults) } override fun permissionManagerDelegate(result: Array<Pair<String, Permission.PermissionResult>>) { result.forEach { println("!!! ${it.first} ${it.second}") // when (it.second) { // Permission.PermissionResult.NO_SYSTEM_FEATURE -> { // } // // Permission.PermissionResult.ACCESS_DENIED -> { // } // // Permission.PermissionResult.ACCESS_ALLOWED -> { // } // } } } }
У меня была аналогичная проблема принять я нажимал кнопку, чтобы сделать вызов, который вызывает callIntent. Сначала я проверил разрешение, если оно не предоставлено, я прошу разрешения и onRequestPermissionResult я вызываю разрешение проверки и снова вызываю.
@Override public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) { switch (requestCode) { case Constants.PERMISSIONS_REQUEST_CALL_PHONE: { if ( grantResults[0] == PackageManager.PERMISSION_GRANTED) { checkPermissionsAndCall(); } } } } public void checkPermissionsAndCall(){ if (Build.VERSION.SDK_INT > 22) { if(ContextCompat.checkSelfPermission(getContext(), Manifest.permission.CALL_PHONE) != PackageManager.PERMISSION_GRANTED){ requestPermissions( new String[]{Manifest.permission.CALL_PHONE}, Constants.PERMISSIONS_REQUEST_CALL_PHONE); } else{ callIntent(); } } }
Comments