I am writing a Xamarin (android flavor) app, OS 12, and am trying to call ActivityCompat.RequestPermissions. Maybe I'm expecting the wrong behavior, since I'm not familiar with this stuff. I expect no matter how many times I run the app, that calling ActivityCompat.RequestPermissions( xxx, yyy, 1 ) will popup a system OS dialog box and ask the user to permit or deny the permissions I specify...
In my MainActivity for my Xamarin Forms (android) app, I correctly init Xamarin Essentials...
I override OnRequestPermissionsResult( )....
Now, in my one LoginViewModel, I call back into MainActivity (via a callback) and inside THAT callback, in MainActivity, it calls
public void Foo()
{
foreach (string s in m_szNeededAppPermissions)
{
bool b = ActivityCompat.ShouldShowRequestPermissionRationale(this, s);
System.Diagnostics.Debug.WriteLine("should show request for " s ", = " b);
}
ActivityCompat.RequestPermissions(this, m_szNeededAppPermissions.ToArray(), 1);
}
Not that big of a deal, right? First time I run the app, the OS dialog for allowing permissions work GREAT. Now if I press "Deny" in those permissions dialogs, I get called back with OnRequestPermissionsResult( ) and the grantResults are -1. Super, that's what I'd expect.
Now, if I stop the app debugging and run it AGAIN, the 2nd time it calls Foo( ) which calls ActivityCompat.RequestPermissions( ), I get a callback immediately with OnRequestPermissionsResult( ) with denied grantResults. No OS dialogs. If I go in and delete the app and re-start debugging, I DO get the OS permission dialogs again.
I think it's because when I say "No" to the 1st-run OS permissions dialogs, it's taking that answer as "never ask again". I think somehow the OS itself is remembering not to show the OS dialogs a 2nd time, even though i'm ASKING it to! How weird!
I think my expectations must be off, or I'm missing 1 key step. Can anybody explain why?
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
// OS dialog ran and told us which permissions user accepted vs which ones they denied.
// We look at them and then call back with whether they all succeeded or not.
bool bGotAllPermissions = true;
foreach( Permission p in grantResults )
{
if( p != Permission.Granted )
{
bGotAllPermissions = false;
break;
}
}
// ps.OnRequestPermissionsResult(bGotAllPermissions);
}
here is the main activity:
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity, ICallbackApp
{
PermissionsService ps;
string[] m_szNeededAppPermissions = { Manifest.Permission.AccessFineLocation, Manifest.Permission.BluetoothAdmin };
protected override void OnCreate(Bundle savedInstanceState)
{
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState);
global::Xamarin.Forms.Forms.Init(this, savedInstanceState);
DependencyService.RegisterSingleton<ICallbackApp>(this);
ps = new PermissionsService(this, m_szNeededAppPermissions);
LoadApplication(new App());
}
and in the view model:
public LoginViewModel()
{
LoginCommand = new Command(OnLoginClicked);
// m_pCrossPlatUtils = DependencyService.Get<ICrossPlatUtils>();
// RefreshPermissions();
Foo();
}
public void Foo()
{
ICallbackApp p = DependencyService.Get<ICallbackApp>();
p.Foo();
}
CodePudding user response:
Yes,in xamarin, we recommend you use Xamarin.Essentials: Permissions just as json said,which provides the ability to check and request runtime permissions.
This API uses runtime permissions on Android. Please ensure that Xamarin.Essentials is fully initialized and permission handling is setup in your app.
In the Android project's MainLauncher
or any Activity that is launched Xamarin.Essentials must be initialized in the OnCreate
method:
protected override void OnCreate(Bundle savedInstanceState)
{
//...
base.OnCreate(savedInstanceState);
Xamarin.Essentials.Platform.Init(this, savedInstanceState); // add this line to your code, it may also be called: bundle
//...
}
To handle runtime permissions on Android, Xamarin.Essentials must receive any OnRequestPermissionsResult
. Add the following code to all Activity
classes:
public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults)
{
Xamarin.Essentials.Platform.OnRequestPermissionsResult(requestCode, permissions, grantResults);
base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
}
For more,, you can check document:https://docs.microsoft.com/en-us/xamarin/essentials/permissions?tabs=android .
CodePudding user response:
The answer these days is different than it used to be. Both iOS and Android are getting tighter about "bugging users for permissions". If you open the system OS permissions dialog to ask the user for permission, if they Deny them, then on successive runs of the app, or future usages of RequestPermissions( ), it WILL NOT SHOW the OS permissions dialog for those permissions that were denied previously! Yeah. That.
The only ways around this, if your app needs those permissions to run are:
- Ask the user to reinstall the app
- Bring up the app's settings pages and ask them to "fix it themselves", and then verify it is fixed when the user returns to the temporarily backgrounded app (backgrounded in order to show the App's settings page)
I think this is all true, I got it from a pretty reliable Xamarin source @ MSFT....