Android
Uprawnienia środowiska wykonawczego w API-23 +
Szukaj…
Wprowadzenie
Android Marshmallow wprowadził model Runtime Permission . Uprawnienia są podzielone na dwie kategorie, tj. Uprawnienia normalne i niebezpieczne . gdzie niebezpieczne uprawnienia są teraz przyznawane przez użytkownika w czasie wykonywania.
Uwagi
Od sdk 23 Android wymaga uprawnień do wykonywania w przypadku uprawnień na urządzeniach z Androidem 6.0 lub nowszym, w ramach kategorii Niebezpieczne grupy uprawnień. Niebezpieczne grupy uprawnień to takie, które uważa się za zagrażające prywatności i / lub bezpieczeństwu użytkownika.
Poniżej znajduje się lista niebezpiecznych grup uprawnień:
Niebezpieczne grupy uprawnień
Grupa uprawnień
KALENDARZ
APARAT FOTOGRAFICZNY
ŁĄCZNOŚĆ
LOKALIZACJA
MIKROFON
TELEFON
CZUJNIKI
SMS
PRZECHOWYWANIE
Wszelkie uprawnienia z tych grup wymagają zarządzania uprawnieniami do wykonywania dla urządzeń z Androidem 6.0 lub nowszym z docelowym SDK 23 lub wyższym.
Normalne uprawnienia
Poniżej znajduje się lista normalnych uprawnień. Nie są one uważane za niebezpieczne dla prywatności lub bezpieczeństwa użytkownika, dlatego nie wymagają uprawnień do wykonywania w przypadku sdk 23 i wyższych.
ACCESS_LOCATION_EXTRA_COMMANDS
ACCESS_NETWORK_STATE
ACCESS_NOTIFICATION_POLICY
ACCESS_WIFI_STATE
BLUETOOTH
BLUETOOTH_ADMIN
BROADCAST_STICKY
CHANGE_NETWORK_STATE
CHANGE_WIFI_MULTICAST_STATE
CHANGE_WIFI_STATE
DISABLE_KEYGUARD
EXPAND_STATUS_BAR
GET_PACKAGE_SIZE
INSTALL_SHORTCUT
INTERNET
KILL_BACKGROUND_PROCESSES
MODIFY_AUDIO_SETTINGS
NFC
READ_SYNC_SETTINGS
READ_SYNC_STATS
RECEIVE_BOOT_COMPLETED
REORDER_TASKS
REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
REQUEST_INSTALL_PACKAGES
NASTAW BUDZIK
SET_TIME_ZONE
USTAW TAPETĘ
SET_WALLPAPER_HINTS
TRANSMIT_IR
UNINSTALL_SHORTCUT
USE_FINGERPRINT
WIBROWAĆ
WAKE_LOCK
WRITE_SYNC_SETTINGS
Android 6.0 wiele uprawnień
Ten przykład pokazuje, jak sprawdzić uprawnienia w czasie wykonywania w systemie Android 6 i nowszych.
public static final int MULTIPLE_PERMISSIONS = 10; // code you want.
String[] permissions = new String[] {
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.CAMERA,
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
};
@Override
void onStart() {
if (checkPermissions()){
// permissions granted.
} else {
// show dialog informing them that we lack certain permissions
}
}
private boolean checkPermissions() {
int result;
List<String> listPermissionsNeeded = new ArrayList<>();
for (String p:permissions) {
result = ContextCompat.checkSelfPermission(getActivity(),p);
if (result != PackageManager.PERMISSION_GRANTED) {
listPermissionsNeeded.add(p);
}
}
if (!listPermissionsNeeded.isEmpty()) {
ActivityCompat.requestPermissions(this, listPermissionsNeeded.toArray(new String[listPermissionsNeeded.size()]), MULTIPLE_PERMISSIONS);
return false;
}
return true;
}
@Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MULTIPLE_PERMISSIONS:{
if(grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED){
// permissions granted.
} else {
// no permissions granted.
}
return;
}
}
}
Egzekwowanie uprawnień w transmisjach, URI
Możesz wykonać sprawdzenie uprawnień podczas wysyłania zamiaru do zarejestrowanego odbiornika. Uprawnienia, które wysyłasz, są sprawdzane krzyżowo z uprawnieniami zarejestrowanymi pod tagiem. Ograniczają, kto może wysyłać transmisje do powiązanego odbiornika.
Aby wysłać żądanie transmisji z uprawnieniami, określ uprawnienie jako ciąg w Context.sendBroadcast(Intent intent, String permission)
, ale pamiętaj, że aplikacja odbiorcy MUSI mieć to uprawnienie, aby otrzymać transmisję. Odbiornik powinien zostać zainstalowany najpierw przed nadawcą.
Podpis metody to:
void sendBroadcast (Intent intent, String receiverPermission)
//for example to send a broadcast to Bcastreceiver receiver
Intent broadcast = new Intent(this, Bcastreceiver.class);
sendBroadcast(broadcast, "org.quadcore.mypermission");
i możesz określić w swoim manifeście, że nadawca jest zobowiązany do dołączenia żądanego pozwolenia wysłanego za pośrednictwem sendBroadcast:
<!-- Your special permission -->
<permission android:name="org.quadcore.mypermission"
android:label="my_permission"
android:protectionLevel="dangerous"></permission>
Zadeklaruj również zezwolenie w manifeście aplikacji, która ma odbierać tę transmisję:
<!-- I use the permission ! -->
<uses-permission android:name="org.quadcore.mypermission"/>
<!-- along with the receiver -->
<receiver android:name="Bcastreceiver" android:exported="true" />
Uwaga: Zarówno odbiorca, jak i nadawca mogą wymagać pozwolenia, a gdy tak się stanie, oba testy uprawnień muszą przejść pomyślnie, aby zamiar został dostarczony do powiązanego celu. Najpierw należy zainstalować aplikację definiującą uprawnienie.
Znajdź pełną dokumentację tutaj dotyczącą uprawnień.
Wiele uprawnień środowiska wykonawczego z tych samych grup uprawnień
W manifeście mamy cztery niebezpieczne uprawnienia do wykonywania w dwóch grupach.
<!-- Required to read and write to shredPref file. -->
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<!-- Required to get location of device. -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
W działaniu, w którym wymagane są uprawnienia. Uwaga: ważne jest, aby sprawdzić uprawnienia w dowolnej działalności wymagającej uprawnień, ponieważ uprawnienia można cofnąć, gdy aplikacja jest w tle, a następnie aplikacja ulegnie awarii.
final private int REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS = 124;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.act_layout);
// A simple check of whether runtime permissions need to be managed
if (Build.VERSION.SDK_INT >= 23) {
checkMultiplePermissions();
}
Musimy jedynie poprosić o pozwolenie na jedno z nich z każdej grupy, a wszystkie inne uprawnienia z tej grupy są przyznawane, chyba że użytkownik je cofnie.
private void checkMultiplePermissions() {
if (Build.VERSION.SDK_INT >= 23) {
List<String> permissionsNeeded = new ArrayList<String>();
List<String> permissionsList = new ArrayList<String>();
if (!addPermission(permissionsList, android.Manifest.permission.ACCESS_FINE_LOCATION)) {
permissionsNeeded.add("GPS");
}
if (!addPermission(permissionsList, android.Manifest.permission.READ_EXTERNAL_STORAGE)) {
permissionsNeeded.add("Read Storage");
}
if (permissionsList.size() > 0) {
requestPermissions(permissionsList.toArray(new String[permissionsList.size()]),
REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS);
return;
}
}
}
private boolean addPermission(List<String> permissionsList, String permission) {
if (Build.VERSION.SDK_INT >= 23)
if (checkSelfPermission(permission) != PackageManager.PERMISSION_GRANTED) {
permissionsList.add(permission);
// Check for Rationale Option
if (!shouldShowRequestPermissionRationale(permission))
return false;
}
return true;
}
Dotyczy to wyniku przyznania przez użytkownika zezwolenia lub odmowy. W tym przykładzie, jeśli uprawnienia nie są dozwolone, aplikacja zostanie zabita.
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
switch (requestCode) {
case REQUEST_CODE_ASK_MULTIPLE_PERMISSIONS: {
Map<String, Integer> perms = new HashMap<String, Integer>();
// Initial
perms.put(android.Manifest.permission.ACCESS_FINE_LOCATION, PackageManager.PERMISSION_GRANTED);
perms.put(android.Manifest.permission.READ_EXTERNAL_STORAGE, PackageManager.PERMISSION_GRANTED);
// Fill with results
for (int i = 0; i < permissions.length; i++)
perms.put(permissions[i], grantResults[i]);
if (perms.get(android.Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED
&& perms.get(android.Manifest.permission.READ_EXTERNAL_STORAGE) == PackageManager.PERMISSION_GRANTED) {
// All Permissions Granted
return;
} else {
// Permission Denied
if (Build.VERSION.SDK_INT >= 23) {
Toast.makeText(
getApplicationContext(),
"My App cannot run without Location and Storage " +
"Permissions.\nRelaunch My App or allow permissions" +
" in Applications Settings",
Toast.LENGTH_LONG).show();
finish();
}
}
}
break;
default:
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
}
Więcej informacji https://inthecheesefactory.com/blog/things-you-need-to-know-about-android-m-permission-developer-edition/en
Korzystanie z uprawnień do
PermissionUtil to prosty i wygodny sposób proszenia o uprawnienia w kontekście. Możesz łatwo podać, co powinno się zdarzyć w przypadku przyznania wszystkich żądanych uprawnień ( onAllGranted()
), każde żądanie zostało odrzucone ( onAnyDenied()
) lub w przypadku, gdy potrzebne jest wymierne ( onRational()
).
Dowolne miejsce w AppCompatActivity lub Fragment, które chcesz poprosić o pozwolenie użytkownika
mRequestObject = PermissionUtil.with(this).request(Manifest.permission.WRITE_EXTERNAL_STORAGE).onAllGranted(
new Func() {
@Override protected void call() {
//Happy Path
}
}).onAnyDenied(
new Func() {
@Override protected void call() {
//Sad Path
}
}).ask(REQUEST_CODE_STORAGE);
I dodaj to do onRequestPermissionsResult
if(mRequestObject!=null){
mRequestObject.onRequestPermissionsResult(requestCode, permissions, grantResults);
}
Dodaj wymagane uprawnienie również do pliku AndroidManifest.xml
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
Dołącz cały kod związany z uprawnieniami do abstrakcyjnej klasy bazowej i rozszerz aktywność tej klasy podstawowej, aby uzyskać czystszy / wielokrotnego użytku kod
public abstract class BaseActivity extends AppCompatActivity {
private Map<Integer, PermissionCallback> permissionCallbackMap = new HashMap<>();
@Override
protected void onStart() {
super.onStart();
...
}
@Override
public void setContentView(int layoutResId) {
super.setContentView(layoutResId);
bindViews();
}
...
@Override
public void onRequestPermissionsResult(
int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
PermissionCallback callback = permissionCallbackMap.get(requestCode);
if (callback == null) return;
// Check whether the permission request was rejected.
if (grantResults.length < 0 && permissions.length > 0) {
callback.onPermissionDenied(permissions);
return;
}
List<String> grantedPermissions = new ArrayList<>();
List<String> blockedPermissions = new ArrayList<>();
List<String> deniedPermissions = new ArrayList<>();
int index = 0;
for (String permission : permissions) {
List<String> permissionList = grantResults[index] == PackageManager.PERMISSION_GRANTED
? grantedPermissions
: ! ActivityCompat.shouldShowRequestPermissionRationale(this, permission)
? blockedPermissions
: deniedPermissions;
permissionList.add(permission);
index ++;
}
if (grantedPermissions.size() > 0) {
callback.onPermissionGranted(
grantedPermissions.toArray(new String[grantedPermissions.size()]));
}
if (deniedPermissions.size() > 0) {
callback.onPermissionDenied(
deniedPermissions.toArray(new String[deniedPermissions.size()]));
}
if (blockedPermissions.size() > 0) {
callback.onPermissionBlocked(
blockedPermissions.toArray(new String[blockedPermissions.size()]));
}
permissionCallbackMap.remove(requestCode);
}
/**
* Check whether a permission is granted or not.
*
* @param permission
* @return
*/
public boolean hasPermission(String permission) {
return ContextCompat.checkSelfPermission(this, permission) == PackageManager.PERMISSION_GRANTED;
}
/**
* Request permissions and get the result on callback.
*
* @param permissions
* @param callback
*/
public void requestPermission(String [] permissions, @NonNull PermissionCallback callback) {
int requestCode = permissionCallbackMap.size() + 1;
permissionCallbackMap.put(requestCode, callback);
ActivityCompat.requestPermissions(this, permissions, requestCode);
}
/**
* Request permission and get the result on callback.
*
* @param permission
* @param callback
*/
public void requestPermission(String permission, @NonNull PermissionCallback callback) {
int requestCode = permissionCallbackMap.size() + 1;
permissionCallbackMap.put(requestCode, callback);
ActivityCompat.requestPermissions(this, new String[] { permission }, requestCode);
}
}
Przykładowe użycie w działaniu
Działanie powinno rozszerzyć abstrakcyjną klasę podstawową zdefiniowaną powyżej w następujący sposób:
private void requestLocationAfterPermissionCheck() {
if (hasPermission(Manifest.permission.ACCESS_FINE_LOCATION)) {
requestLocation();
return;
}
// Call the base class method.
requestPermission(Manifest.permission.ACCESS_FINE_LOCATION, new PermissionCallback() {
@Override
public void onPermissionGranted(String[] grantedPermissions) {
requestLocation();
}
@Override
public void onPermissionDenied(String[] deniedPermissions) {
// Do something.
}
@Override
public void onPermissionBlocked(String[] blockedPermissions) {
// Do something.
}
});
}