Android 10 – Location Permissions

Filed Under: Android

In this tutorial, we’ll be discussing and implementing the new location permissions model in our android application.

Note: Google has taken a detour from the Android Alphabetical versions. Android Q has been renamed to Android 10. Since this tutorial was written before Google decided to do this, you’ll see Android Q at some places in the article.

Android 10 Location Permissions

With the introduction of Android 10, besides the dialog UI, the way of handling location permissions has also changed.
Now the user is allowed to choose whether they want location updates when the app is in the background.
For that a new permission needs to be declared in the Manifest file:


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

Calling this along with COARSE_LOCATION would pop up a dialog with three options:

  • Always Allow
  • Allow only while using the app
  • Deny

On selecting Deny, the next time the dialog will show a fourth option – Deny & Do Not Ask Again.

Always Allow ensures that you can poll for location updates in foreground and background.

If you select “Allow only while using the app”, the next time the permission dialog will only ask you to always allow the location permission or deny.

In the following section, we’ll be implementing our first Android Q Application.
Let’s update the SDK Manager and also create a new AVD with Android Q.

Project Structure

Our build.gradle file is given below:


apply plugin: 'com.android.application'

android {
    compileSdkVersion 'android-Q'
    defaultConfig {
        applicationId "com.journaldev.androidqlocationpermissions"
        minSdkVersion 16
        targetSdkVersion 'Q'
        versionCode 1
        versionName "1.0"
        testInstrumentationRunner "android.support.test.runner.AndroidJUnitRunner"
    }
    buildTypes {
        release {
            minifyEnabled false
            proguardFiles getDefaultProguardFile('proguard-android-optimize.txt'), 'proguard-rules.pro'
        }
    }
}

dependencies {
    implementation fileTree(dir: 'libs', include: ['*.jar'])
    implementation 'androidx.appcompat:appcompat:1.1.0-alpha03'
    implementation 'com.android.support.constraint:constraint-layout:1.1.3'
    testImplementation 'junit:junit:4.12'
    androidTestImplementation 'com.android.support.test:runner:1.0.2'
    androidTestImplementation 'com.android.support.test.espresso:espresso-core:3.0.2'
}

We’ve upgraded the dependencies for Android – Q.

Code

The code for the activity_main.xml layout is given below:


<?xml version="1.0" encoding="utf-8"?>
<android.support.constraint.ConstraintLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:app="http://schemas.android.com/apk/res-auto"
    xmlns:tools="http://schemas.android.com/tools"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context=".MainActivity">

    <Button
        android:id="@+id/btnPermissions"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="LOCATION PERMISSION"
        app:layout_constraintBottom_toBottomOf="parent"
        app:layout_constraintLeft_toLeftOf="parent"
        app:layout_constraintRight_toRightOf="parent"
        app:layout_constraintTop_toTopOf="parent" />

</android.support.constraint.ConstraintLayout>

Inside the MainActivity.java :


package com.journaldev.androidqlocationpermissions;


import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;

import androidx.annotation.NonNull;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;

public class MainActivity extends AppCompatActivity {

    Button btnPermissions;

    public static final int REQUEST_CODE_PERMISSIONS = 101;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        btnPermissions = findViewById(R.id.btnPermissions);

        btnPermissions.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View view) {
                requestLocationPermission();
            }
        });
    }

    private void requestLocationPermission() {

        boolean foreground = ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED;

        if (foreground) {
            boolean background = ActivityCompat.checkSelfPermission(this,
                    Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED;

            if (background) {
                handleLocationUpdates();
            } else {
                ActivityCompat.requestPermissions(this,
                        new String[]{Manifest.permission.ACCESS_BACKGROUND_LOCATION}, REQUEST_CODE_PERMISSIONS);
            }
        } else {
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_COARSE_LOCATION,
                            Manifest.permission.ACCESS_BACKGROUND_LOCATION}, REQUEST_CODE_PERMISSIONS);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);
        if (requestCode == REQUEST_CODE_PERMISSIONS) {

            boolean foreground = false, background = false;

            for (int i = 0; i < permissions.length; i++) {
                if (permissions[i].equalsIgnoreCase(Manifest.permission.ACCESS_COARSE_LOCATION)) {
                    //foreground permission allowed
                    if (grantResults[i] >= 0) {
                        foreground = true;
                        Toast.makeText(getApplicationContext(), "Foreground location permission allowed", Toast.LENGTH_SHORT).show();
                        continue;
                    } else {
                        Toast.makeText(getApplicationContext(), "Location Permission denied", Toast.LENGTH_SHORT).show();
                        break;
                    }
                }

                if (permissions[i].equalsIgnoreCase(Manifest.permission.ACCESS_BACKGROUND_LOCATION)) {
                    if (grantResults[i] >= 0) {
                        foreground = true;
                        background = true;
                        Toast.makeText(getApplicationContext(), "Background location location permission allowed", Toast.LENGTH_SHORT).show();
                    } else {
                        Toast.makeText(getApplicationContext(), "Background location location permission denied", Toast.LENGTH_SHORT).show();
                    }

                }
            }

            if (foreground) {
                if (background) {
                    handleLocationUpdates();
                } else {
                    handleForegroundLocationUpdates();
                }
            }
        }
    }

    private void handleLocationUpdates() {
        //foreground and background
        Toast.makeText(getApplicationContext(),"Start Foreground and Background Location Updates",Toast.LENGTH_SHORT).show();
    }

    private void handleForegroundLocationUpdates() {
        //handleForeground Location Updates
        Toast.makeText(getApplicationContext(),"Start foreground location updates",Toast.LENGTH_SHORT).show();
    }
}

In the onRequestPermissionResult method, we check whether the permission is granted or not.
If the foreground location permission is not granted then we break out of the loop.
This is because, without the foreground permission allowed, the background location permission is of no use.

Once the permission is granted, you can poll for the location updates.

The output of the above application in action is given below:

Android Q Location Permissions Output 1

Android Q Location Permissions Output 1

We can go to the Settings | Apps | Permissions to view the permission is granted or not as shown in the illustration below:

Android Q Location Permissions Settings

Android Q Location Permissions Settings

Once the permission is denied and do not ask again is selected, the dialog would no longer open.

That brings an end to this tutorial. You can download the complete Android Q Location Permissions Project from the link given below or check out the Github Repository for the full source code.

Leave a Reply

Your email address will not be published. Required fields are marked *

close
Generic selectors
Exact matches only
Search in title
Search in content
Search in posts
Search in pages