Skip to content

Instantly share code, notes, and snippets.

@nissivm
Last active March 28, 2017 12:45
Show Gist options
  • Save nissivm/b3832ecaaa5d46af2e53c60626a5efee to your computer and use it in GitHub Desktop.
Save nissivm/b3832ecaaa5d46af2e53c60626a5efee to your computer and use it in GitHub Desktop.
Android (from Marshmallow up) - Obtain user location permission & user location
<!-- In your AndroidManifest.xml -->
<?xml version="1.0" encoding="utf-8"?>
<manifest
xmlns:android="http://schemas.android.com/apk/res/android"
package="your.app.package">
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
</manifest>
dependencies {
...
compile 'com.android.support:appcompat-v7:25.3.0'
compile 'com.google.android.gms:play-services-location:10.2.1'
}
package your.app.package;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.location.Location;
import android.os.Bundle;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.app.ActivityCompat;
import android.support.v4.content.ContextCompat;
import android.view.View;
import android.widget.Button;
import android.widget.Toast;
import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GoogleApiAvailability;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.common.api.PendingResult;
import com.google.android.gms.common.api.ResultCallback;
import com.google.android.gms.common.api.Status;
import com.google.android.gms.location.LocationListener;
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.LocationSettingsResult;
import com.google.android.gms.location.LocationSettingsStatusCodes;
import java.util.Random;
public class UserLocationActivity extends Activity implements ActivityCompat.OnRequestPermissionsResultCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener
{
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private static final String PREFS_NAME = "MyApp";
private int googleApiClientRequestCode = 0;
private int locationPermissionRequestCode = 0;
private int locationSettingsRequestCode = 0;
private boolean isReturnedFromSettings = false;
private boolean justAskedForUserLocation = false;
private AlertDialog dialog;
@Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.user_location_activity);
if (savedInstanceState != null)
{
googleApiClientRequestCode = savedInstanceState.getInt("googleApiClientRequestCode");
locationPermissionRequestCode = savedInstanceState.getInt("locationPermissionRequestCode");
locationSettingsRequestCode = savedInstanceState.getInt("locationSettingsRequestCode");
}
if (googleApiClient == null)
{
googleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
if (locationRequest == null)
{
locationRequest = LocationRequest.create()
.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
.setInterval(5 * 1000) // 5 seconds, in milliseconds
.setFastestInterval(2 * 1000); // 2 seconds, in milliseconds
}
if (googleApiClientRequestCode == 0)
{
Random r = new Random();
int min = 1000;
int max = 10000;
googleApiClientRequestCode = r.nextInt((max - min) + 1) + min;
locationPermissionRequestCode = r.nextInt((max - min) + 1) + min;
locationSettingsRequestCode = r.nextInt((max - min) + 1) + min;
}
Button button = (Button)findViewById(R.id.allowLocationBtn);
button.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
int permission = ContextCompat.checkSelfPermission(UserLocationActivity.this, android.Manifest.permission.ACCESS_FINE_LOCATION);
if (permission != PackageManager.PERMISSION_GRANTED)
{
askLocationPermission();
}
else
{
checkGoogleApiClient();
}
}
});
}
@Override
protected void onResume()
{
if (isReturnedFromSettings)
{
isReturnedFromSettings = false;
int permission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION);
if (permission == PackageManager.PERMISSION_GRANTED)
{
checkGoogleApiClient();
}
}
super.onResume();
}
@Override
protected void onPause()
{
if (dialog != null)
{
dialog.dismiss();
dialog = null;
}
super.onPause();
}
@Override
protected void onStop()
{
if (googleApiClient.isConnected())
{
googleApiClient.disconnect();
}
super.onStop();
}
@Override
public void onSaveInstanceState(Bundle outState)
{
outState.putInt("googleApiClientRequestCode", googleApiClientRequestCode);
outState.putInt("locationPermissionRequestCode", locationPermissionRequestCode);
outState.putInt("locationSettingsRequestCode", locationSettingsRequestCode);
super.onSaveInstanceState(outState);
}
//----------------------------------------------------------------------------------------//
// Ask location permission
//----------------------------------------------------------------------------------------//
private void askLocationPermission()
{
SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);
String result = settings.getString("AskedLocationPermissionFirstTime", "does not exist");
if (result.equals("does not exist"))
{
// First time app is asking for location permission.
SharedPreferences.Editor editor = settings.edit();
editor.putString("AskedLocationPermissionFirstTime", "True");
editor.apply();
ActivityCompat.requestPermissions(UserLocationActivity.this,
new String[] {android.Manifest.permission.ACCESS_FINE_LOCATION},
locationPermissionRequestCode);
}
else if (ActivityCompat.shouldShowRequestPermissionRationale(this, android.Manifest.permission.ACCESS_FINE_LOCATION))
{
// User was asked permission before, but denied.
// Never ask again was not checked.
ActivityCompat.requestPermissions(UserLocationActivity.this,
new String[] {android.Manifest.permission.ACCESS_FINE_LOCATION},
locationPermissionRequestCode);
}
else
{
// Never ask again was checked.
takeMeThereCancelDialog();
}
}
//----------------------------------------------------------------------------------------//
// Take me there / Cancel dialog
//----------------------------------------------------------------------------------------//
private void takeMeThereCancelDialog()
{
DialogInterface.OnClickListener takeMeThereListener = new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface d, int which)
{
isReturnedFromSettings = true;
dialog = null;
startActivity(new Intent(android.provider.Settings.ACTION_APPLICATION_SETTINGS));
}
};
DialogInterface.OnClickListener cancelListener = new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface d, int which)
{
dialog = null;
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(UserLocationActivity.this);
builder.setTitle("Enable my location tracking");
builder.setMessage("Just access device's settings:");
builder.setCancelable(false);
builder.setPositiveButton("Take me there", takeMeThereListener);
builder.setNegativeButton("Cancel", cancelListener);
dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();
}
//----------------------------------------------------------------------------------------//
// ActivityCompat.OnRequestPermissionsResultCallback
//----------------------------------------------------------------------------------------//
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)
{
if (requestCode == locationPermissionRequestCode)
{
if ((permissions.length == 1) &&
permissions[0].equals(android.Manifest.permission.ACCESS_FINE_LOCATION) &&
(grantResults[0] == PackageManager.PERMISSION_GRANTED))
{
// User gave her/his permission
checkGoogleApiClient();
}
}
}
//----------------------------------------------------------------------------------------//
// Check Google Api Client
//----------------------------------------------------------------------------------------//
private void checkGoogleApiClient()
{
if(googleApiClient.isConnected())
{
checkLocationSettings();
}
else
{
googleApiClient.connect();
}
}
//----------------------------------------------------------------------------------------//
// Check location settings
//----------------------------------------------------------------------------------------//
// Note: This step is important, for example, if user doesn't have gps enabled, which is necessary for fine location
private void checkLocationSettings()
{
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>()
{
@Override
public void onResult(@NonNull LocationSettingsResult result)
{
final Status status = result.getStatus();
switch (status.getStatusCode())
{
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied.
// The client can initialize location requests here.
getUserLocation();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied, but this can be fixed
// by showing the user a dialog.
try
{
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(UserLocationActivity.this, locationSettingsRequestCode);
}
catch (IntentSender.SendIntentException e)
{
// Resolution intent has been canceled or is no longer able to execute the request.
Context context = getApplicationContext();
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, "An error occurred, please try again.", duration);
toast.show();
}
break;
case 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.
String msg = "Your device was not able to meet the necessary requirements to retrieve your location in a satisfactory manner.";
DialogInterface.OnClickListener okListener = new DialogInterface.OnClickListener()
{
@Override
public void onClick(DialogInterface d, int which)
{
dialog = null;
}
};
AlertDialog.Builder builder = new AlertDialog.Builder(UserLocationActivity.this);
builder.setMessage(msg);
builder.setCancelable(false);
builder.setPositiveButton("Ok", okListener);
dialog = builder.create();
dialog.setCanceledOnTouchOutside(false);
dialog.show();
break;
}
}
});
}
//----------------------------------------------------------------------------------------//
// Get user location
//----------------------------------------------------------------------------------------//
private void getUserLocation()
{
int permission = ContextCompat.checkSelfPermission(this, android.Manifest.permission.ACCESS_FINE_LOCATION);
if (permission == PackageManager.PERMISSION_GRANTED)
{
PendingResult<Status> result = LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
result.setResultCallback(new ResultCallback<Status>()
{
@Override
public void onResult(@NonNull Status status)
{
if (status.isSuccess())
{
// If in a real device, onLocationChanged(Location location) will be automatically called
}
else
{
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, UserLocationActivity.this);
}
}
});
}
}
//----------------------------------------------------------------------------------------//
// LocationListener
//----------------------------------------------------------------------------------------//
@Override
public void onLocationChanged(Location location) // Not called in simulator
{
double userLat = location.getLatitude();
double userLong = location.getLongitude();
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
// Do some action with user coordinates
}
//----------------------------------------------------------------------------------------//
// onActivityResult
//----------------------------------------------------------------------------------------//
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data)
{
if (resultCode == RESULT_OK)
{
if (requestCode == locationSettingsRequestCode)
{
checkLocationSettings();
}
else if (requestCode == googleApiClientRequestCode)
{
googleApiClient.connect();
}
}
else
{
Context context = getApplicationContext();
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, "An error occurred, please try again.", duration);
toast.show();
}
}
//----------------------------------------------------------------------------------------//
// ConnectionCallbacks
//----------------------------------------------------------------------------------------//
@Override
public void onConnected(@Nullable Bundle bundle)
{
checkLocationSettings();
}
@Override
public void onConnectionSuspended(int i) {}
//----------------------------------------------------------------------------------------//
// OnConnectionFailedListener
//----------------------------------------------------------------------------------------//
@Override
public void onConnectionFailed(@NonNull ConnectionResult result)
{
GoogleApiAvailability avail = GoogleApiAvailability.getInstance();
int errorCode = result.getErrorCode();
if (avail.isUserResolvableError(errorCode))
{
avail.getErrorDialog(this, errorCode, googleApiClientRequestCode).show();
}
else
{
Context context = getApplicationContext();
int duration = Toast.LENGTH_LONG;
Toast toast = Toast.makeText(context, "An error occurred, please try again.", duration);
toast.show();
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment