java – How to request Location Permission at runtime-ThrowExceptions

Exception or error:

In the manifest file I added permissions coarse and fine, and when I run on device with Android 6, nothing happens! I try
everything but no way to get location updates…

What am I doing wrong?

public class MainActivity extends AppCompatActivity implements LocationListener {

    LocationManager locationManager;
    String provider;

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

        locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);

        provider = locationManager.getBestProvider(new Criteria(), false);

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        Location location = locationManager.getLastKnownLocation(provider);

        if (location != null) {

            Log.i("Location Info", "Location achieved!");

        } else {

            Log.i("Location Info", "No location :(");

        }

    }


    @Override
    protected void onResume() {
        super.onResume();

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        locationManager.requestLocationUpdates(provider, 400, 1, this);

    }

    @Override
    protected void onPause() {
        super.onPause();

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        locationManager.removeUpdates(this);

    }

    @Override
    public void onLocationChanged(Location location) {

        Double lat = location.getLatitude();
        Double lng = location.getLongitude();

        Log.i("Location info: Lat", lat.toString());
        Log.i("Location info: Lng", lng.toString());

    }

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {

    }

    @Override
    public void onProviderEnabled(String provider) {

    }

    @Override
    public void onProviderDisabled(String provider) {

    }

    public void getLocation(View view) {

        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            // TODO: Consider calling
            //    ActivityCompat#requestPermissions
            // here to request the missing permissions, and then overriding
            //   public void onRequestPermissionsResult(int requestCode, String[] permissions,
            //                                          int[] grantResults)
            // to handle the case where the user grants the permission. See the documentation
            // for ActivityCompat#requestPermissions for more details.
            return;
        }
        Location location = locationManager.getLastKnownLocation(provider);

        onLocationChanged(location);


    }

}
How to solve:

You need to actually request the Location permission at runtime (notice the comments in your code stating this).

Here is tested and working code to request the Location permission.

Be sure to import android.Manifest:

import android.Manifest;

Then put this code in the Activity:

public static final int MY_PERMISSIONS_REQUEST_LOCATION = 99;

public boolean checkLocationPermission() {
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            != PackageManager.PERMISSION_GRANTED) {

        // Should we show an explanation?
        if (ActivityCompat.shouldShowRequestPermissionRationale(this,
                Manifest.permission.ACCESS_FINE_LOCATION)) {

            // Show an explanation to the user *asynchronously* -- don't block
            // this thread waiting for the user's response! After the user
            // sees the explanation, try again to request the permission.
            new AlertDialog.Builder(this)
                    .setTitle(R.string.title_location_permission)
                    .setMessage(R.string.text_location_permission)
                    .setPositiveButton(R.string.ok, new DialogInterface.OnClickListener() {
                        @Override
                        public void onClick(DialogInterface dialogInterface, int i) {
                            //Prompt the user once explanation has been shown
                            ActivityCompat.requestPermissions(MainActivity.this,
                                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                                    MY_PERMISSIONS_REQUEST_LOCATION);
                        }
                    })
                    .create()
                    .show();


        } else {
            // No explanation needed, we can request the permission.
            ActivityCompat.requestPermissions(this,
                    new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
                    MY_PERMISSIONS_REQUEST_LOCATION);
        }
        return false;
    } else {
        return true;
    }
}

@Override
public void onRequestPermissionsResult(int requestCode,
                                       String permissions[], int[] grantResults) {
    switch (requestCode) {
        case MY_PERMISSIONS_REQUEST_LOCATION: {
            // If request is cancelled, the result arrays are empty.
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {

                // permission was granted, yay! Do the
                // location-related task you need to do.
                if (ContextCompat.checkSelfPermission(this,
                        Manifest.permission.ACCESS_FINE_LOCATION)
                        == PackageManager.PERMISSION_GRANTED) {

                    //Request location updates:
                    locationManager.requestLocationUpdates(provider, 400, 1, this);
                }

            } else {

                // permission denied, boo! Disable the
                // functionality that depends on this permission.

            }
            return;
        }

    }
}

Then call the checkLocationPermission() method in onCreate():

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

    //.........

    checkLocationPermission();
}

You can then use onResume() and onPause() exactly as it is in the question.

Here is a condensed version that is a bit more clean:

@Override
protected void onResume() {
    super.onResume();
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {

        locationManager.requestLocationUpdates(provider, 400, 1, this);
    }
}

@Override
protected void onPause() {
    super.onPause();
    if (ContextCompat.checkSelfPermission(this,
            Manifest.permission.ACCESS_FINE_LOCATION)
            == PackageManager.PERMISSION_GRANTED) {

        locationManager.removeUpdates(this);
    }
}

