Разрешения среды выполнения Android широко известны как проблемные, в вашем случае проблема в том, что панель пользовательского интерфейса запроса разрешений Android захватывает передний план на первом Permission.RequestUserPermission, приостанавливая работу вашего приложения и предотвращая выполнение следующего кода
Самое чистое решение, которое я до сих пор рассматривал для обработки прав доступа, состоит в том, чтобы запустить бесконечный цикл в сопрограмму, которая жадно проверяет необходимые вам разрешения и предлагает пользователю предоставить каждое из них, если оно не
ЭтоНа первый взгляд может показаться уродливым, но учтите, что при запросе разрешения цикл прерывается по той же причине, по которой ваш код не работает: потому что панель пользовательского интерфейса запроса разрешения захватывает передний план, и ваше приложение приостанавливается, когда фокусПосле возвращения ваш цикл снова начинает проверять отсутствующие разрешения, плюс вы можете замедлить ваш цикл с возвращением доходности, новым WaitForSeconds (0.2f)
Это код с некоторым оформлением, чтобы уведомить вас. Так как он не может работать без предоставления всех необходимых разрешений:
private bool _locationPermissionAsked;
private bool _microphonePermissionAsked;
private bool _cameraPermissionAsked;
private bool _storagePermissionAsked;
private void Start()
{
#if UNITY_ANDROID && !UNITY_EDITOR
StartCoroutine(RequestPermissionsRoutine());
#else
/***** Ready to run you app *****/
#endif
}
private IEnumerator RequestPermissionsRoutine()
{
yield return new WaitForEndOfFrame();
while (true)
{
// For each permission you need, build a block like the following, it could
// have been done dynamically but given the small ammount of possible options
// I preferred to keep it extended
if (!Permission.HasUserAuthorizedPermission(Permission.FineLocation) && !_locationPermissionAsked)
{
// This flag keeps track of the user choice against the permission panel
//
// if he choose to NOT grant the permission we skip the permission request
// because we are gonna notify him that he needs to grant the permission later
// using a message in our App
_locationPermissionAsked = true;
// You can even ask permissions using android literal definition instead of Unity's Permission.FineLocation
yield return Permission.RequestPermission("android.permission.ACCESS_FINE_LOCATION").WaitForCompletion();
continue;
}
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone) && !_microphonePermissionAsked)
{
_microphonePermissionAsked = true;
yield return Permission.RequestPermission(Permission.Microphone).WaitForCompletion();
continue;
}
if (!Permission.HasUserAuthorizedPermission(Permission.Camera) && !_cameraPermissionAsked)
{
_cameraPermissionAsked = true;
yield return Permission.RequestPermission(Permission.Camera).WaitForCompletion();
continue;
}
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite) && !_storagePermissionAsked)
{
_storagePermissionAsked = true;
yield return Permission.RequestPermission(Permission.ExternalStorageWrite);
continue;
}
// This is the part where we check if all the permissions were granted
// and allow the user to run the App ( else condition )
// or prompt him to grant the permissions he denied
//
// Note that this code is never reached before each permission have been asked
// once, because of the "continue;"s used before
if (!Permission.HasUserAuthorizedPermission(Permission.FineLocation) ||
!Permission.HasUserAuthorizedPermission(Permission.Microphone) ||
!Permission.HasUserAuthorizedPermission(Permission.Camera) ||
!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
{
if (!Permission.HasUserAuthorizedPermission(Permission.FineLocation))
{
/***** Tell the user to grant FineLocation Permission *****/
}
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
{
/***** Tell the user to grant Microphone Permission *****/
}
if (Permission.HasUserAuthorizedPermission(Permission.Camera))
{
/***** Tell the user to grant Camera Permission *****/
}
if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
{
/***** Tell the user to grant ExternalStorageWrite Permission *****/
}
/***** This is where all permissions have been asked once *****/
/***** and one or more were NOT granted, *****/
/***** you can write the code to handle this fallback here *****/
}
else
{
// I like to give some time to the Android looper before running my App, just to be safe
yield return new WaitForSeconds(1f);
/***** Ready to run you App *****/
}
// Slow down the loop by a little bit, not strictly needed but not harmful either
yield return new WaitForSeconds(0.2f);
}
}
Это работает даже в тех случаях, когда, например, пользователь отказывает в одном разрешении и затем принудительно убивает ваше приложение, или какое-то другое приложение захватываетнеожиданно на переднем плане и другие рискованные случаи, с которыми я сталкивался до сих пор
Я добавлю небольшой плюс: если вы используете Google ARCore, имейте в виду, что он переопределяет оригинальный механизм запроса разрешений Unity (https://github.com/google-ar/arcore-unity-sdk/issues/151)поощряя разработчиков использовать свой собственный GoogleARCore.AndroidPermissionsManager вместо UnityEngine.Android.Permission, в результате чего UnityEngine.Android.Permission не будет работать, вы все равно можете использовать этот скрипт, но вам нужно будет заменить все «Permission.RequestUserPermission» на«AndroidPermissionsManager.RequestUserPermission» (вам не нужно заменять «Permission.HasUserAuthorizedPermission», они все еще работают), или даже лучше, я могу сделать это для вас:
private IEnumerator RequestPermissionsRoutine()
{
yield return new WaitForEndOfFrame();
while (true)
{
if (!Permission.HasUserAuthorizedPermission(Permission.FineLocation) && !_locationPermissionAsked)
{
_locationPermissionAsked = true;
yield return AndroidPermissionsManager.RequestPermission("android.permission.ACCESS_FINE_LOCATION").WaitForCompletion();
continue;
}
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone) && !_microphonePermissionAsked)
{
_microphonePermissionAsked = true;
yield return AndroidPermissionsManager.RequestPermission(Permission.Microphone).WaitForCompletion();
continue;
}
if (!Permission.HasUserAuthorizedPermission(Permission.Camera) && !_cameraPermissionAsked)
{
_cameraPermissionAsked = true;
yield return AndroidPermissionsManager.RequestPermission(Permission.Camera).WaitForCompletion();
continue;
}
if (!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite) && !_storagePermissionAsked)
{
_storagePermissionAsked = true;
yield return AndroidPermissionsManager.RequestPermission(Permission.ExternalStorageWrite);
continue;
}
if (!Permission.HasUserAuthorizedPermission(Permission.FineLocation) ||
!Permission.HasUserAuthorizedPermission(Permission.Microphone) ||
!Permission.HasUserAuthorizedPermission(Permission.Camera) ||
!Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
{
if (!Permission.HasUserAuthorizedPermission(Permission.FineLocation))
{
/***** Tell the user to grant FineLocation Permission *****/
}
if (!Permission.HasUserAuthorizedPermission(Permission.Microphone))
{
/***** Tell the user to grant Microphone Permission *****/
}
if (Permission.HasUserAuthorizedPermission(Permission.Camera))
{
/***** Tell the user to grant Camera Permission *****/
}
if (Permission.HasUserAuthorizedPermission(Permission.ExternalStorageWrite))
{
/***** Tell the user to grant ExternalStorageWrite Permission *****/
}
/***** This is where all permissions have been asked once *****/
/***** and one or more were NOT granted, *****/
/***** you can write the code to handle this fallback here *****/
}
else
{
yield return new WaitForSeconds(1f);
/***** Ready to run you App *****/
}
yield return new WaitForSeconds(0.2f);
}
}