webentwicklung-frage-antwort-db.com.de

Android M Berechtigungen: onRequestPermissionsResult () wird nicht aufgerufen

Ich aktualisiere unsere App, um das neue M-Berechtigungssystem zu verwenden. Es funktioniert alles außer dem onRequestPermissionsResult (). Ich muss eine Berechtigung bei einem Tastendruck überprüfen und bei Erfolg eine Textnachricht senden. Wenn ich die Erlaubnis dazu erteile, wird das Dialogfeld geschlossen, aber der Sendetext wird erst ausgelöst, wenn ich erneut auf die Schaltfläche drücke.

Ich habe in der onRequestPermissionsResult () -Methode ein Debugging durchgeführt und Haltepunkte gesetzt, aber es wird nie ausgeführt.

Diese Methode wird zuerst aufgerufen:

    private void askForPermission() {
    String[] permissions = new String[]{Manifest.permission.SEND_SMS};
    ActivityCompat.requestPermissions(getActivity(), permissions, PERMISSIONS_CODE);
}

Und dann sieht mein Rückruf so aus:

    @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);
                }
            }
        }
    }
}

Ist jemand auf ein ähnliches Problem gestoßen? Schätzen Sie jede Hilfe dabei. Vielen Dank

272
AndyOHart

Dieses Problem wurde tatsächlich durch NestedFragments verursacht. Grundsätzlich haben wir die meisten Fragmente um ein HostedFragment erweitert, das wiederum ein CompatFragment erweitert. Diese verschachtelten Fragmente verursachten Probleme, die schließlich von einem anderen Entwickler im Projekt gelöst wurden.

Er hat ein paar Dinge auf niedriger Ebene gemacht, wie das Bit-Switching, um dies zum Laufen zu bringen, also bin ich mir der tatsächlichen endgültigen Lösung nicht sicher

10
AndyOHart

Ich bin auf dasselbe Problem gestoßen und habe gerade die Lösung gefunden. Wenn Sie die Support-Bibliothek verwenden, müssen Sie die richtigen Methodenaufrufe verwenden. Zum Beispiel:

  • In AppCompatActivity sollten Sie ActivityCompat.requestPermissions verwenden.
  • In Android.support.v4.app.Fragment sollten Sie einfach requestPermissions verwenden (dies ist eine Instanzmethode von Android.support.v4.app.Fragment)

Wenn Sie ActivityCompat.requestPermissions in einem Fragment aufrufen, wird der Rückruf onRequestPermissionsResult für die Aktivität und nicht für das Fragment aufgerufen.

Hoffe das hilft!

559
yavor87

Sie können dies versuchen:

requestPermissions(permissions, PERMISSIONS_CODE);

Wenn Sie diesen Code aus einem Fragment aufrufen, verfügt er über eine eigene requestPermissions-Methode. Ich glaube, das Problem ist, dass Sie statische Methode aufrufen.

Pro Tipp, wenn Sie die onRequestPermissionsResult() in einem Fragment wollen: FragmentCompat.requestPermissions(Fragment fragment, String[] permissions, int requestCode)

94
Tieru

Ich hoffe, es funktioniert gut

Für die Aktivität:

 ActivityCompat.requestPermissions(this,permissionsList,REQUEST_CODE);

Für Fragment:

 requestPermissions(permissionsList,REQUEST_CODE);
63

Ich bin auch auf dieses Problem gestoßen. Wenn Sie eine Aktivität wünschen, die Berechtigungen verarbeitet, die nicht im Verlauf/in den letzten Abschnitten enthalten sind, werden Sie versucht sein, Ihren Eintrag AndroidManifest.xml zu ändern.

Wenn Sie die Aktivität, die Sie requestPermissions oder AppCompatActivity.requestPermissions aufrufen, mit einstellen

Android:noHistory="true"
Android:excludeFromRecents="true"