Answer:

Google has created a library for easy Permissions management. Its called EasyPermissions

Here is a simple example on requesting Location permission using this library.

public class MainActivity extends AppCompatActivity {

    private final int REQUEST_LOCATION_PERMISSION = 1;

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

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

        // Forward results to EasyPermissions
        EasyPermissions.onRequestPermissionsResult(requestCode, permissions, grantResults, this);
    }

    @AfterPermissionGranted(REQUEST_LOCATION_PERMISSION)
    public void requestLocationPermission() {
        String[] perms = {Manifest.permission.ACCESS_FINE_LOCATION};
        if(EasyPermissions.hasPermissions(this, perms)) {
            Toast.makeText(this, "Permission already granted", Toast.LENGTH_SHORT).show();
        }
        else {
            EasyPermissions.requestPermissions(this, "Please grant the location permission", REQUEST_LOCATION_PERMISSION, perms);
        }
    }
}

@AfterPermissionsGranted(REQUEST_CODE) is used to indicate the method that needs to be executed after a permission request with the request code REQUEST_CODE has been granted.

This above case, the method requestLocationPermission() method is called if the user grants the permission to access location services. So, that method acts as both a callback and a method to request the permissions.

You can implement separate callbacks for permission granted and permission denied as well. It is explained in the github page.

Answer:

I like short code. I use RxPermission for permissions.

First add these permissions (or one you need) in your manifest.xml.

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

Then ask run time permission from user in your activity.

RxPermissions rxPermissions = new RxPermissions(this);
rxPermissions
.request(Manifest.permission.ACCESS_FINE_LOCATION,
         Manifest.permission.ACCESS_COARSE_LOCATION) // ask single or multiple permission once
.subscribe(granted -> {
    if (granted) {
       // All requested permissions are granted
    } else {
       // At least one permission is denied
    }
});

add this library in your build.gradle

allprojects {
    repositories {
        ...
        maven { url 'https://jitpack.io' }
    }
}

dependencies {
    implementation 'com.github.tbruyelle:rxpermissions:0.10.1'
    implementation 'com.jakewharton.rxbinding2:rxbinding:2.1.1'
}

Isn’t this easy?

Answer:

Location permission privacy change in Android 10 or Android Q.

We have to define additional ACCESS_BACKGROUND_LOCATION permission if user wants to access their current location in background so user needs to granted permission runtime also in requestPermission()

If we are using lower than Android 10 device then ACCESS_BACKGROUND_LOCATION permission allow automatically with ACCESS_FINE_LOCATION or ACCESS_COARSE_LOCATION permission

This tabular format might be easy to understand what if we don’t specify ACCESS_BACKGROUND_LOCATION in manifest file.

enter image description here

AndroidManifest.xml

<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION" /> // here we defined ACCESS_BACKGROUND_LOCATION for Android 10 device

MainActivity.java
Call checkRunTimePermission() in onCreate() or onResume()

public void checkRunTimePermission() {
   if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
        if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED || 
             ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED||
             ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                gpsTracker = new GPSTracker(context);

        } else {
                requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION},
                        10);
        }
   } else {
            gpsTracker = new GPSTracker(context); //GPSTracker is class that is used for retrieve user current location
   }
}

 @Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults);
    if (requestCode == 10) {
        if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
            gpsTracker = new GPSTracker(context);
        } else {
            if (!ActivityCompat.shouldShowRequestPermissionRationale((Activity) context, Manifest.permission.ACCESS_FINE_LOCATION)) {
                // If User Checked 'Don't Show Again' checkbox for runtime permission, then navigate user to Settings
                AlertDialog.Builder dialog = new AlertDialog.Builder(context);
                dialog.setTitle("Permission Required");
                dialog.setCancelable(false);
                dialog.setMessage("You have to Allow permission to access user location");
                dialog.setPositiveButton("Settings", new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        Intent i = new Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS, Uri.fromParts("package",
                                context.getPackageName(), null));
                        //i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
                        startActivityForResult(i, 1001);
                    }
                });
                AlertDialog alertDialog = dialog.create();
                alertDialog.show();
            }
            //code for deny
        }
    }
}

