Od Androida 6.0 Marshmallow system używa modelu uprawnień, który usprawnia proces instalowania aplikacji i automatycznego aktualizowania. Uprawnienia są wymagane w czasie działania, a nie przed instalacją aplikacji. Dodatkowo użytkownicy mogą odmówić udzielenia określonych uprawnień. Aby zapewnić użytkownikom taką elastyczność, musisz się upewnić, że aplikacja działa zgodnie z oczekiwaniami, gdy użytkownik włączy lub wyłączy określone uprawnienie.
Usługi Google Play mają uprawnienia w czasie działania, które użytkownicy mogą odrzucać niezależnie od uprawnień, o które prosi aplikacja. Usługi Google Play automatycznie uzyskują wszystkie uprawnienia potrzebne do obsługi interfejsów API. Aplikacja powinna jednak w miarę potrzeby sprawdzać uprawnienia w czasie działania i prosić o nie oraz odpowiednio obsługiwać błędy w przypadku, gdy użytkownik odmówił usługom Google Play uprawnień wymaganych przez interfejs API, którego używa aplikacja.
Dobrą praktyką jest zarządzanie oczekiwaniami użytkownika w ramach ustawiania uprawnień, których może wymagać środowisko uruchomieniowe. Te sprawdzone metody pomogą Ci uniknąć potencjalnych problemów.
Wymagania wstępne
Uprawnienia musisz zadeklarować w pliku AndroidManifest.xml
.
Na przykład:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Wytyczne
Sprawdzanie uprawnień przed wywołaniem interfejsów API
Po zadeklarowaniu interfejsów API, których chcesz używać w pliku AndroidManifest.xml
, sprawdź, czy masz wymagane uprawnienia, zanim wywołasz interfejs API. Można to zrobić za pomocą metody checkSelfPermission
ActivityCompat
lub ContextCompat
.
Jeśli wywołanie zwróci wartość false, oznacza to, że uprawnienia nie zostały przyznane. Aby je zażądać, użyj metody requestPermissions
. Odpowiedź na to jest zwracana w wywołaniu zwrotnym, które zobaczysz w następnym kroku.
Na przykład:
Kotlin
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Request Permissions Now ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION_CODE) } else { // permission has been granted, continue as usual val locationResult = LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation }
Java
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Request Permissions Now ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, REQUEST_LOCATION_PERMISSION_CODE); } else { // permission has been granted, continue as usual TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); }
Zaimplementuj wywołanie zwrotne prośby o zgodę
Jeśli użytkownik nie przyznał aplikacji wymaganych uprawnień, należy wywołać metodę requestPermissions
, aby poprosić użytkownika o ich przyznanie. Odpowiedź użytkownika jest rejestrowana w pobraniu onRequestPermissionsResult
. Aplikacja powinna to uwzględnić i zawsze sprawdzać wartości zwracane, ponieważ prośba może zostać odrzucona lub anulowana. Możesz też poprosić o kilka uprawnień jednocześnie i je sprawdzić – poniższy przykład sprawdza tylko jedno uprawnienie.
Kotlin
fun onRequestPermissionsResult( requestCode: Int, permissions: Array, grantResults: IntArray ) { if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) { if (grantResults.singleOrNull() == PackageManager.PERMISSION_GRANTED) { // We can now safely use the API we requested access to val locationResult: Task = LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation // Request the last known location. } else { // Permission was denied or request was cancelled } } }
Java
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) { if (requestCode == REQUEST_LOCATION_PERMISSION_CODE) { if(grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) { // We can now safely use the API we requested access to TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); // Request the last known location. } else { // Permission was denied or request was cancelled } } }
Pokaż uzasadnienie dotyczące uprawnień
Jeśli uprawnienia, o które prosi aplikacja, są niezbędne do działania jej głównych funkcji, a użytkownik odmówił wcześniej przyznania uprawnień, aplikacja powinna wyświetlić dodatkowe wyjaśnienie, zanim poprosi o nie ponownie. Użytkownicy chętniej udzielają uprawnień, gdy rozumieją, dlaczego są one potrzebne i jakie korzyści z nich wynikają.
W takim przypadku przed wywołaniem requestPermissions
należy wywołać shouldShowRequestPermissionRationale
. Jeśli zwróci wartość true, musisz utworzyć interfejs użytkownika, aby wyświetlić dodatkowy kontekst uprawnienia.
Twój kod może wyglądać np. tak:
Kotlin
private const val REQUEST_LOCATION_PERMISSION_CODE = 2 if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Check Permissions Now if ActivityCompat.shouldShowRequestPermissionRationale( this, Manifest.permission.ACCESS_FINE_LOCATION ) { // Display UI and wait for user interaction } else { ActivityCompat.requestPermissions( this, arrayOf(Manifest.permission.ACCESS_FINE_LOCATION), REQUEST_LOCATION_PERMISSION_CODE) } } else { // Permission has already been granted, continue as usual val locationResult: Task= LocationServices .getFusedLocationProviderClient(this /* Context */) .lastLocation }
Java
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) { // Check Permissions Now private static final int REQUEST_LOCATION_PERMISSION_CODE = 2; if (ActivityCompat.shouldShowRequestPermissionRationale(this, Manifest.permission.ACCESS_FINE_LOCATION)) { // Display UI and wait for user interaction } else { ActivityCompat.requestPermissions( this, new String[]{Manifest.permission.LOCATION_FINE}, REQUEST_LOCATION_PERMISSION_CODE); } } else { // permission has been granted, continue as usual TasklocationResult = LocationServices .getFusedLocationProviderClient(this /** Context */) .getLastLocation(); }
Wywołania interfejsu API usług Google Play automatycznie wyświetlają okno dialogowe (jeśli klient jest instancją interfejsu Activity
) lub powiadomienie na pasku systemowym (jeśli klient jest instancją interfejsu Context
), które użytkownik może kliknąć, aby rozpocząć działanie dotyczące rozwiązywania problemów z uprawnieniami. Pozwolenie na dostęp do danych będzie wiązało się z umieszczeniem połączeń w kolejce i ponownym próbowaniem połączenia.