Разрешения на выполнение приложений для Android - как реализовать
Документация разработчика Android дает этот пример запроса разрешений во время выполнения:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.READ_CONTACTS)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.READ_CONTACTS)) {
// Show an expanation to the user *asynchronously* -- don't block
// this thread waiting for the user response! After the user
// sees the explanation, try again to request the permission.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.READ_CONTACTS},
MY_PERMISSIONS_REQUEST_READ_CONTACTS);
// MY_PERMISSIONS_REQUEST_READ_CONTACTS is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Что такое "MY_PERMISSIONS_REQUEST_READ_CONTACTS" в этом примере? Он говорит, что это константа int, определяемая приложением, но означает ли это, что я должен создать Constants.java и объявить открытый static int? Каким должно быть значение?
В других примерах я вижу, что люди используют 1 здесь, или 0 или 0xFFEEDDCC, но я не могу найти объяснения, что это такое. Может кто-нибудь объяснить мне, что нужно здесь и почему? (В моем случае мне нужно убедиться, что у приложения есть разрешение на доступ к прекрасному местоположению)
Документация ActivityCompat гласит: "Код запроса конкретного приложения соответствует результату, указанному в onRequestPermissionsResult"? Это не помогает мне.
Ответы
Ответ 1
Что такое "MY_PERMISSIONS_REQUEST_READ_CONTACTS" в этом примере?
Это int
, чтобы связать конкретный вызов requestPermissions()
с соответствующим обратным вызовом onRequestPermissionsResult()
.
Под обложками requestPermissions()
используется startActivityForResult()
; этот int
выполняет ту же роль, что и в startActivityForResult()
.
означает ли это, что я должен создать Constants.java и объявить открытый static int?
Я бы просто сделал это private static final int
в активности. Но вы можете объявить его там, где хотите.
Каким должно быть значение?
Кажется, я помню, что он должен быть ниже 0x8000000, но в противном случае он может быть любым, что вы хотите. Значение, которое вы используете для каждого вызова requestPermissions()
в действии, должно иметь отличный int
, но фактические цифры не имеют значения.
Если ваша активность имеет только один вызов requestPermissions()
, значение int
действительно не имеет значения. Но многие приложения будут иметь несколько вызовов requestPermissions()
в активности. В этом случае разработчику может понадобиться знать в onRequestPermissionsResult()
, для чего этот запрос является результатом.
Ответ 2
Посмотрите чуть дальше в документации в разделе "Обратиться к запросу запроса разрешений", и вы увидите его цель.
Метод обратного вызова, называемый onRequestPermissionsResult
, получает тот же код, что и параметр, поэтому вы знаете, какое разрешение запрашивалось/предоставлялось:
@Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_READ_CONTACTS: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
Поскольку константа используется вами, вы можете дать ей любое значение, которое вам нравится, как public static final int
. Каждое запрашиваемое разрешение требует своей постоянной.
Ответ 3
Я просмотрел все ответы, но не удовлетворил свой точный необходимый ответ, поэтому вот пример, который я написал и отлично работает, даже если пользователь нажимает флажок Больше не спрашивать.
-
Создайте метод, который будет вызываться, когда вы хотите запросить разрешение во время выполнения, например readContacts()
или вы также можете использовать openCamera()
как показано ниже:
private void readContacts() {
if (!askContactsPermission()) {
return;
} else {
queryContacts();
} }
Теперь нам нужно сделать askContactsPermission()
, вы также можете назвать его как askCameraPermission()
или любое askCameraPermission()
разрешение, которое вы собираетесь запрашивать.
private boolean askContactsPermission() {
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.M) {
return true;
}
if (checkSelfPermission(READ_CONTACTS) == PackageManager.PERMISSION_GRANTED) {
return true;
}
if (shouldShowRequestPermissionRationale(READ_CONTACTS)) {
Snackbar.make(parentLayout, R.string.permission_rationale, Snackbar.LENGTH_INDEFINITE)
.setAction(android.R.string.ok, new View.OnClickListener() {
@Override
@TargetApi(Build.VERSION_CODES.M)
public void onClick(View v) {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
}
}).show();
} else if (contactPermissionNotGiven) {
openPermissionSettingDialog();
} else {
requestPermissions(new String[]{READ_CONTACTS}, REQUEST_READ_CONTACTS);
contactPermissionNotGiven = true;
}
return false;
}
Перед написанием этой функции убедитесь, что вы определили приведенную ниже переменную экземпляра, как показано ниже:
private View parentLayout;
private boolean contactPermissionNotGiven;;
/**
* Id to identity READ_CONTACTS permission request.
*/
private static final int REQUEST_READ_CONTACTS = 0;
Теперь последний шаг для переопределения метода onRequestPermissionsResult
как показано ниже:
/**
* Callback received when a permissions request has been completed.
*/
@RequiresApi(api = Build.VERSION_CODES.M)
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions,
@NonNull int[] grantResults) {
if (requestCode == REQUEST_READ_CONTACTS) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
queryContacts();
}
}
}
Здесь мы закончили с разрешениями RunTime, надстройкой является openPermissionSettingDialog()
который просто открывает экран настроек, если пользователь навсегда отключил разрешение, установив флажок "Больше не спрашивать". ниже метод:
private void openPermissionSettingDialog() {
String message = getString(R.string.message_permission_disabled);
AlertDialog alertDialog =
new AlertDialog.Builder(MainActivity.this, AlertDialog.THEME_DEVICE_DEFAULT_LIGHT)
.setMessage(message)
.setPositiveButton(getString(android.R.string.ok),
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
Intent intent = new Intent();
intent.setAction(Settings.ACTION_APPLICATION_DETAILS_SETTINGS);
Uri uri = Uri.fromParts("package", getPackageName(), null);
intent.setData(uri);
startActivity(intent);
dialog.cancel();
}
}).show();
alertDialog.setCanceledOnTouchOutside(true);
}
Что мы пропустили? 1. Определение используемых строк в strings.xml
<string name="permission_rationale">"Contacts permissions are needed to display Contacts."</string>
<string name="message_permission_disabled">You have disabled the permissions permanently,
To enable the permissions please go to Settings -> Permissions and enable the required Permissions,
pressing OK you will be navigated to Settings screen</string>
-
Инициализация parentLayout
переменной внутри onCreate
метода
parentLayout = findViewById (R.id.content);
-
Определение необходимого разрешения в AndroidManifest.xml
<uses-permission android:name="android.permission.READ_CONTACTS" />
-
Метод queryContacts
, основанный на вашей потребности или разрешении времени выполнения, вы можете вызвать свой метод, до которого это permission
было необходимо. в моем случае я просто использую загрузчик, чтобы получить контакт, как показано ниже:
private void queryContacts() {
getLoaderManager().initLoader(0, null, this);}
Это прекрасно работает счастливое кодирование :)
Ответ 4
public class SplashActivity extends RuntimePermissionsActivity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_splash);
SplashActivity.super.requestAppPermissions(new
String[]{android.Manifest.permission.READ_PHONE_STATE,
Manifest.permission.WRITE_EXTERNAL_STORAGE,
Manifest.permission.READ_EXTERNAL_STORAGE}, R.string.app_name
, 20);
}
@Override
public void onPermissionsGranted(int requestCode) {
try {
TelephonyManager tele = (TelephonyManager) getApplicationContext()
.getSystemService(Context.TELEPHONY_SERVICE);
String imei =tele.getDeviceId()
} catch (Exception e) {
e.printStackTrace();
}
}
public abstract class RuntimePermissionsActivity extends AppCompatActivity {
private SparseIntArray mErrorString;
@Override
protected void onCreate(@Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
mErrorString = new SparseIntArray();
}
@Override
public void onRequestPermissionsResult(int requestCode, String[] permissions, int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
for (int permission : grantResults) {
permissionCheck = permissionCheck + permission;
}
if ((grantResults.length > 0) && permissionCheck == PackageManager.PERMISSION_GRANTED) {
onPermissionsGranted(requestCode);
} else {
finish();
}
}
public void requestAppPermissions(final String[] requestedPermissions,
final int stringId, final int requestCode) {
mErrorString.put(requestCode, stringId);
int permissionCheck = PackageManager.PERMISSION_GRANTED;
boolean shouldShowRequestPermissionRationale = false;
for (String permission : requestedPermissions) {
permissionCheck = permissionCheck + ContextCompat.checkSelfPermission(this, permission);
shouldShowRequestPermissionRationale = shouldShowRequestPermissionRationale || ActivityCompat.shouldShowRequestPermissionRationale(this, permission);
}
if (permissionCheck != PackageManager.PERMISSION_GRANTED) {
if (shouldShowRequestPermissionRationale) {
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
/*Snackbar.make(findViewById(android.R.id.content), stringId,
Snackbar.LENGTH_INDEFINITE).setAction("GRANT",
new View.OnClickListener() {
@Override
public void onClick(View v) {
ActivityCompat.requestPermissions(RuntimePermissionsActivity.this, requestedPermissions, requestCode);
}
}).show();*/
} else {
ActivityCompat.requestPermissions(this, requestedPermissions, requestCode);
}
} else {
onPermissionsGranted(requestCode);
}
}
public abstract void onPermissionsGranted(int requestCode);
}