10

Da das Android SDK 23 Benutzern die Möglichkeit gibt, Apps den Zugriff auf bestimmte Funktionen zu verweigern, wollte ich eine meiner Apps aktualisieren, um Berechtigungen wie hier beschrieben anzufordern: https://developer.android.com/preview/features/runtime-permissions.html.Doppelte Erlaubnisanfrage nach Orientierungsänderung

In einer der Aktivitäten bette ich eine ein. Damit es funktioniert, benötigen Sie die Berechtigung WRITE_EXTERNAL_STORAGE, also fordere ich sie an, wenn ich die Aktivität starte, was zur Erstellung eines Berechtigungsanforderungsdialogs führt.

Jetzt ist das Problem, dass, wenn der Dialog noch geöffnet ist und ich das Gerät rotiere, die Aktivität neu gestartet wird und einen neuen Erlaubnisanforderungsdialog öffnet, während der alte noch da ist. Das Ergebnis sind zwei dieser Dialoge übereinander und nur eines davon ist nützlich.

Gibt es eine Möglichkeit, den Dialog, der zuerst gestartet wurde, loszuwerden?

+4

Da Sie den Dialog nicht erstellt haben, ist mir keine Möglichkeit bekannt, ihn zu entfernen. Setzen Sie einen 'boolean' in Ihren gespeicherten Instanzzustand' Bundle', der angibt, dass die Berechtigungsanforderung aussteht, und fordern Sie die Berechtigung nicht erneut an. Oder warten Sie, bis Sie die Erlaubnis erhalten, bis Sie eine Art von Benutzereingabe erhalten (z. B. durch Antippen des Aktionsleistenelements, das das 'SupportMapFragment' startet). In diesem Fall sollten Sie sicher sein, da der Benutzer das Element während des Dialogs nicht erneut antippen kann ist sichtbar. – CommonsWare

+0

Yup, das macht es. Ich glaube nicht, dass dies eine Option wäre, da der "alte" Dialog nur an die "alte" Aktivität gebunden wäre, aber ich habe es gerade versucht und das Ergebnis wird von der "neuen" Aktivität empfangen. – Thorben

Antwort

11

Wie CommonsWare in seiner comment sagt, ist die beste Lösung, einen boolean in das savedInstanceState-Bundle zu setzen, um zu wissen, ob der Dialog noch offen ist.

Beispiel:

// true if dialog already open 
private boolean alreadyAskedForStoragePermission = false; 

@Override 
protected void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 

    if(savedInstanceState != null) { 
     alreadyAskedForStoragePermission = savedInstanceState.getBoolean(STORAGE_PERMISSION_DIALOG_OPEN_KEY, false); 
    } 
} 

@Override 
protected void onSaveInstanceState(Bundle outState) { 
    super.onSaveInstanceState(outState); 

    outState.putBoolean(KEY, alreadyAskedForStoragePermission); 
} 

private void checkStoragePermission(){ 
    if(alreadyAskedForStoragePermission){ 
     // don't check again because the dialog is still open 
     return; 
    } 

    if(ActivityCompat.checkSelfPermission(this, STORAGE_PERMISSIONS[0]) != PackageManager.PERMISSION_GRANTED){ 
     // the dialog will be opened so we have to keep that in memory 
     alreadyAskedForStoragePermission = true; 
     ActivityCompat.requestPermissions(this, STORAGE_PERMISSIONS, STORAGE_PERMISSION_REQUEST_CODE); 
    } else { 
     onStoragePermissionGranted(); 
    } 
} 

@Override 
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) { 
    switch (requestCode){ 
     case STORAGE_PERMISSION_REQUEST_CODE: 
      // the request returned a result so the dialog is closed 
      alreadyAskedForStoragePermission = false; 

      if(grantResults[0] == PackageManager.PERMISSION_GRANTED){ 
       onStoragePermissionGranted(); 
      } 

      break; 
    } 
} 
+0

Ich glaube, es gibt ein System boolean existiert in Bundle savedInstanceState android: hasCurrentPermissionsRequest = true wenn Erlaubnis Dialogfeld angezeigt wird, obwohl keine Erwähnung in der Dokumentation finden. – user1991776

0

Ich denke, da dies ein Systemdialog ist, können Sie es nicht steuern. Sie können stattdessen verhindern, dass Ihre Aktivität neu geladen wird, wenn Sie Ihr Gerät einschalten.

8

Wie @ user1991776 erwähnt, gibt es tatsächlich ein nicht dokumentiert Extra ist, ob oder nicht enthält eine Erlaubnis Dialog zur Zeit geöffnet ist, in Activity:

private static final String HAS_CURENT_PERMISSIONS_REQUEST_KEY = 
     "android:hasCurrentPermissionsRequest"; 

Allerdings gibt es ein besserer Weg. Wenn Sie eine Erlaubnis Dialog zum zweiten Mal (aufgrund einer Rotation) beantragen, bricht Activity automatisch den alten Dialog von Ihrem onRequestPermissionResult()with empty arrays Aufruf:

public final void requestPermissions(@NonNull String[] permissions, int requestCode) { 
    if (mHasCurrentPermissionsRequest) { 
     Log.w(TAG, "Can reqeust only one set of permissions at a time"); 
     // Dispatch the callback with empty arrays which means a cancellation. 
     onRequestPermissionsResult(requestCode, new String[0], new int[0]); 
     return; 
    } 
    Intent intent = getPackageManager().buildRequestPermissionsIntent(permissions); 
    startActivityForResult(REQUEST_PERMISSIONS_WHO_PREFIX, intent, requestCode, null); 
    mHasCurrentPermissionsRequest = true; 
} 

Oder natürlich dieses Verhalten isn't documented denn dies ist Android, und wer will dokumentieren komplexes Verhalten?

In jedem Fall können Sie immer nur Berechtigungen in onCreate() anfordern und dann Anrufe zu onRequestPermissionsResult() mit Null-Länge permissions Arrays ignorieren.

+0

+ für die Dokumentation von android =) –

Verwandte Themen