Android M Permissions: onRequestPermissionsResult () n'est pas appelé
Je mets à jour notre application pour utiliser le nouveau système D'autorisations M. Tout fonctionne en plus de onRequestPermissionsResult(). Je dois vérifier une autorisation sur une pression de bouton, et si elle réussit, envoyer un message texte. Lorsque j'accorde la permission de le faire, la boîte de dialogue se ferme, mais elle ne déclenche pas L'envoi de texte jusqu'à ce que j'appuie à nouveau sur le bouton.
J'ai débogué et défini des points d'arrêt dans la méthode onRequestPermissionsResult() mais elle n'y va jamais.
Cette méthode est appelée premier:
private void askForPermission() {
String[] permissions = new String[]{Manifest.permission.SEND_SMS};
ActivityCompat.requestPermissions(getActivity(), permissions, PERMISSIONS_CODE);
}
Et puis Mon Rappel ressemble à ceci:
@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);
}
}
}
}
}
Quelqu'un a-t-il rencontré un problème similaire? Appréciez toute aide avec cela. Merci
22 réponses
J'ai rencontré le même problème et je viens de trouver la solution. Lorsque vous utilisez la bibliothèque de Support, vous devez utiliser les appels de méthode corrects. Par exemple:
- Lorsque dans AppCompatActivity, vous devez utiliser ActivityCompat.requestPermissions ;
- Quand dans android.soutien.v4.App.Fragment, vous devez utiliser simplement requestPermissions (c'est une méthode d'instance de android.soutien.v4.App.Fragment)
Si vous appelez ActivityCompat.requestPermissions dans un fragment, le rappel onRequestPermissionsResult est appelé sur l'activité et non sur le fragment.
J'espère que cela aide!
, Vous pouvez essayer ceci:
requestPermissions(permissions, PERMISSIONS_CODE);
Si vous appelez ce code à partir d'un fragment, il a sa propre méthode requestPermissions. Je crois que le problème est que vous appelez la méthode statique.
Astuce Pro si vous voulez le onRequestPermissionsResult()
dans un fragment:
FragmentCompat.requestPermissions(Fragment fragment, String[] permissions, int requestCode)
J'espère que cela fonctionne bien
Pour L'Activité:
ActivityCompat.requestPermissions(this,permissionsList,REQUEST_CODE);
Pour Le Fragment:
requestPermissions(permissionsList,REQUEST_CODE);
, j'ai rencontré ce problème aussi. Si vous voulez que l'activité qui gère les autorisations ne figure pas dans l'historique/les récents, vous serez tenté de changer votre entrée AndroidManifest.xml
.
Si vous définissez l'activité que vous appelez requestPermissions
ou AppCompatActivity.requestPermissions
avec
android:noHistory="true"
android:excludeFromRecents="true"
Votre AndroidManifest.xml
, puis onRequestPermissionsResult()
ne sera pas appelé. Cela est vrai si votre activité est dérivée de Activity
ou AppCompatActivity
.
Cela peut être corrigé en supprimant les deux drapeaux de ' AndroidManifest.xml' et terminer votre activité avec finishAndRemoveTask()
à la place.
Si vous avez onRequestPermissionsResult
dans activity et fragment, assurez-vous d'appeler super.onRequestPermissionsResult
dans activity. Il n'est pas nécessaire dans fragment, mais il est en activité.
À l'intérieur du fragment, vous devez appeler:
FragmentCompat.requestPermissions(permissionsList, RequestCode)
Pas:
ActivityCompat.requestPermissions(Activity, permissionsList, RequestCode);
Si vous utilisez requestPermissions dans fragment, il accepte 2 paramètres au lieu de 3.
Vous devriez utiliser requestPermissions(permissions, PERMISSIONS_CODE);
Si, pour une raison quelconque, vous avez étendu une activité personnalisée située dans une bibliothèque externe qui n'appelle pas le SUPER, vous devrez appeler manuellement le Super Fragment.onRequestPermissionsResult vous-même dans votre activité 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);
}
...
Vous avez la fonctioncheckpermissions pour les périphériques pré Marshmallow dans FragmentCompat. J'utilise comme ceci:
FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
, j'ai découvert que est importante où vous appelez android.support.v4.app.Fragment.requestPermissions
.
Si vous le faites dans onCreate()
, onRequestPermissionsResult()
n'est jamais appelée.
Solution: appelez-le dans 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);
}
Ce problème a été causé par NestedFragments. Fondamentalement, la plupart des fragments que nous avons étendent un HostedFragment qui à son tour étend un CompatFragment. Avoir ces fragments imbriqués a causé des problèmes qui ont finalement été résolus par un autre développeur sur le projet.
Il faisait des choses de bas niveau comme la commutation de bits pour que cela fonctionne, donc je ne suis pas trop sûr de la solution finale réelle
/* 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);
Cela fonctionnera..
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
Si vous appelez ce code à partir d'un fragment, il a sa propre méthode requestPermissions.
Le concept de base est donc, si vous êtes dans une activité, appelez
ActivityCompat.requestPermissions(this,
permissionsList,
permissionscode);
Et si dans un Fragment, appelez simplement
requestPermissions(permissionsList,
permissionscode);
Avant de tout vérifier selon les réponses ci-dessus, assurez-vous que votre code de demande n'est pas 0!!!
Vérifiez le code de onRequestPermissionsResult () dans Fragmentaactivity.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);
}
}
}
Basé sur la réponse de goodgamerguy la solution est:
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();
}
}
Vous pouvez utiliser requestPermissions(PERMISSIONS, MULTIPLE_PERMISSIONS_CODE);
. N'utilisez pas FragmentCompat si vous utilisez v4.
UPDATE: j'ai vu la réponse de quelqu'un d'autre à propos de l'appel de super.onRequestPermissionResult() dans Activity et qui corrige le problème de code de requête que j'ai mentionné et appelle onRequestPermissionResult du fragment.
Ignorer ce genre de choses:
Pour moi, il appelait onRequestPermissionResult de l'activité malgré que j'appelle fragment.requestPermission(...), Mais il a renvoyé le résultat avec un requestCode incorrect (111 transformé en 65647 pourquoi ??? Je ne le saurai jamais).
Heureusement c'est la seule autorisation que nous demandons sur cet écran, donc j'ignore simplement le code de la demande (je n'ai pas le temps de comprendre pourquoi ce n'est pas correct en ce moment)
J'ai une solution incroyable pour y parvenir faire une BaseActivity comme celle-ci.
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();
}
}
}
}
}
Maintenant, vous pouvez appeler le code pour demander la permission comme ceci
ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);
Maintenant, chaque fois que cela se produit n'importe où, que ce soit dans votre fragment ou dans n'importe quelle activité, l'activité de base serait appelée.
Merci
Détails
- Kotlin 1.2.70
- vérifié dans minSdkVersion 19
- Android Studio 3.1.4
Algorithme
Module - appareil photo, l'emplacement, l' ....
- Vérifiez si hasSystemFeature (Si module existent dans le téléphone)
- Vérifiez si l'Utilisateur a accès au module
- Envoyer des autorisations de demande (demander à l'utilisateur d'autoriser module utilisation)
Caractéristiques
- travailler avec des activités et Fragments
- N'a qu'une seule réponse de résultat
- Pouvez vérifier plusieurs modules dans une requête
Solution
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()
}
}
}
Utilisation dans L'activité (dans le fragment le même)
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 -> {
// }
// }
}
}
}
J'ai eu un problème similaire accepter que j'appuyais sur le bouton pour faire un appel, ce qui déclenche le callIntent. J'ai d'abord vérifié l'autorisation, si non accordée, je demande l'autorisation et onRequestPermissionResult j'appelle l'autorisation de vérification et appelle à nouveau.
@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();
}
}
}