@Override
public void startActivityForResult(Intent intent, int requestCode) {
    super.startActivityForResult(intent, requestCode);
    switch (requestCode) {
        case 1001:
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
                if (ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED ||
                        ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_COARSE_LOCATION) == PackageManager.PERMISSION_GRANTED 
                        || ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_BACKGROUND_LOCATION) == PackageManager.PERMISSION_GRANTED) {
                    gpsTracker = new GPSTracker(context);
                    if (gpsTracker.canGetLocation()) {
                        latitude = gpsTracker.getLatitude();
                        longitude = gpsTracker.getLongitude();
                    }
                } else {
                    requestPermissions(new String[]{Manifest.permission.ACCESS_COARSE_LOCATION, Manifest.permission.ACCESS_FINE_LOCATION,
                        Manifest.permission.ACCESS_BACKGROUND_LOCATION},10);
                }
            }
            break;
        default:
            break;
    }
}

build.gradle (app level)

android {
    compileSdkVersion 29 //should be >= 29
    buildToolsVersion "29.0.2"
    useLibrary 'org.apache.http.legacy'
    defaultConfig {
        applicationId "com.example.runtimepermission"
        minSdkVersion 21
        targetSdkVersion 29 //should be >= 29
        versionCode 1
        versionName "1.0"
        multiDexEnabled true
        testInstrumentationRunner "androidx.test.runner.AndroidJUnitRunner"
        vectorDrawables.useSupportLibrary = true
    }
}

Here you can find GPSTracker.java file code

Answer:

This code work for me. I also handled case “Never Ask Me”

In AndroidManifest.xml

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

In build.gradle (Module: app)

dependencies {
    ....
    implementation "com.google.android.gms:play-services-location:16.0.0"
}

This is CurrentLocationManager.kt

import android.Manifest
import android.app.Activity
import android.content.Context
import android.content.IntentSender
import android.content.pm.PackageManager
import android.location.Location
import android.location.LocationListener
import android.location.LocationManager
import android.os.Bundle
import android.os.CountDownTimer
import android.support.v4.app.ActivityCompat
import android.support.v4.content.ContextCompat
import android.util.Log
import com.google.android.gms.common.api.ApiException
import com.google.android.gms.common.api.CommonStatusCodes
import com.google.android.gms.common.api.ResolvableApiException
import com.google.android.gms.location.LocationRequest
import com.google.android.gms.location.LocationServices
import com.google.android.gms.location.LocationSettingsRequest
import com.google.android.gms.location.LocationSettingsStatusCodes
import java.lang.ref.WeakReference


object CurrentLocationManager : LocationListener {

    const val REQUEST_CODE_ACCESS_LOCATION = 123

    fun checkLocationPermission(activity: Activity) {
        if (ContextCompat.checkSelfPermission(
                activity,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) != PackageManager.PERMISSION_GRANTED
        ) {
            ActivityCompat.requestPermissions(
                activity,
                arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
                REQUEST_CODE_ACCESS_LOCATION
            )
        } else {
            Thread(Runnable {
                // Moves the current Thread into the background
                android.os.Process.setThreadPriority(android.os.Process.THREAD_PRIORITY_BACKGROUND)
                //
                requestLocationUpdates(activity)
            }).start()
        }
    }

    /**
     * be used in HomeActivity.
     */
    const val REQUEST_CHECK_SETTINGS = 55
    /**
     * The number of millis in the future from the call to start().
     * until the countdown is done and onFinish() is called.
     *
     *
     * It is also the interval along the way to receive onTick(long) callbacks.
     */
    private const val TWENTY_SECS: Long = 20000
    /**
     * Timer to get location from history when requestLocationUpdates don't return result.
     */
    private var mCountDownTimer: CountDownTimer? = null
    /**
     * WeakReference of current activity.
     */
    private var mWeakReferenceActivity: WeakReference<Activity>? = null
    /**
     * user's location.
     */
    var currentLocation: Location? = null

    @Synchronized
    fun requestLocationUpdates(activity: Activity) {
        if (mWeakReferenceActivity == null) {
            mWeakReferenceActivity = WeakReference(activity)
        } else {
            mWeakReferenceActivity?.clear()
            mWeakReferenceActivity = WeakReference(activity)
        }
        //create location request: https://developer.android.com/training/location/change-location-settings.html#prompt
        val mLocationRequest = LocationRequest()
        // Which your app prefers to receive location updates. Note that the location updates may be
        // faster than this rate, or slower than this rate, or there may be no updates at all
        // (if the device has no connectivity)
        mLocationRequest.interval = 20000
        //This method sets the fastest rate in milliseconds at which your app can handle location updates.
        // You need to set this rate because other apps also affect the rate at which updates are sent
        mLocationRequest.fastestInterval = 10000
        mLocationRequest.priority = LocationRequest.PRIORITY_HIGH_ACCURACY

        //Get Current Location Settings
        val builder = LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest)
        //Next check whether the current location settings are satisfied
        val client = LocationServices.getSettingsClient(activity)
        val task = client.checkLocationSettings(builder.build())
        //Prompt the User to Change Location Settings
        task.addOnSuccessListener(activity) {
            Log.d("CurrentLocationManager", "OnSuccessListener")
            // All location settings are satisfied. The client can initialize location requests here.
            // If it's failed, the result after user updated setting is sent to onActivityResult of HomeActivity.
            val activity1 = mWeakReferenceActivity?.get()
            if (activity1 != null) {
                startRequestLocationUpdate(activity1.applicationContext)
            }
        }

