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.поддержка.В4.приложение.Фрагмент, вы должны использовать просто requestPermissions (это метод экземпляра андроид.поддержка.В4.приложение.Фрагмент)
Если вы вызываете ActivityCompat.requestPermissions в фрагменте,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);
я тоже столкнулся с этой проблемой. Если вы хотите действие, которое обрабатывает разрешения не в истории / recents, то у вас будет соблазн изменить свой AndroidManifest.xml
запись.
если вы установите действие, которое вы вызываете requestPermissions
или AppCompatActivity.requestPermissions
С
android:noHistory="true"
android:excludeFromRecents="true"
в своем AndroidManifest.xml
затем onRequestPermissionsResult()
не будет называться. Это верно, если ваша деятельность происходит от Activity
или AppCompatActivity
.
это можно исправить, удалив оба флага из ' AndroidManifest.формате XML и завершение вашей деятельности с .
Если у вас onRequestPermissionsResult
как в activity, так и в fragment обязательно вызовите 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 Marshmallow в 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);
}
}
}
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.
UPDATE: видел чей-то ответ о вызове super.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();
}
}
}