I am working on accessing the user current location and have gone through this tutorial Current location and this tutorial Current Location. Everything seems fine but latitude and longitude are not coming up in the TextView field.
Here is my code
#Keep
public class edit_information extends Fragment implements AdapterView.OnItemSelectedListener, GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener, ResultCallback<LocationSettingsResult> {
protected final static String TAG = "EditInformation";
private static final int MY_PERMISSIONS_ACCESS_LOCATION = 1;
private RadioGroup radioGroup;
private RadioGroup musicRadioGroup;
private RadioGroup decorRadioGroup;
protected static final int REQUEST_CHECK_SETTINGS = 0x1;
//The desired interval for location updates
public static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000;
//The fastest rate for active location updates
public static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = UPDATE_INTERVAL_IN_MILLISECONDS / 2;
//Keys for storing activity state in bundle
protected static final String KEY_REQUESTING_LOCATION_UPDATES = "requesting-location-updates";
protected static final String KEY_LOCATION = "location";
protected static final String KEY_LAST_UPDATED_TIME_STRING = "last-updated-time-string";
/*
Provides entry point to Google play service
*/
protected GoogleApiClient mGoogleApiClient;
//Store parametrers for request to the FusedLocationProviderApi
protected LocationRequest mLocationRequest;
//location setting request
protected LocationSettingsRequest mLocationSettingsRequest;
protected Location mCurrentLocation;
//UI
protected TextView mLatitudeText;
protected TextView mLongitudeText;
protected Boolean mRequestingLocationUpdates;
protected String mLastUpdateTime;
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
View view = inflater.inflate(R.layout.edit_information, container, false);
Spinner spinner = (Spinner) view.findViewById(R.id.spinner1);
Spinner spinner2 = (Spinner) view.findViewById(R.id.spinner2);
//Creating an array adapter using the string array and a default spinner layout
ArrayAdapter<CharSequence> adapter = ArrayAdapter.createFromResource(getContext(), R.array.hall_type, simple_spinner_item);
ArrayAdapter<CharSequence> adapter1 = ArrayAdapter.createFromResource(getContext(), R.array.hall_size, simple_spinner_item);
//Layout to choose the dropdown list
adapter.setDropDownViewResource(simple_spinner_dropdown_item);
adapter1.setDropDownViewResource(simple_spinner_dropdown_item);
spinner.setAdapter(adapter);
spinner2.setAdapter(adapter1);
spinner.setOnItemSelectedListener(this);
spinner2.setOnItemSelectedListener(this);
radioGroup = (RadioGroup) view.findViewById(R.id.food_facility);
musicRadioGroup = (RadioGroup) view.findViewById(R.id.music_facility);
decorRadioGroup = (RadioGroup) view.findViewById(R.id.decor_facility);
mLatitudeText = (TextView) view.findViewById(R.id.myLatitude);
mLongitudeText = (TextView) view.findViewById(R.id.myLongitude);
mRequestingLocationUpdates = false;
mLastUpdateTime = "";
updateValuesFromBundle(savedInstanceState);
//Start the process of building GoogleApiClient, LocationRequest and LocationSettingRequest
buildGoogleApiClient();
createLocationRequest();
buildLocationSettingsRequest();
radioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int checkedId) {
switch (checkedId) {
case R.id.yes:
Toast.makeText(getContext(), "Yes", Toast.LENGTH_SHORT).show();
break;
case R.id.may:
Toast.makeText(getContext(), "May be", Toast.LENGTH_SHORT).show();
break;
case R.id.no:
Toast.makeText(getContext(), "No", Toast.LENGTH_SHORT).show();
break;
}
}
});
musicRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
switch (i) {
case R.id.yesMusic:
Toast.makeText(getContext(), "Yes", Toast.LENGTH_SHORT).show();
break;
case R.id.mayMusic:
Toast.makeText(getContext(), "May be", Toast.LENGTH_SHORT).show();
break;
case R.id.noMusic:
Toast.makeText(getContext(), "No", Toast.LENGTH_SHORT).show();
break;
}
}
});
decorRadioGroup.setOnCheckedChangeListener(new RadioGroup.OnCheckedChangeListener() {
#Override
public void onCheckedChanged(RadioGroup radioGroup, int i) {
switch (i) {
case R.id.yesDecor:
Toast.makeText(getContext(), "Yes", Toast.LENGTH_SHORT).show();
break;
case R.id.mayDecor:
Toast.makeText(getContext(), "May be", Toast.LENGTH_SHORT).show();
break;
case R.id.noDecor:
Toast.makeText(getContext(), "No", Toast.LENGTH_SHORT).show();
break;
}
}
});
return view;
}
#Override
public void onItemSelected(AdapterView<?> adapterView, View view, int i, long l) {
Toast.makeText(adapterView.getContext(), "" + adapterView.getItemAtPosition(i).toString(), Toast.LENGTH_SHORT).show();
}
#Override
public void onNothingSelected(AdapterView<?> adapterView) {
}
private void updateValuesFromBundle(Bundle savedInstanceState) {
if (savedInstanceState != null) {
// Update the value of mRequestingLocationUpdates from the Bundle, and make sure that
// the Start Updates and Stop Updates buttons are correctly enabled or disabled.
if (savedInstanceState.keySet().contains(KEY_REQUESTING_LOCATION_UPDATES)) {
mRequestingLocationUpdates = savedInstanceState.getBoolean(
KEY_REQUESTING_LOCATION_UPDATES);
}
// Update the value of mCurrentLocation from the Bundle and update the UI to show the
// correct latitude and longitude.
if (savedInstanceState.keySet().contains(KEY_LOCATION)) {
// Since KEY_LOCATION was found in the Bundle, we can be sure that mCurrentLocation
// is not null.
mCurrentLocation = savedInstanceState.getParcelable(KEY_LOCATION);
}
// Update the value of mLastUpdateTime from the Bundle and update the UI.
if (savedInstanceState.keySet().contains(KEY_LAST_UPDATED_TIME_STRING)) {
mLastUpdateTime = savedInstanceState.getString(KEY_LAST_UPDATED_TIME_STRING);
}
updateUI();
}
}
protected synchronized void buildGoogleApiClient() {
Log.i(TAG, "Building GoogleApiClient");
mGoogleApiClient = new GoogleApiClient.Builder(getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
protected void createLocationRequest() {
mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
}
protected void buildLocationSettingsRequest() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(mLocationRequest);
mLocationSettingsRequest = builder.build();
}
protected void checkLocationSettings() {
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(
mGoogleApiClient,
mLocationSettingsRequest
);
result.setResultCallback(this);
}
#Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Log.i(TAG, "All location settings are satisfied.");
startLocationUpdates();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to" +
"upgrade location settings ");
try {
// Show the dialog by calling startResolutionForResult(), and check the result
// in onActivityResult().
status.startResolutionForResult(getActivity(), REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog " +
"not created.");
break;
}
}
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case REQUEST_CHECK_SETTINGS:
switch (resultCode) {
case Activity.RESULT_OK:
Log.i(TAG, "User agreed to make required location settings changes.");
startLocationUpdates();
break;
case Activity.RESULT_CANCELED:
Log.i(TAG, "User chose not to make required location settings changes.");
break;
}
break;
}
}
public void startUpdatesButtonHandler(View view) {
checkLocationSettings();
}
public void stopUpdatesButtonHandler(View view) {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
stopLocationUpdates();
}
protected void startLocationUpdates() {
if (ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_FINE_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;
}
LocationServices.FusedLocationApi.requestLocationUpdates(
mGoogleApiClient,
mLocationRequest,
this
).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
mRequestingLocationUpdates = true;
}
});
}
private void updateUI() {
updateLocationUI();
}
private void updateLocationUI() {
if (mCurrentLocation != null) {
mLatitudeText.setText(String.valueOf(mCurrentLocation.getLatitude()));
mLongitudeText.setText(String.valueOf(mCurrentLocation.getLongitude()));
}
}
#Override
public void onStart() {
super.onStart();
mGoogleApiClient.connect();
}
#Override
public void onResume() {
super.onResume();
// Within {#code onPause()}, we pause location updates, but leave the
// connection to GoogleApiClient intact. Here, we resume receiving
// location updates if the user has requested them.
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
#Override
public void onPause() {
super.onPause();
// Stop location updates to save battery, but don't disconnect the GoogleApiClient object.
if (mGoogleApiClient.isConnected()) {
stopLocationUpdates();
}
}
protected void stopLocationUpdates() {
// It is a good practice to remove location requests when the activity is in a paused or
// stopped state. Doing so helps battery performance and is especially
// recommended in applications that request frequent location updates.
LocationServices.FusedLocationApi.removeLocationUpdates(
mGoogleApiClient,
this
).setResultCallback(new ResultCallback<Status>() {
#Override
public void onResult(Status status) {
mRequestingLocationUpdates = false;
}
});
}
#Override
public void onStop() {
super.onStop();
mGoogleApiClient.disconnect();
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onConnected(#Nullable Bundle bundle) {
Log.i(TAG, "Connected to GoogleApiClient");
// If the initial location was never previously requested, we use
// FusedLocationApi.getLastLocation() to get it. If it was previously requested, we store
// its value in the Bundle and check for it in onCreate(). We
// do not request it again unless the user specifically requests location updates by pressing
// the Start Updates button.
//
// Because we cache the value of the initial location in the Bundle, it means that if the
// user launches the activity,
// moves to a new location, and then changes the device orientation, the original location
// is displayed as the activity is re-created.
if (mCurrentLocation == null) {
if (ActivityCompat.checkSelfPermission(getContext(), android.Manifest.permission.ACCESS_FINE_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;
}
mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
}
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_ACCESS_LOCATION: {
// If request is cancelled, the result arrays are empty.
if (grantResults.length > 0
&& grantResults[0] == PackageManager.PERMISSION_GRANTED) {
updateLocationUI();
// permission was granted, yay! Do the
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
#Override
public void onConnectionSuspended(int i) {
Log.i(TAG, "Connection suspended");
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + connectionResult.getErrorCode());
}
#RequiresApi(api = Build.VERSION_CODES.N)
#Override
public void onLocationChanged(Location location) {
mCurrentLocation = location;
mLastUpdateTime = DateFormat.getTimeInstance().format(new Date());
updateLocationUI();
}
/**
* Stores activity data in the Bundle.
*/
public void onSaveInstanceState(Bundle savedInstanceState) {
savedInstanceState.putBoolean(KEY_REQUESTING_LOCATION_UPDATES, mRequestingLocationUpdates);
savedInstanceState.putParcelable(KEY_LOCATION, mCurrentLocation);
savedInstanceState.putString(KEY_LAST_UPDATED_TIME_STRING, mLastUpdateTime);
super.onSaveInstanceState(savedInstanceState);
}
}
These are permissions which I have added in manifest file
<uses-permission android:name = "android.permission.INTERNET" />
<uses-permission android:name = "android.permission.ACCESS_FINE_LOCATION" />
This is the xml code for latitude and longitude
<TextView
android:id="#+id/myLatitude"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="15sp"
android:textColor="#color/cordinates_color"
/>
<TextView
android:id="#+id/myLongitude"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:textSize="15sp"
android:textColor="#color/cordinates_color"
/>
I have added this line in build.gradle app level and sync the project compile 'com.google.android.gms:play-services:10.0.1'
I have been able to connect to GoogleApiClient but coordinates are not coming up. This is a glimpse of logcat
01-29 14:49:31.395 10560-10560/com.example.luke.xyz I/EditInformation: Building GoogleApiClient
01-29 14:49:31.675 10560-10560/com.example.luke.xyz D/ViewRootImpl: #1 mView = android.widget.LinearLayout{2782c80 V.E...... ......I. 0,0-0,0}
01-29 14:49:31.715 10560-10616/com.example.luke.xyz D/mali_winsys: new_window_surface returns 0x3000, [468x91]-format:1
01-29 14:49:31.755 10560-10560/com.example.luke.xyz I/EditInformation: Connected to GoogleApiClient
01-29 14:49:31.805 10560-10616/com.example.luke.xyz V/RenderScript: 0xdc179000 Launching thread(s), CPUs 8
I am testing it on Android Marshmallow. Still unable to figure it out.
Can you help me out ?
Thank you
Ask run time permissions like this:
// Here, thisActivity is the current activity
if (ContextCompat.checkSelfPermission(thisActivity,
Manifest.permission.ACCESS_COURSE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
// Should we show an explanation?
if (ActivityCompat.shouldShowRequestPermissionRationale(thisActivity,
Manifest.permission.ACCESS_COURSE_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.
} else {
// No explanation needed, we can request the permission.
ActivityCompat.requestPermissions(thisActivity,
new String[]{Manifest.permission.ACCESS_COURSE_LOCATION},
MY_PERMISSIONS_REQUEST_LOCATION);
// MY_PERMISSIONS_REQUEST_LOCATION is an
// app-defined int constant. The callback method gets the
// result of the request.
}
}
Then:
#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
// contacts-related task you need to do.
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
more details you can find it out here: https://developer.android.com/training/permissions/requesting.html
Use both the location Permission - ACCESS_COARSE_LOCATION , ACCESS_FINE_LOCATION, same time use Double for LatLng:
#Override
public void onConnected(#Nullable Bundle connectionHint) {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission
(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&&
ActivityCompat.checkSelfPermission
(getContext(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
{
requestPermissions(new String[]{
Manifest.permission.ACCESS_COARSE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION
}, 1);
return;
}
}
else{
Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
if(mLastLocation!=null){
mLatitudeText.setText(Double.parseDouble(mLastLocation.getLatitude()));
mLongitudeText.setText(Double.parseDouble(mLastLocation.getLongitude()));
}else {
Toast.makeText(getContext(),"LOcation is null",Toast.LENGTH_SHORT).show();
}
}
}
Handle requested Permission:
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
switch (requestCode) {
case 1:
if (grantResults[0] != PackageManager.PERMISSION_GRANTED){
Toast.makeText(getContext(),"PERMISSION_GRANTED",Toast.LENGTH_SHORT).show();
}
else {
Toast.makeText(getContext(),"PERMISSION_GRANTED",Toast.LENGTH_SHORT).show();
}
break;
}
}
Go to Settings > Apps > Your_app, and in the Permissions tab, enable Location for instantly getting the output on Marshmallow.
Your coding is fine you just need to add few more permission to your manifest file
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.LOCATION_HARDWARE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
Make sure your gps is enabled. Let me know if this fix your problem.
You are currently only asking for the last known location in onConnected. If there is no cached location, this will do nothing.
You should override onLocationChanged to receive the current location once your Google API client is connected. https://developer.android.com/training/location/receive-location-updates.html#callback
The GoogleApiClient.connect method is asynchronous. In the documentation I linked above, the request for location updates is made after the GoogleApiClient connects. You are making this request in onResume, but you are not guaranteed that the GoogleApiClient is connected until onConnected. Make the request in onConnected, as the example in the documentation shows.
Related
I am working on an android app that needs user location, every time user logins into the app.
I have written code to get user location and works fine, but the problem is if the user denies permission twice it didn't ask again, here is my code:
public class MainActivity extends AppCompatActivity {
String myLocation = "";
private LocationRequest locationRequest;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(5000);
locationRequest.setFastestInterval(2000);
getCurrentLocation();
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if (requestCode == 1) {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
if (isGPSEnabled()) {
getCurrentLocation();
} else {
turnOnGPS();
}
}
}
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 2) {
if (resultCode == Activity.RESULT_OK) {
getCurrentLocation();
}
}
}
private void getCurrentLocation() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) {
if (isGPSEnabled()) {
LocationServices.getFusedLocationProviderClient(MainActivity.this)
.requestLocationUpdates(locationRequest, new LocationCallback() {
#Override
public void onLocationResult(#NonNull LocationResult locationResult) {
super.onLocationResult(locationResult);
LocationServices.getFusedLocationProviderClient(MainActivity.this)
.removeLocationUpdates(this);
if (locationResult != null && locationResult.getLocations().size() > 0) {
int index = locationResult.getLocations().size() - 1;
double latitude = locationResult.getLocations().get(index).getLatitude();
double longitude = locationResult.getLocations().get(index).getLongitude();
myLocation = "Latitude: " + latitude + " Longitude: " + longitude;
Toast.makeText(getApplicationContext(), myLocation, Toast.LENGTH_LONG).show();
}
}
}, Looper.getMainLooper());
} else {
turnOnGPS();
}
} else {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, 1);
}
}
}
private void turnOnGPS() {
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
Task<LocationSettingsResponse> result = LocationServices.getSettingsClient(getApplicationContext())
.checkLocationSettings(builder.build());
result.addOnCompleteListener(new OnCompleteListener<LocationSettingsResponse>() {
#Override
public void onComplete(#NonNull Task<LocationSettingsResponse> task) {
try {
LocationSettingsResponse response = task.getResult(ApiException.class);
Toast.makeText(MainActivity.this, "GPS is already tured on", Toast.LENGTH_SHORT).show();
} catch (ApiException e) {
switch (e.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
ResolvableApiException resolvableApiException = (ResolvableApiException) e;
resolvableApiException.startResolutionForResult(MainActivity.this, 2);
} catch (IntentSender.SendIntentException ex) {
ex.printStackTrace();
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
//Device does not have location
break;
}
}
}
});
}
private boolean isGPSEnabled() {
LocationManager locationManager = null;
boolean isEnabled = false;
if (locationManager == null) {
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
}
isEnabled = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
return isEnabled;
}
}
As, the user's location is mandatory for the working of app. Now, I want the app to:
1- ask for permission on activity start, if the permission is not granted or denied previously.
2- if permission is granted then proceed further else close the activity.
So, how can I achieve this.
Thanks
You can check whether the user has given permission or not using checkSelfPermission and if not then you ask for permission again else process with program flow.
if (ContextCompat.checkSelfPermission(this,Manifest.permission.READ_EXTERNAL_STORAGE)
== PackageManager.PERMISSION_GRANTED){
doStuff()
} else {
requestStoragePermission()
}
but the problem is if the user denies permission twice it didn't ask
again,
Yes, you cannot ask again once the user denies the permission with "Don't ask again" checked. This checkbox is normally checked by default on the second permission request. Beware that on api 11, there is no checkbox and the denial is automatic auto-denial auto-reset.
The way is that, you don't assume something about it, just put logic for handling it. If denied, you can only inform the user about the required permission. The official doc says: ref
If the ContextCompat.checkSelfPermission() method returns
PERMISSION_DENIED, call shouldShowRequestPermissionRationale(). If
this method returns true, show an educational UI to the user. In this
UI, describe why the feature, which the user wants to enable, needs a
particular permission.
info
I'm using the following code to check for and request permission for GPS:
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION }, 1);
}
I have the following in the manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
I'm deploying the app to an Android 5.0.2 tablet using Android Studio.
I know the checkSelfPermission doesn't return PERMISSION_GRANTED and it executes the requestPermissions, but it doesn't show a dialog or grant the permission. How do I grant the app permission to use GPS?
ActivityCompat.requestPermissions(this, new String[]{
Manifest.permission.ACCESS_FINE_LOCATION }, 1);
This code requests runtime permissions on android 6.For lower versions i launch the settings intent for the user to turn on the preferred setting as below(in place of the above code)
Intent myIntent = new Intent(Settings.ACTION_SETTINGS);
startActivity(myIntent);
Add these lines in manifest:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
and these too:
<!-- Below permissions are used to detect required hardware or service providers for the application -->
<uses-feature
android:name="android.hardware.location"
android:required="true" />
<uses-feature
android:name="android.hardware.location.gps"
android:required="true" />
You can use the below code. With the below code it will ask to turn the GPS on .
public class Activity extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener, LocationListener {
private final static int PLAY_SERVICES_RESOLUTION_REQUEST = 1000;
private Location mLastLocation;
// Google client to interact with Google API
private GoogleApiClient mGoogleApiClient;
// boolean flag to toggle periodic location updates
private boolean mRequestingLocationUpdates = false;
private LocationRequest mLocationRequest;
// Location updates intervals in sec
private static int UPDATE_INTERVAL = 600000; // 10 min
private static int FATEST_INTERVAL = 600000; // 10 min
private static int DISPLACEMENT = 5; // 5 meters
PendingResult<LocationSettingsResult> result;
AlertDialog.Builder alertDialogBuilder;
LinearLayout parent;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
alertDialogBuilder = new AlertDialog.Builder(Activity.this);
parent = new LinearLayout(ActivitySetting.this);
parent.setGravity(Gravity.CENTER);
parent.setLayoutParams(new ViewGroup.LayoutParams(ViewGroup.LayoutParams.MATCH_PARENT,
ViewGroup.LayoutParams.MATCH_PARENT));
alertDialogBuilder.setTitle("name");
// First we need to check availability of play services
if (checkPlayServices()) {
// Building the GoogleApi client
buildGoogleApiClient();
createLocationRequest();
}
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY));
result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates locationSettingsStates = result.getLocationSettingsStates();
// final LocationSettingsStates locationSettingsStates = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
alertDialogBuilder.setMessage("Turn On GPS");
alertDialogBuilder.setView(parent);
alertDialogBuilder.setCancelable(false);
alertDialogBuilder.setPositiveButton("Ok", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(ActivitySetting.this, 1000);
} catch (IntentSender.SendIntentException e) {
// check error.
}
}
});
alertDialogBuilder.setNegativeButton("Cancel", new DialogInterface.OnClickListener() {
public void onClick(DialogInterface dialog, int id) {
try {
// Show the dialog by calling startResolutionForResult(),
finish();
} catch (Exception e) {
// check error.
}
}
});
alertDialogBuilder.create();
alertDialogBuilder.show();
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// you can do here what ever you want.
break;
}
}
});
}
#Override
protected void onStart() {
super.onStart();
if (mGoogleApiClient != null) {
mGoogleApiClient.connect();
}
}
#Override
protected void onResume() {
super.onResume();
checkPlayServices();
// Resuming the periodic location updates
if (mGoogleApiClient.isConnected() && mRequestingLocationUpdates) {
startLocationUpdates();
}
}
/**
* Creating google api client object
*/
protected synchronized void buildGoogleApiClient() {
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode) {
case 1000:
switch (resultCode) {
case Activity.RESULT_OK:
// If user has active gps you will get it here
break;
case Activity.RESULT_CANCELED:
// The user was asked to change settings, but chose not to turn on
break;
default:
break;
}
break;
}
}
/**
* Method to verify google play services on the device
*/
private boolean checkPlayServices() {
int resultCode = GooglePlayServicesUtil
.isGooglePlayServicesAvailable(this);
if (resultCode != ConnectionResult.SUCCESS) {
if (GooglePlayServicesUtil.isUserRecoverableError(resultCode)) {
GooglePlayServicesUtil.getErrorDialog(resultCode, this,
PLAY_SERVICES_RESOLUTION_REQUEST).show();
} else {
Toast.makeText(getApplicationContext(),
"This device is not supported.", Toast.LENGTH_LONG)
.show();
finish();
}
return false;
}
return true;
}
/**
* Google api callback methods
*/
#Override
public void onConnectionFailed(ConnectionResult result) {
Log.i("fsAil", "Connection failed: ConnectionResult.getErrorCode() = "
+ result.getErrorCode());
}
#Override
public void onConnected(Bundle arg0) {
}
#Override
public void onConnectionSuspended(int arg0) {
mGoogleApiClient.connect();
}
#Override
public void onLocationChanged(Location location) {
}
}
Here API <= 21 gps permission will be granted automatically(if you have defined permission on manifest) and for marshmallow and above you need to ask for runtime permission(also add permission in manifest) but to turn on GPS after permission granted you can use the above code.
With this code one alertbox comes up and ask to turn on the GPS(if not active). So you can directly turn on GPS with the above code.
Hope this help you.
Cheers!!
I want to fetch user's current lat long on click of a button. I know that you can get the last known location using FusedLocationApi. But what I am not able to understand is, gps or location services needs to be turned on for this? If yes, how to check that the user has turned on location and get the current location. Also, how to include marshmallow permission checks in getting the location.
I have already referred:
1) googlesamples/android-play-location
2) googlesamples/android-XYZTouristAttractions
and many other links but unable to make a complete flow.
Code
public class AccessLocationFragment extends BaseFragment implements View.OnClickListener, LocationListener,
GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, GeneralDialogFragment.GeneralDialogClickListener {
private static final int MY_PERMISSIONS_REQUEST_LOCATION = 101;
private static final String TAG = AccessLocationFragment.class.getSimpleName();
private static final int REQUEST_CHECK_SETTINGS = 102;
private Button mAccessLocation;
private EditText mZipCode;
private Dialog progressDialog;
private GoogleApiClient mGoogleApiClient;
private Location mLastLocation;
public static AccessLocationFragment newInstance() {
return new AccessLocationFragment();
}
#Nullable
#Override
public View onCreateView(LayoutInflater inflater, #Nullable ViewGroup container, #Nullable Bundle savedInstanceState) {
return inflater.inflate(R.layout.fragment_access_location, container, false);
}
#Override
public void onViewCreated(View view, #Nullable Bundle savedInstanceState) {
super.onViewCreated(view, savedInstanceState);
RecycleApplication.getEventBus().register(this);
mAccessLocation = (Button) view.findViewById(R.id.access_location);
mZipCode = (EditText) view.findViewById(R.id.zip_code);
mAccessLocation.setOnClickListener(this);
mZipCode.setOnEditorActionListener(new TextView.OnEditorActionListener() {
#Override
public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
if (actionId == EditorInfo.IME_ACTION_DONE) {
String zipCode = mZipCode.getText().toString().trim();
if (TextUtils.isEmpty(zipCode)) {
Toast.makeText(mActivity, "Please enter zip code", Toast.LENGTH_SHORT).show();
} else {
Call<Address> response = mRecycleService.getAddress(zipCode);
response.enqueue(new GetLocationCallback(AccessLocationFragment.this));
}
}
return false;
}
});
// Create an instance of GoogleAPIClient.
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(mActivity)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
if (!LocationUtils.checkFineLocationPermission(mActivity)) {
// See if user has denied permission in the past
if (shouldShowRequestPermissionRationale(android.Manifest.permission.ACCESS_FINE_LOCATION)) {
// Show a simple snackbar explaining the request instead
showPermissionSnackbar();
} else {
requestFineLocationPermission();
}
} else {
displayLocationSettingsRequest();
}
}
private void startHomeActivity(Address address) {
RecyclePreferences.getInstance().setCity(address.getCity());
RecyclePreferences.getInstance().setState(address.getState());
RecyclePreferences.getInstance().setLatitude(address.getLatitude());
RecyclePreferences.getInstance().setLongitude(address.getLongitude());
RecyclePreferences.getInstance().setZipCode(address.getZipCode());
startActivity(new Intent(mActivity, HomeActivity.class));
mActivity.finish();
}
#Override
public void onSuccess(Call<Address> call, Response<Address> response) {
mActivity.hideProgressDialog(progressDialog);
if (response.isSuccessful()) {
Address address = response.body();
startHomeActivity(address);
}
}
#Override
public void onFailure(Call<Address> call, Throwable t) {
mActivity.hideProgressDialog(progressDialog);
}
#Override
public void onClick(View view) {
if (view.getId() == R.id.access_location) {
fetchAddress(mLastLocation);
}
}
#Override
public void onRequestPermissionsResult(int requestCode, String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSIONS_REQUEST_LOCATION: {
if (grantResults[0] == PackageManager.PERMISSION_GRANTED) {
displayLocationSettingsRequest();
}
}
}
}
private void fetchAddress(Location location) {
mRecycleService = new RecycleRetrofitBuilder(mActivity).getService();
Call<Address> response = mRecycleService.getAddress(String.valueOf(location.getLatitude()), String.valueOf(location.getLongitude()));
progressDialog = mActivity.showProgressDialog(mActivity);
response.enqueue(new GetLocationCallback(AccessLocationFragment.this));
}
private void requestFineLocationPermission() {
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, MY_PERMISSIONS_REQUEST_LOCATION);
}
private void showPermissionSnackbar() {
GeneralDialogFragment generalDialogFragment = GeneralDialogFragment.
newInstance("Permissions", "Allow Recycle the World to use your location.", "Allow", "Go Back", this);
mActivity.showDialogFragment(generalDialogFragment);
displayLocationSettingsRequest();
}
private void displayLocationSettingsRequest() {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(10000 / 2);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
getLocation();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i(TAG, "Location settings are not satisfied. Show the user a dialog to upgrade location settings ");
try {
status.startResolutionForResult(mActivity, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.i(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog not created.");
break;
}
}
});
}
private void getLocation() {
if (ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&& ActivityCompat.checkSelfPermission(mActivity, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CHECK_SETTINGS) {
getLocation();
}
}
#Override
public void onStart() {
mGoogleApiClient.connect();
super.onStart();
}
#Override
public void onStop() {
mGoogleApiClient.disconnect();
super.onStop();
}
#Override
public void onConnected(#Nullable Bundle bundle) {
getLocation();
}
#Override
public void onDestroy() {
super.onDestroy();
RecycleApplication.getEventBus().unregister(this);
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(#NonNull ConnectionResult connectionResult) {
}
#Override
public void onOk(DialogFragment dialogFragment) {
dialogFragment.dismiss();
requestFineLocationPermission();
}
#Override
public void onCancel(DialogFragment dialogFragment) {
dialogFragment.dismiss();
}
}
Sorry, I haven't go through your code, I am just writing the functions that you have asked for in your question.
First, you need to build a connection to google api client like:
private synchronized void buildGoogleApiClient(){
mGoogleApiClient = new GoogleApiClient.Builder(GTApplication.getContext())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
mGoogleApiClient.connect();
}
After this in my experience, you almost always get called onConnected() function where you can ask for the location permission after API level 23:
public void checkLocationPermission(){
if(ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
// You don't have the permission you need to request it
ActivityCompat.requestPermissions(this, Manifest.permission.ACCESS_FINE_LOCATION), REQ_CODE);
}else{
// You have the permission.
requestLocationAccess();
}
}
If you requested the permission your onRequestPermissionsResult() function will be called with the REQ_CODE. If you need more info to implement the events check the original documentation for runtime permissions it is very useful.
When you have the permission you can check if the location is enabled like:
public void requestLocationAccess(){
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval((long) (LocationHelper.UPDATE_INTERVAL_IN_MILLISECONDS*1.1));
mLocationRequest.setFastestInterval(LocationHelper.UPDATE_INTERVAL_IN_MILLISECONDS);
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
final LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true); //this is the key ingredient
com.google.android.gms.common.api.PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>(){
#Override
public void onResult(#NonNull LocationSettingsResult result){
if(requester != null){
final Status resultStatus = result.getStatus();
switch(resultStatus.getStatusCode()){
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. You can ask for the user's location HERE
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user a dialog.
try{
resultStatus.startResolutionForResult(this, REQUEST_LOCATION);
break;
}catch(IntentSender.SendIntentException ignored){}
}
}
}
}
});
}
If the enable location dialog needed to be shown to the user you will get a callback in onActivityResult() function with the request code REQUEST_LOCATION)
That's it after you done with all this process you can call locationManager.getLastKnownLocation() or start location request or whatever you want.
PS.: I have cut this code from my bigger class, so please if you find any mistakes feel free to ask. I have specified only the case when everything goes well, because it contains the essence, you can handle the exceptions yourself I hope.
try this code:
public void showMap() {
mapFragment = (SupportMapFragment)getChildFragmentManager().findFragmentById(R.id.map);
if (map == null) {
map = mapFragment.getMap();
}
// Enable Zoom
map.getUiSettings().setZoomGesturesEnabled(true);
//set Map TYPE
map.setMapType(GoogleMap.MAP_TYPE_NORMAL);
//enable Current location Button
map.setMyLocationEnabled(true);
LocationManager locationManager = (LocationManager)getActivity().getSystemService(getActivity().LOCATION_SERVICE);
Criteria criteria = new Criteria();
String bestProvider = locationManager.getBestProvider(criteria, true);
if (ActivityCompat.checkSelfPermission(getContext(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(getActivity(), 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(bestProvider);
if (location != null) {
onLocationChanged(location);
}
locationManager.requestLocationUpdates(bestProvider, 2000, 0, this);
}
#Override
public void onLocationChanged(Location location) {
latitude= location.getLatitude();
longitude=location.getLongitude();
LatLng loc = new LatLng(latitude, longitude);
if (marker!=null){
marker.remove();
}
marker= map.addMarker(new MarkerOptions().position(loc).title("Sparx IT Solutions"));
map.moveCamera(CameraUpdateFactory.newLatLng(loc));
map.animateCamera(CameraUpdateFactory.newLatLngZoom(loc, 16.0f));
}
#Override
public void onProviderDisabled(String provider) {
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
Toast.makeText(getActivity().getBaseContext(), "Gps is turned off!!",
Toast.LENGTH_SHORT).show();
}
#Override
public void onProviderEnabled(String provider) {
Toast.makeText(getActivity().getBaseContext(), "Gps is turned on!! ",
Toast.LENGTH_SHORT).show();
}
I have an app which gets the users current location and then loads a Google Map and plots markers of interest in their area. It works flawlessly on everything below Marshmallow. I've added the run-time permissions check, and they are being set as I do get the prompt, and after I hit accept I see the Permission listed in the app details from the settings of the phone. However, I can not for the life of me figure out why I'm getting no location back.
I am using the example as seen here https://developer.android.com/training/location/retrieve-current.html
I have all the permissions set with the tag in the manifest. I even have my Fragment implementing the LocationListener. However, the onLocationChanged method never gets called. I am calling it within the onConnected method of the Google API Client like below..
#Override
public void onConnected(#Nullable Bundle bundle) {
try {
Log.d("MYAPPTAG","isConnected: " + mGoogleApiClient.isConnected());
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
myLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
} catch (SecurityException ex) {
myLocation = null;
}
}
the onConnected method DOES get called because I get my Log to the console. myLocation is always null though. I get a message in the console everytime I call getLastLocation that says
No Location to return for getLastLocation()
GoogleSignatureVerifier: com.myappname.android signature not valid. Found: LONG KEY HERE
Is there something special I need to do in Marshmallow?
my OnLocationChanged method
#Override
public void onLocationChanged(Location location) {
myLocation = location;
Log.d("MYAPPTAG", "LocatinChngListner, loc: " + location.getLatitude() + "," + location.getLongitude());
}
AndroidManifest.xml - permissions section (above node)
<!--- App permissions -->
<permission android:name="com.myappname.android.permission.MAPS_RECEIVE" android:protectionLevel="signature"/>
<uses-permission android:name="com.myappname.android.permission.MAPS_RECEIVE"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES"/>
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.GET_ACCOUNTS"/>
<uses-permission android:name="android.permission.CALL_PHONE"/>
<uses-permission android:name="android.permission.KILL_BACKGROUND_PROCESSES" />
<uses-permission android:name="android.permission.WRITE_CONTACTS" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="com.google.android.c2dm.permission.RECEIVE" />
<permission android:name="com.myappname.android.permission.C2D_MESSAGE" android:protectionLevel="signature" />
<uses-permission android:name="com.myappname.android.permission.C2D_MESSAGE"/>
onCreate Method snippet
createLocationRequest();
if (mGoogleApiClient == null) {
mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API)
.build();
}
createLocationRequest method
private void createLocationRequest(){
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(5000);
mLocationRequest.setFastestInterval(1000);
}
onStart() onStop() methods
#Override
public void onStart() {
if (!mGoogleApiClient.isConnected()) mGoogleApiClient.connect();
super.onStart();
}
#Override
public void onStop() {
if (mGoogleApiClient.isConnected()) mGoogleApiClient.disconnect();
super.onStop();
}
I call this code below right after the Fragment onCreate method
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.LOLLIPOP_MR1 && (ContextCompat.checkSelfPermission(getActivity(), android.Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED || ContextCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)) {
requestPermissions(new String[] { Manifest.permission.ACCESS_FINE_LOCATION, Manifest.permission.ACCESS_COARSE_LOCATION }, REQUEST_PERMISSION_USER_LOCATION);
} else {
googleMapsLocationPermissionContainer.setVisibility(View.GONE);
getUserLocationAndInitializeMap();
}
googleMapsLocationPermissionContainer is just a layout I overlay on the map until the permissions are granted.
getUserLocationAndInitializeMap()
try {
MapsInitializer.initialize(getActivity());
// Set reference for map object
if (map == null) {
mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map);
mapFragment.getMapAsync(this);
// Here I set the map to invisible then after I plot all the markers I set it to visible again
mapFragment.getView().setVisibility(View.INVISIBLE);
}
} catch (Exception e) {
// Show the google maps alert dialog
showGoogleMapsErrorDialog();
}
My approach for this is the following:
#Override
public void onResume() {
super.onResume();
initGpsTracker();
}
public synchronized void initGpsTracker() {
if (mMap != null) {
try {
checkIfPermissionAllowedForLocation();
} catch (SecurityException secex) {
Toast.makeText(getActivity(), "not enabled in manifest", Toast.LENGTH_SHORT).show();
}
}
}
/**
* rule is the following. First we check if the permissions are there. If not, we check if we can enable or not.
* If the permissions are check if gps is enabled.
*/
private void checkIfPermissionAllowedForLocation() {
//if permissions are set then we go to else, check for gps
if (ActivityCompat.checkSelfPermission(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// Request missing location permission.
if (ActivityCompat.shouldShowRequestPermissionRationale(getActivity(), Manifest.permission.ACCESS_FINE_LOCATION)) {
askIfToRequestPermissions();
} else {
requestPermissions();
}
} else {
// Location permission has been granted, continue as usual.
if (!isGpsProviderEnabled()) {
askToEnableGPS();
} else {
mMap.setMyLocationEnabled(true);
}
}
}
private void askToEnableGPS() {
CustomFragmentDialog customFragmentDialog = CustomFragmentDialog.newInstance(getString(R.string.enable_gps_title),
getString(R.string.enable_gps_message),
getString(R.string.ok),
getString(R.string.cancel),
callback);
customFragmentDialog.show(getFragmentManager(), CUSTOM_TAG);
}
private void requestPermissions() {
ActivityCompat.requestPermissions(getActivity(),
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
REQUEST_CODE_LOCATION);
}
private void enableGPS() {
if (enableLocationService != null) {
enableLocationService.askToEnableGps(locationCallback);
}
}
private GoogleAskToEnableLocationService.GpsCallback locationCallback = new GoogleAskToEnableLocationService.GpsCallback() {
#Override
public void onSuccess() {
initGpsTracker();
}
#Override
public void onResolutionRequired(Status status) {
try {
status.startResolutionForResult(getActivity(), CONNECTION_RESOLUTION_CODE);
} catch (IntentSender.SendIntentException setex) {
Toast.makeText(getActivity(), "Exception in sending intent:", Toast.LENGTH_SHORT).show();
}
}
#Override
public void onError() {
Toast.makeText(getActivity(), "Location services unavailable!", Toast.LENGTH_SHORT).show();
}
};
private void askIfToRequestPermissions() {
CustomFragmentDialog customFragmentDialog = CustomFragmentDialog.newInstance(getString(R.string.enable_gps_title),
getString(R.string.enable_permissions_message),
getString(R.string.ok),
getString(R.string.cancel),
callback_permissions);
customFragmentDialog.show(getFragmentManager(), CUSTOM_TAG);
}
private CustomFragmentDialog.Callback callback = new CustomFragmentDialog.Callback() {
#Override
public void onPositiveButtonClicked(Bundle bundle) {
enableGPS();
}
#Override
public void onNegativeButtonClicked(Bundle bundle) {
}
};
private CustomFragmentDialog.Callback callback_permissions = new CustomFragmentDialog.Callback() {
#Override
public void onPositiveButtonClicked(Bundle bundle) {
requestPermissions();
}
#Override
public void onNegativeButtonClicked(Bundle bundle) {
}
};
private boolean isGpsProviderEnabled() {
return googleUtils.isGpsProviderEnabled();
}
//inside it is a normal check if locationManager can access
//the gps provider
if (locationManager.getProvider(provider) == null) {
return false;
}
Now, for request permission there are some callbacks:
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
case CONNECTION_RESOLUTION_CODE:
switch (resultCode) {
case Activity.RESULT_OK:
initGpsTracker();
break;
case Activity.RESULT_CANCELED:
Toast.makeText(getContext(), "Gps not enabled:", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
break;
}
}
#Override
public void onRequestPermissionsResult(int requestCode, #NonNull String[] permissions, #NonNull int[] grantResults) {
if (requestCode == REQUEST_CODE_LOCATION) {
if (grantResults.length == 1 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
initGpsTracker();
} else {
Toast.makeText(getActivity(), "Manifest permission, not enabled", Toast.LENGTH_SHORT).show();
}
}
}
Now, finally the class where you deal with the request for the location so you do not have to go to settings:
public void askToEnableGps(final GpsCallback callback) {
if (locationClient == null) {
return;
}
mLocationRequestHighAccuracy = LocationRequest.create();
mLocationRequestHighAccuracy.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequestHighAccuracy.setInterval(30 * 1000);
mLocationRequestHighAccuracy.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequestHighAccuracy);
builder.setAlwaysShow(true);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(locationClient, builder.build());
result.setResultCallback(getResultCallback(callback));
}
private ResultCallback<LocationSettingsResult> getResultCallback(final GpsCallback callback) {
return new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
if (result != null) {
final Status status = result.getStatus();
if (callback != null) {
//final LocationSettingsStates statesResult = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
callback.onSuccess();
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
callback.onResolutionRequired(status);
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.
callback.onError();
break;
}
}
}
}
};
}
public interface GpsCallback {
/**
* callback method for when the result it is a success.
*/
void onSuccess();
/**
* callback for when user interaction it is required.
*
* #param status the result from the service needed for the resolution.
*/
void onResolutionRequired(Status status);
/**
* Callback for when the change it is not possible.
*/
void onError();
}
I am working on project where i need to access user's gps location. Due to android 6, I need run time permissions. I tried to do it , first time it asked for gps location on activity starts, but without giving me location. I am still not getting any location coordinates. Hope someone can help ?
public class benzinpriser_akt extends AppCompatActivity implements OnItemClickListener {
public static final int MY_PERMISSION_REQUEST_GPS_LOCATION = 1 ;
LocationManager locationManager;
LocationListener locationListener;
Location currentLocation;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
locationManager = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
locationListener = new LocationListener() {
public void onLocationChanged(Location location) {
// Called when a new location is found by the network location provider.
currentLocation = location;
System.out.println("Current Location "+ currentLocation );
}
public void onStatusChanged(String provider, int status, Bundle extras) {
}
public void onProviderEnabled(String provider) {
}
public void onProviderDisabled(String provider) {
}
};
if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION)) {
} else {
ActivityCompat.requestPermissions(this,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
MY_PERMISSION_REQUEST_GPS_LOCATION);
}
}
// Some other code regarding listview and fetching data from database
}
#Override
public void onRequestPermissionsResult(int requestCode,
String permissions[], int[] grantResults) {
switch (requestCode) {
case MY_PERMISSION_REQUEST_GPS_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
// contacts-related task you need to do.
System.out.println("Permission Granted");
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
} else {
// permission denied, boo! Disable the
// functionality that depends on this permission.
}
return;
}
// other 'case' lines to check for other
// permissions this app might request
}
}
First of all add theese two lines to your build.gradle:
compile 'com.google.android.gms:play-services-maps:8.4.0'
compile 'com.google.android.gms:play-services-location:8.4.0'
Then in your activity you must implement like that :
public class benzinpriser_akt extends AppCompatActivity implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener,LocationListener, android.location.LocationListener {
private GoogleApiClient mGoogleApiClient;
private LocationRequest mLocationRequest;
private int UPDATE_INTERVAL = 20000; // 20 sec
private int FASTEST_INTERVAL = 10000; // 10 sec
private int DISPLACEMENT = 50; // get location per 50 meter change
protected final String TAG = "Location Service";
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(yourlayout);
//build google api client
buildGoogleApiClient();
} //oncreate end
protected synchronized void buildGoogleApiClient() {
Log.v(TAG, "google client building");
if (GooglePlayServicesUtil.isGooglePlayServicesAvailable(this) == ConnectionResult.SUCCESS) {
mGoogleApiClient = new GoogleApiClient.Builder(thisService)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.addApi(LocationServices.API).build();
if (!mGoogleApiClient.isConnected() || !mGoogleApiClient.isConnecting()) {
mGoogleApiClient.connect();
}
startListenLocation();
} else {
Log.e(TAG, "unable to connect to google play services.");
}
}
public void createLocationRequestWithDialog(final Activity activity){
mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
mLocationRequest.setInterval(UPDATE_INTERVAL);
mLocationRequest.setFastestInterval(FASTEST_INTERVAL);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
//**************************
builder.setAlwaysShow(true); //this is the key ingredient
//**************************
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
final LocationSettingsStates state = result.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the user
// a dialog.
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(
activity, 1000);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
}
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.
break;
}
}
});
}
public void checkGpsPermission(Activity activity) {
if (ContextCompat.checkSelfPermission(activity, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
ActivityCompat.requestPermissions(activity,
new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSION_ACCESS_GPS);
}
else
{
createLocationRequestWithDialog(activity);
}
}
protected void startListenLocation() {
if (ActivityCompat.checkSelfPermission(thisService, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {
//no permission , create a notification and want permission
NotificationManager notificationManager = (NotificationManager)
getSystemService(NOTIFICATION_SERVICE);
Notification n = new Notification.Builder(thisService)
.setContentTitle(" notification")
.setContentText("there is no permission about using gps services, please give location permissions")
.setSmallIcon(R.drawable.logo)
.setAutoCancel(true)
.build();
notificationManager.notify((int)System.currentTimeMillis(), n);
} else {
// permission has been granted, continue as usual
if(mGoogleApiClient.isConnected()) {
LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this);
}
}
}
#Override
public void onConnected(#Nullable Bundle bundle) {
if (mGoogleApiClient.isConnected() && mLastLocation != null) {
createLocationRequestWithDialog();
startListenLocation();
}
}
#Override
public void onConnectionSuspended(int i) {
mGoogleApiClient.connect();
}
//TODO add other override methods , onresume, onproviderenabled etc...
}//class end
Battery drain :
/*
Priority update interval Battery drain per hour (%) Accuracy
HIGH_ACCURACY 5 seconds 7.25% ~10 meters
BALANCED_POWER 20 seconds 0.6% ~40 meters
NO_POWER N/A small ~1 mile
*/