        task.addOnFailureListener(activity) { e ->
            Log.d("CurrentLocationManager", "addOnFailureListener")
            val statusCode = (e as ApiException).statusCode
            when (statusCode) {
                CommonStatusCodes.RESOLUTION_REQUIRED ->
                    // Location settings are not satisfied, but this can be fixed
                    // by showing the user a dialog.
                    try {
                        val activity1 = mWeakReferenceActivity?.get()
                        if (activity1 != null) {
                            // Show the dialog by calling startResolutionForResult(),
                            // and check the result in onActivityResult().
                            val resolvable = e as ResolvableApiException
                            resolvable.startResolutionForResult(
                                activity1, REQUEST_CHECK_SETTINGS
                            )
                        }
                    } catch (sendEx: IntentSender.SendIntentException) {
                        // Ignore the error.
                        sendEx.printStackTrace()
                    }

                LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
                    // Location settings are not satisfied. However, we have no way
                    // to fix the settings so we won't show the dialog.
                }
            }
        }
    }

    fun startRequestLocationUpdate(appContext: Context) {
        val mLocationManager = appContext.getSystemService(Context.LOCATION_SERVICE) as LocationManager
        if (ActivityCompat.checkSelfPermission(
                appContext.applicationContext,
                Manifest.permission.ACCESS_FINE_LOCATION
            ) == PackageManager.PERMISSION_GRANTED
        ) {
            //Utilities.showProgressDialog(mWeakReferenceActivity.get());
            if (mLocationManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
                mLocationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, 10000, 0f, this
                )
            } else {
                mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, 10000, 0f, this
                )
            }
        }

        /*Timer to call getLastKnownLocation() when requestLocationUpdates don 't return result*/
        countDownUpdateLocation()
    }

    override fun onLocationChanged(location: Location?) {
        if (location != null) {
            stopRequestLocationUpdates()
            currentLocation = location
        }
    }

    override fun onStatusChanged(provider: String, status: Int, extras: Bundle) {

    }

    override fun onProviderEnabled(provider: String) {

    }

    override fun onProviderDisabled(provider: String) {

    }

    /**
     * Init CountDownTimer to to get location from history when requestLocationUpdates don't return result.
     */
    @Synchronized
    private fun countDownUpdateLocation() {
        mCountDownTimer?.cancel()
        mCountDownTimer = object : CountDownTimer(TWENTY_SECS, TWENTY_SECS) {
            override fun onTick(millisUntilFinished: Long) {}

            override fun onFinish() {
                if (mWeakReferenceActivity != null) {
                    val activity = mWeakReferenceActivity?.get()
                    if (activity != null && ActivityCompat.checkSelfPermission(
                            activity,
                            Manifest.permission.ACCESS_FINE_LOCATION
                        ) == PackageManager.PERMISSION_GRANTED
                    ) {
                        val location = (activity.applicationContext
                            .getSystemService(Context.LOCATION_SERVICE) as LocationManager)
                            .getLastKnownLocation(LocationManager.PASSIVE_PROVIDER)
                        stopRequestLocationUpdates()
                        onLocationChanged(location)
                    } else {
                        stopRequestLocationUpdates()
                    }
                } else {
                    mCountDownTimer?.cancel()
                    mCountDownTimer = null
                }
            }
        }.start()
    }

    /**
     * The method must be called in onDestroy() of activity to
     * removeUpdateLocation and cancel CountDownTimer.
     */
    fun stopRequestLocationUpdates() {
        val activity = mWeakReferenceActivity?.get()
        if (activity != null) {
            /*if (ActivityCompat.checkSelfPermission(activity,
                    Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {*/
            (activity.applicationContext
                .getSystemService(Context.LOCATION_SERVICE) as LocationManager).removeUpdates(this)
            /*}*/
        }
        mCountDownTimer?.cancel()
        mCountDownTimer = null
    }
}

In MainActivity.kt

override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
...
CurrentLocationManager.checkLocationPermission(this@LoginActivity)
}

override fun onDestroy() {
        CurrentLocationManager.stopRequestLocationUpdates()
        super.onDestroy()
    }


    override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (requestCode == CurrentLocationManager.REQUEST_CODE_ACCESS_LOCATION) {
            if (grantResults[0] == PackageManager.PERMISSION_DENIED) {
                //denied
                val builder = AlertDialog.Builder(this)
                builder.setMessage("We need permission to use your location for the purpose of finding friends near you.")
                    .setTitle("Device Location Required")
                    .setIcon(com.eswapp.R.drawable.ic_info)
                    .setPositiveButton("OK") { _, _ ->
                        if (ActivityCompat.shouldShowRequestPermissionRationale(
                                this,
                                Manifest.permission.ACCESS_FINE_LOCATION
                            )
                        ) {
                            //only deny
                            CurrentLocationManager.checkLocationPermission(this@LoginActivity)
                        } else {
                            //never ask again
                            val intent = Intent(Settings.ACTION_APPLICATION_DETAILS_SETTINGS)
                            val uri = Uri.fromParts("package", packageName, null)
                            intent.data = uri
                            startActivityForResult(intent, CurrentLocationManager.REQUEST_CHECK_SETTINGS)
                        }
                    }
                    .setNegativeButton("Ask Me Later") { _, _ ->

                    }
                // Create the AlertDialog object and return it
                val dialog = builder.create()
                dialog.show()
            } else if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                CurrentLocationManager.requestLocationUpdates(this)
            }
        }
    }

    //Forward Login result to the CallBackManager in OnActivityResult()
    override fun onActivityResult(requestCode: Int, resultCode: Int, data: Intent?) {
        when (requestCode) {
            //case 1. After you allow the app access device location, Another dialog will be displayed to request you to turn on device location
            //case 2. Or You chosen Never Ask Again, you open device Setting and enable location permission
            CurrentLocationManager.REQUEST_CHECK_SETTINGS -> when (resultCode) {
                RESULT_OK -> {
                    Log.d("REQUEST_CHECK_SETTINGS", "RESULT_OK")
                    //case 1. You choose OK
                    CurrentLocationManager.startRequestLocationUpdate(applicationContext)
                }
                RESULT_CANCELED -> {
                    Log.d("REQUEST_CHECK_SETTINGS", "RESULT_CANCELED")
                    //case 1. You choose NO THANKS
                    //CurrentLocationManager.requestLocationUpdates(this)

                    //case 2. In device Setting screen: user can enable or not enable location permission,
                    // so when user back to this activity, we should re-call checkLocationPermission()
                    CurrentLocationManager.checkLocationPermission(this@LoginActivity)
                }
                else -> {
                    //do nothing
                }
            }
            else -> {
                super.onActivityResult(requestCode, resultCode, data)
            }
        }
    }

Answer:

check this code from MainActivity

 // Check location permission is granted - if it is, start
// the service, otherwise request the permission
fun checkOrAskLocationPermission(callback: () -> Unit) {
    // Check GPS is enabled
    val lm = getSystemService(Context.LOCATION_SERVICE) as LocationManager
    if (!lm.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
        Toast.makeText(this, "Please enable location services", Toast.LENGTH_SHORT).show()
        buildAlertMessageNoGps(this)
        return
    }

    // Check location permission is granted - if it is, start
    // the service, otherwise request the permission
    val permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
    if (permission == PackageManager.PERMISSION_GRANTED) {
        callback.invoke()
    } else {
        // callback will be inside the activity's onRequestPermissionsResult(
        ActivityCompat.requestPermissions(
            this,
            arrayOf(Manifest.permission.ACCESS_FINE_LOCATION),
            PERMISSIONS_REQUEST
        )
    }
}

plus

   override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
    super.onRequestPermissionsResult(requestCode, permissions, grantResults)
    if (requestCode == PERMISSIONS_REQUEST) {
        if (grantResults[0] == PackageManager.PERMISSION_GRANTED){
              // Permission ok. Do work.
         }
    }
}

plus

 fun buildAlertMessageNoGps(context: Context) {
    val builder = AlertDialog.Builder(context);
    builder.setMessage("Your GPS is disabled. Do you want to enable it?")
        .setCancelable(false)
        .setPositiveButton("Yes") { _, _ -> context.startActivity(Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS)) }
        .setNegativeButton("No") { dialog, _ -> dialog.cancel(); }
    val alert = builder.create();
    alert.show();
}

usage

checkOrAskLocationPermission() {
            // Permission ok. Do work.
        }

Leave a Reply

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