简体   繁体   中英

Xamarin Android Request Runtime Permissions Not Working

so I am trying to ask the user for permission to use Location on the app that I am trying to create. I have included the permission in Android Manifest

<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

And in my SplashActivity page where the Splash Screen is and where I want my permissions to appear to the user i have put the following code in:

namespace Cabiee.Droid
{
[Activity(Theme  = "@style/Theme.Splash",
    MainLauncher = true,
    NoHistory = true,
    Icon = "@drawable/CabieBackground")]
public class SplashActivity : Activity
{

    protected async override void OnCreate(Bundle savedInstanceState)
    {
        await TryToGetPermissions();


        base.OnCreate(savedInstanceState);
        System.Threading.Thread.Sleep(500);
        StartActivity(typeof(Login));

        // Create your application here
    }


    #region RuntimePermissions

    async Task TryToGetPermissions()
    {
        if ((int)Build.VERSION.SdkInt >= 23)
        {
            await GetPermissionsAsync();
            return;
        }


    }
    const int RequestLocationId = 0;

    readonly string[] PermissionsGroupLocation =
        {
                        //TODO add more permissions
                        Manifest.Permission.AccessCoarseLocation,
                        Manifest.Permission.AccessFineLocation,
         };
    async Task GetPermissionsAsync()
    {
        const string permission = Manifest.Permission.AccessFineLocation;

        if (CheckSelfPermission(permission) == (int)Android.Content.PM.Permission.Granted)
        {
            //TODO change the message to show the permissions name
            Toast.MakeText(this, "Special permissions granted", ToastLength.Short).Show();
            return;
        }

        if (ShouldShowRequestPermissionRationale(permission))
        {
            //set alert for executing the task
            AlertDialog.Builder alert = new AlertDialog.Builder(this);
            alert.SetTitle("Permissions Needed");
            alert.SetMessage("The application need special permissions to continue");
            alert.SetPositiveButton("Request Permissions", (senderAlert, args) =>
            {
                RequestPermissions(PermissionsGroupLocation, RequestLocationId);
            });

            alert.SetNegativeButton("Cancel", (senderAlert, args) =>
            {
                Toast.MakeText(this, "Cancelled!", ToastLength.Short).Show();
            });

            Dialog dialog = alert.Create();
            dialog.Show();


            return;
        }

        RequestPermissions(PermissionsGroupLocation, RequestLocationId);

    }
    public override async void OnRequestPermissionsResult(int requestCode, string[] permissions, [GeneratedEnum] Android.Content.PM.Permission[] grantResults)
    {
        switch (requestCode)
        {
            case RequestLocationId:
                {
                    if (grantResults[0] == (int)Android.Content.PM.Permission.Granted)
                    {
                        Toast.MakeText(this, "Special permissions granted", ToastLength.Short).Show();

                    }
                    else
                    {
                        //Permission Denied :(
                        Toast.MakeText(this, "Special permissions denied", ToastLength.Short).Show();

                    }
                }
                break;
        }
        //base.OnRequestPermissionsResult(requestCode, permissions, grantResults);
    }

    #endregion
}

However, the user isn't being asked for the permssions. I think it might have something to do with the await TryToGetPermissions(); line towards the start of the code which is not actually calling the TryToGetPermissions and therefore it is not working.

Any help would be greatly appreciated.

Thanks!

If you don't require async/await, below is what I did in my app where I needed Camera permissions. It works great for my needs and maybe it will for you as well.

Your implementation would be even simpler as you wouldn't need to iterate multiple results in OnRequestPermissionsResult(). I had to do that as my app needs to save the pictures, and therefore needs both the Camera and WriteExternalStorage permissions before I can load the camera interface/activity.

[Activity(Label = "@string/app_name", Theme = "@style/AppTheme.NoActionBar", MainLauncher = true, ScreenOrientation = ScreenOrientation.Landscape)]
public class MainLoaderActivity : AppCompatActivity {

    private const string LOG_TAG = "CAMERA2_LOG";        
    private const int PERMISSION_REQUEST_CODE_CAMERA_USAGE = 4500;  // Arbitrary number to identify our permissions required for camera app usage
    private Button btnLoadCameraActivity;

    protected override void OnCreate(Bundle savedInstanceState) {
        base.OnCreate(savedInstanceState);
        SetContentView(Resource.Layout.main_loader);
        btnLoadCameraActivity = FindViewById<Button>(Resource.Id.btnLoadCameraActivity);
        btnLoadCameraActivity.Click += btnLoadCameraActivity_Click;
    }