in deinem AndroidManifest.xml wird dann onRequestPermissionsResult() nicht aufgerufen. Dies gilt, wenn Ihre Aktivität von Activity oder AppCompatActivity abgeleitet ist.

Dies kann behoben werden, indem Sie beide Flags aus 'AndroidManifest.xml' entfernen und Ihre Aktivität stattdessen mit finishAndRemoveTask() beenden.

50

Wenn Sie onRequestPermissionsResult in Aktivität und Fragment haben, müssen Sie super.onRequestPermissionsResult in Aktivität aufrufen. Es ist nicht in Fragment erforderlich, aber es ist in Aktivität.

36
Dusan Zivkovic

Innerhalb Fragment müssen Sie anrufen:

FragmentCompat.requestPermissions(permissionsList, RequestCode)

Nicht:

ActivityCompat.requestPermissions(Activity, permissionsList, RequestCode);
31
Ben.Slama.Jihed

Wenn Sie requestPermissions in fragment verwenden, werden 2 anstelle von 3 Parametern akzeptiert.

Sie sollten requestPermissions(permissions, PERMISSIONS_CODE); verwenden

15
AkKi

Wenn Sie aus irgendeinem Grund eine benutzerdefinierte Aktivität in einer externen Bibliothek erweitert haben, die den Super nicht aufruft, müssen Sie das Fragment super.onRequestPermissionsResult manuell aufrufen. Führen Sie dazu, dass Sie die Aktivität onRequestPermissionsResult ausführen.

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);
    }
...
14
TouchBoarder

Sie haben die Funktion checkPermissions für Geräte vor Marshmallow in FragmentCompat. Ich benutze so:

FragmentCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
12
Marta Rodriguez

Ich habe herausgefunden, dass dies wichtig ist, wenn Sie Android.support.v4.app.Fragment.requestPermissions aufrufen.

Wenn Sie dies in onCreate() tun, wird onRequestPermissionsResult() niemals aufgerufen.

Lösung: Rufen Sie es in onActivityCreated() auf.

@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);

}
12
almisoft
 /* 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);
9
Shahab Rauf

Das wird funktionieren..

@Override
    public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    }
6
Sumit khare

Wenn Sie diesen Code aus einem Fragment aufrufen, verfügt er über eine eigene requestPermissions-Methode.

Das Grundkonzept lautet also: Wenn Sie sich in einer Aktivität befinden, rufen Sie an

ActivityCompat.requestPermissions(this,
                            permissionsList,
                            permissionscode);

und wenn Sie in einem Fragment sind, rufen Sie einfach an

requestPermissions(permissionsList,
                            permissionscode);

Ich hatte ein ähnliches Problem, außer dass ich eine Taste drückte, um einen Anruf zu tätigen, wodurch callIntent ausgelöst wurde. Ich habe zuerst die Berechtigung überprüft. Wenn ich sie nicht erhalte, bitte ich um Erlaubnis. OnRequestPermissionResult rufe ich die Überprüfungsberechtigung auf und rufe erneut an.

 @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();
        }
    }
}
4
ndheti

Ich habe eine erstaunliche Lösung, um dies zu erreichen und eine BaseActivity wie diese zu erstellen.

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();
            }
        }
    }
}

}

Jetzt können Sie den Code anrufen, um nach einer solchen Erlaubnis zu fragen

 ActivityCompat.requestPermissions(getActivity(), new String[]{Manifest.permission.WRITE_EXTERNAL_STORAGE}, 1);

Jedes Mal, wenn dies passiert, egal ob in Ihrem Fragment oder in einer Aktivität, wird die Basisaktivität aufgerufen.

Vielen Dank

2
Abhishek Dubey

Stellen Sie sicher, dass Ihr Anforderungscode nicht 0 ist, bevor Sie alles gemäß den obigen Antworten überprüfen !!!

überprüfen Sie den Code von onRequestPermissionsResult () in 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);
        }
    }
}
2
Chandler

Basierend auf goodgamerguy's answer lautet die Lösung:

myFragment.this.requestPermissions(....)
2
Hamza Elmi
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();
    }
}
2
user2002721

UPDATE: Ich habe die Antwort einer anderen Person über den Aufruf von super.onRequestPermissionResult () in Activity gesehen. Damit wurde das erwähnte Problem mit dem Anforderungscode behoben und das onRequestPermissionResult des Fragments aufgerufen.

ignoriere dieses Zeug:

Für mich wurde das onRequestPermissionResult der Aktivität aufgerufen, obwohl ich fragment.requestPermission (...) aufgerufen habe, ABER das Ergebnis wurde mit einem falschen requestCode zurückgegeben (111 wurde zu 65647, warum ??? Ich werde es nie erfahren).

Zum Glück ist dies die einzige Erlaubnis, die wir auf diesem Bildschirm anfordern. Deshalb ignoriere ich den Anforderungscode (ich habe keine Zeit herauszufinden, warum er momentan nicht korrekt ist).

1
grgrssll

Einzelheiten

  • Kotlin 1.2.70
  • in minSdkVersion 19 eingecheckt
  • Android Studio 3.1.4

Algorithmus

Modul - Kamera, Ort, ....

  1. Überprüfen Sie, ob hasSystemFeature (wenn Modul im Telefon vorhanden ist)
  2. Überprüfen Sie, ob der Benutzer Zugriff auf Modul hat
  3. Berechtigungsanfrage senden (Benutzer bitten, Modul Nutzung zuzulassen)

Eigenschaften

  1. Arbeiten Sie mit Aktivitäten und Fragmenten
  2. Hat nur eine Ergebnisantwort
  3. Kann mehrere Module in einer Anfrage prüfen

Lösung

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()
        }
    }
}

Verwendung in Aktivität (im Fragment das gleiche)

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 -> {
//                }
//            }
        }
    }
}
1

Sie können requestPermissions(PERMISSIONS, MULTIPLE_PERMISSIONS_CODE); verwenden. Verwenden Sie FragmentCompat nicht, wenn Sie Version 4 verwenden.

1
Remario

Hier möchte ich meinen Code zeigen, wie ich das geschafft habe.

public class CheckPermission {

public Context context;

public static final int PERMISSION_REQUEST_CODE =  200;

public CheckPermission(Context context){
    this.context = context;
}

public boolean isPermissionGranted(){
    int read_contact = ContextCompat.checkSelfPermission(context.getApplicationContext() , READ_CONTACTS);
    int phone = ContextCompat.checkSelfPermission(context.getApplicationContext() , CALL_PHONE);

    return read_contact == PackageManager.PERMISSION_GRANTED && phone == PackageManager.PERMISSION_GRANTED;
   }
}

Hier in dieser Klasse möchte ich die Erlaubnis überprüfen, die erteilt wird oder nicht. Ist das nicht dann werde ich gerne die Erlaubnis von meiner MainActivity abrufen

public void requestForPermission() {
       ActivityCompat.requestPermissions(MainActivity.this, new String[]    {READ_CONTACTS, CALL_PHONE}, PERMISSION_REQUEST_CODE);
}

@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    switch (requestCode) {
        case PERMISSION_REQUEST_CODE:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (shouldShowRequestPermissionRationale(ACCESS_FINE_LOCATION)) {
                    showMessageOKCancel("You need to allow access to both the permissions",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog, int which) {
                                    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                                        requestPermissions(new String[]{Manifest.permission.READ_CONTACTS, Manifest.permission.CALL_PHONE},
                                                PERMISSION_REQUEST_CODE);
                                    }
                                }
                            });
                    return;
                }
            }
    }
}

Jetzt müssen Sie in der Methode onCreate die Funktion requestForPermission () aufrufen.

Das war's. Sie können auch mehrere Berechtigungen gleichzeitig anfordern.

0
pavel