    private void btnLoadCameraActivity_Click(object sender, EventArgs e) {
        // Using the camera on Android 6.0 and later requires a run-time permissions granting by the user.
        // So, check to see if user manually enabled in Settings, or previously was prompted in this app and was granted access.  If not, we'll prompt them...

        if (CheckSelfPermission(Android.Manifest.Permission.Camera) == Permission.Granted && 
            CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage) == Permission.Granted) {
            // We have both permissions necessary to run the Camera interface...
            StartActivity(typeof(CameraActivity));
            return;
        }

        // If we get here, at least one of the required permissions hasn't been approved, so find out which one and request accordingly...
        var listPermissions = new System.Collections.Generic.List<string>();

        // Build array of permissions needed for Camera usage
        if (CheckSelfPermission(Android.Manifest.Permission.Camera) != Permission.Granted) {
            Log.Warn(LOG_TAG, "CheckSelfPermission(Camera) not yet granted - will prompt user for permission");
            listPermissions.Add(Android.Manifest.Permission.Camera);
        }
        if (CheckSelfPermission(Android.Manifest.Permission.WriteExternalStorage) != Permission.Granted) {
            Log.Warn(LOG_TAG, "CheckSelfPermission(WriteExternalStorage) not yet granted - will prompt user for permission");
            listPermissions.Add(Android.Manifest.Permission.WriteExternalStorage);
        }

        // Make the request with the permissions needed...and then check OnRequestPermissionsResult() for the results
        RequestPermissions(listPermissions.ToArray(), PERMISSION_REQUEST_CODE_CAMERA_USAGE);
    }

    public override void OnRequestPermissionsResult(int requestCode, string[] permissions, Android.Content.PM.Permission[] grantResults) {
        Log.Info(LOG_TAG, $"OnRequestPermissionsResult(requestCode={requestCode} - Permissions Count={permissions.Length} - GrantResults Count={grantResults.Length})");
        switch (requestCode) {
            // To use the camera, the user must grant privs to the Camera as well as writing to external storage, so this case checks both
            case PERMISSION_REQUEST_CODE_CAMERA_USAGE: {                    
                for (var i = 0; i < permissions.Length; i++) {
                    Log.Info(LOG_TAG, $"Checking permission for {permissions[i]}...");
                    if (grantResults[i] != Permission.Granted) {
                        Log.Info(LOG_TAG, $"Permission Denied for {permissions[i]}!");
                        Toast.MakeText(this, "You must approve all permissions prompted to use the camera.", ToastLength.Long).Show();
                        return;
                    }
                    Log.Info(LOG_TAG, $"Permission Granted for {permissions[i]}.");
                }
                // If we get here then all the permissions we requested were approved and we can now load the Camera interface
                StartActivity(typeof(CameraActivity));
                break;
            }
        }
    }

}

I have a working solution for the exact same thing which is something as follows:

In your OnCreate method check for existing permissions:

 if (!(CheckPermissionGranted(Manifest.Permission.AccessCoarseLocation) &&
            CheckPermissionGranted(Manifest.Permission.AccessFineLocation)))
        {
            RequestLocationPermission();
        }
        else
        {
            InitializeLocationManager();
        }
        InitPageWidgets();

Where Check permission Granted is a method something like this:

 [Export]
    public bool CheckPermissionGranted(string Permissions)
    {
        // Check if the permission is already available.
        if (ActivityCompat.CheckSelfPermission(this, Permissions) != Permission.Granted)
        {
            return false;
        }
        else
        {
            return true;
        }


    }

And the Request permission code looks something like this:

  private void RequestLocationPermission()
    {
        if (ActivityCompat.ShouldShowRequestPermissionRationale(this, Manifest.Permission.AccessFineLocation))
        {
            // Provide an additional rationale to the user if the permission was not granted
            // and the user would benefit from additional context for the use of the permission.
            // For example if the user has previously denied the permission.
            ActivityCompat.RequestPermissions(this, PermissionsLocation, REQUEST_LOCATION);

        }
        else
        {
            // Camera permission has not been granted yet. Request it directly.
            ActivityCompat.RequestPermissions(this, PermissionsLocation, REQUEST_LOCATION);
        }
    }

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM