The addProximityAlert call stopped triggering alerts on Android 11 devices.
I call the addProximityAlert for the special locations (calculated for the user location) from the Application.onCreate method or whenever the ACCESS_FINE_LOCATION permission is granted using the following code:
mLocationManager = (LocationManager) mApplicationContext.getSystemService(Context.LOCATION_SERVICE);
if (mLocationManager != null) {
final Criteria criteria = new Criteria();
//criteria.setAccuracy(Criteria.ACCURACY_COARSE);
criteria.setAccuracy(Criteria.ACCURACY_FINE);
String provider = mLocationManager.getBestProvider(criteria, true);
if (!TextUtils.isEmpty(provider)) {
mLocationUpdatelistener = new LocationListener() {
#Override
public void onLocationChanged(Location location) {
subscribeForProximityAlert(location);
}
#Override
public void onStatusChanged(String provider, int status, Bundle extras) {
}
#Override
public void onProviderEnabled(String provider) {
}
#Override
public void onProviderDisabled(String provider) {
}
};
final Location lastKnownLocation = mLocationManager.getLastKnownLocation(provider);
if (lastKnownLocation == null) {
try {
mLocationManager.requestSingleUpdate(criteria, mLocationUpdatelistener, Looper.getMainLooper());
} catch (Throwable e) {
e.printStackTrace();
}
} else {
subscribeForProximityAlert(lastKnownLocation);
}
}
}
The subscribeForProximityAlert function is as follows (it is called actually after the successful single location update - I've checked that):
void subscribeForProximityAlert(Location location) {
String id;
double lat;
double lng;
long radius;
// ... compute the params above using the location
final Intent intent = new Intent(ACTION_FILTER);
intent.putExtra("_id", id);
intent.putExtra("_lat", lat);
intent.putExtra("_lng", lng);
intent.putExtra("_rad", radius);
final PendingIntent pendingIntent = PendingIntent.getBroadcast(mApplicationContext, i, intent, 0);
mPendingIntents.add(pendingIntent);
mLocationManager.addProximityAlert(
lat,
lng,
(float) radius,
24 * 60 * 60 * 1000,
pendingIntent
);
}
The ACTION_FILTER is the com.example.appname.ProximityAlert exactly the value I use in manifest to subscribe for the Proximity Alert broadcasts (com.example.appname is the package name of the app):
<application>
<receiver android:name="com.example.appname.ProximityAlertBroadcastReceiver">
<intent-filter>
<action android:name="com.example.appname.ProximityAlert" />
</intent-filter>
</receiver>
</application>
The ProximityAlertBroadcastReceiver can be as simple as:
public class ProximityAlertBroadcastReceiver extends BroadcastReceiver {
public ProximityAlertBroadcastReceiver() {
}
#Override
public void onReceive(Context context, Intent intent) {
}
}
its onReceive method is never called on Android 11 devices (checked with Lod.d and Toast.makeText...show() calls). Not when the app is running, not when it's in background. Not when I'm already in the radius of specified point, not when I'm entering/exiting.
Tried to add the android.permission.ACCESS_BACKGROUND_LOCATION permission to the manifest (nothing about it in the LocationManager.addProximityAlerts docs anyway) and grant the permission in system settings for the app, but it didn't help.
Also tried to reduce the targetSdkVersion from 30 to 28, but it didn't help.
The problem happened because of the implicit intent for the broadcast receiver, which is prohibited for the app targeting Android 8+ (SDK version 26):
https://developer.android.com/about/versions/oreo/background#broadcasts
After changing the
final Intent intent = new Intent(ACTION_FILTER);
to
final Intent intent = new Intent(mApplicationContext, ProximityAlertBroadcastReceiver.class);
I started to receive the broadcasts.
UPDATE: There's a bug in recent Android versions (11, 12, maybe others) which makes Geofences unresponsive on some devices and completely non-working on other devices if no app is actively requesting location at the moment:
https://issuetracker.google.com/issues/218335535
addProximityAlert creates a geofence under the hood, so it's affected too.
I am working with the google features to enable and disable location for the user, my main goal is, i enter the camera activity and it asks the user if he clicks cancel it goes back to the previous activity if everything fine it let the user take the photo.
This is my code:
`public class GoogleLocation extends Activity {
private static final int REQUEST_CHECK_SETTINGS = 5 ;
public static void displayLocationSettingsRequest(final Context context) {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).build();
googleApiClient.connect();
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(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Log.i("location", "All location settings are satisfied.");
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.i("location", "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().
Log.d("HELLO2","HELLO2");
status.startResolutionForResult((Activity) context, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.i("location", "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.i("location", "Location settings are inadequate, and cannot be fixed here. Dialog not created.");
break;
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
Log.d("requestCode",String.valueOf(requestCode));
Log.d("resultCode",String.valueOf(resultCode));
if (requestCode == REQUEST_CHECK_SETTINGS) {
Log.d("ENTERED","ENTERED");
if(resultCode == RESULT_OK){
}
if(resultCode == RESULT_CANCELED){
Log.d("ENTERED","ENTERED");
this.finish();
}
}
}
}
`
i thaught that i can controll the dialog options 'ok' and 'cancel' with the onactivityresult, but as you guys can see inside the onactivity result i have 2 Log.d this just get fired when i pres the 'x' from the camera to close the camera, what is going on? i need to control the dialog but it is not working :/.
Any tip?
Thanks
use this function to enable location in high accuracy
public static void checkLocationSettings(final Activity context){
if(!LocationUtil.isLocationServicesAvailable(context)){
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
.addApi(LocationServices.API).build();
googleApiClient.connect();
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(googleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
Log.e(TAG, "All location settings are satisfied.");
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
Log.e(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(context, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.e(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Log.e(TAG, "Location settings are inadequate, and cannot be fixed here. Dialog not created.");
break;
}
}
});
}
use this function to check location is enabled with high accuracy
public static boolean isLocationServicesAvailable(Context context) {
int locationMode = 0;
boolean isAvailable = false;
if (Build.VERSION.SDK_INT > Build.VERSION_CODES.KITKAT){
try {
locationMode = Settings.Secure.getInt(context.getContentResolver(), Settings.Secure.LOCATION_MODE);
} catch (Settings.SettingNotFoundException e) {
e.printStackTrace();
}
isAvailable = (locationMode != Settings.Secure.LOCATION_MODE_OFF && locationMode == Settings.Secure.LOCATION_MODE_HIGH_ACCURACY);
}
return isAvailable;
}
if the user hit ok then the location will enable with high accuracy. else it will stay in the current state. if the location is already enabled and not in high accuracy, then it also the prompt will come to change location mode to high accuracy.
I know that the question about turning on/off GPS programatically on android has been discussed many times, and the answer is always the same:
"You can't for security/privacy reasons, you have to forward to location preferences screen and let the user enable/disable it."
I understand that, however I recently bought Tasker from the market and, among many other things that you can accomplish with it, you can set rules to auto-enable GPS on entering pre-determined applications and disable it on exit (see here for the tutorial on how to do it, and it just works!) and this app can't be signed with the firmware signing key as it works on many android versions and different devices and you don't even need to be rooted.
I would like to do this in my app. Of course, I don't want to blow up the users privacy, so I would first ask the user if he wants to turn it on automatically with the typical "remember my decision" checkbox and if he answers yes, enable it.
Does anybody have any idea or clue on how Tasker achieves this?
the GPS can be toggled by exploiting a bug in the power manager widget. see this xda thread for discussion.
here's some example code i use
private void turnGPSOn(){
String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if(!provider.contains("gps")){ //if gps is disabled
final Intent poke = new Intent();
poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
sendBroadcast(poke);
}
}
private void turnGPSOff(){
String provider = Settings.Secure.getString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if(provider.contains("gps")){ //if gps is enabled
final Intent poke = new Intent();
poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
sendBroadcast(poke);
}
}
use the following to test if the existing version of the power control widget is one which will allow you to toggle the gps.
private boolean canToggleGPS() {
PackageManager pacman = getPackageManager();
PackageInfo pacInfo = null;
try {
pacInfo = pacman.getPackageInfo("com.android.settings", PackageManager.GET_RECEIVERS);
} catch (NameNotFoundException e) {
return false; //package not found
}
if(pacInfo != null){
for(ActivityInfo actInfo : pacInfo.receivers){
//test if recevier is exported. if so, we can toggle GPS.
if(actInfo.name.equals("com.android.settings.widget.SettingsAppWidgetProvider") && actInfo.exported){
return true;
}
}
}
return false; //default
}
All these answers are not allowed now. Here is the correct one:
For all those still looking for the Answer:
Here is how OLA Cabs and other such apps are doing it.
Add this in your onCreate
if (googleApiClient == null) {
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API).addConnectionCallbacks(this)
.addOnConnectionFailedListener(Login.this).build();
googleApiClient.connect();
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(30 * 1000);
locationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
// **************************
builder.setAlwaysShow(true); // this is the key ingredient
// **************************
PendingResult<LocationSettingsResult> result = LocationServices.SettingsApi
.checkLocationSettings(googleApiClient, 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(Login.this, 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;
}
}
});
}
These are the implmented methods:
#Override
public void onConnected(Bundle arg0) {
// TODO Auto-generated method stub
}
#Override
public void onConnectionSuspended(int arg0) {
// TODO Auto-generated method stub
}
#Override
public void onConnectionFailed(ConnectionResult arg0) {
// TODO Auto-generated method stub
}
Here is the Android Documentation for the same.
This is to help other guys if they are still struggling:
Edit: Adding Irfan Raza's comment for more help.
#Override protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == 1000) {
if(resultCode == Activity.RESULT_OK){
String result=data.getStringExtra("result");
} if (resultCode == Activity.RESULT_CANCELED) {
//Write your code if there's no result
}
}
}
ENABLE GPS:
Intent intent=new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", true);
sendBroadcast(intent);
DISABLE GPS:
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", false);
sendBroadcast(intent);
This code works on ROOTED phones if the app is moved to /system/aps, and they have the following permissions in the manifest:
<uses-permission android:name="android.permission.WRITE_SETTINGS"/>
<uses-permission android:name="android.permission.WRITE_SECURE_SETTINGS"/>
Code
private void turnGpsOn (Context context) {
beforeEnable = Settings.Secure.getString (context.getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
String newSet = String.format ("%s,%s",
beforeEnable,
LocationManager.GPS_PROVIDER);
try {
Settings.Secure.putString (context.getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
newSet);
} catch(Exception e) {}
}
private void turnGpsOff (Context context) {
if (null == beforeEnable) {
String str = Settings.Secure.getString (context.getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if (null == str) {
str = "";
} else {
String[] list = str.split (",");
str = "";
int j = 0;
for (int i = 0; i < list.length; i++) {
if (!list[i].equals (LocationManager.GPS_PROVIDER)) {
if (j > 0) {
str += ",";
}
str += list[i];
j++;
}
}
beforeEnable = str;
}
}
try {
Settings.Secure.putString (context.getContentResolver(),
Settings.Secure.LOCATION_PROVIDERS_ALLOWED,
beforeEnable);
} catch(Exception e) {}
}
Instead of using intent Settings.ACTION_LOCATION_SOURCE_SETTINGS you can directly able to show pop up in your app like Google Map & on Gps on click of ok button their is no need to redirect to setting simply you need to use my code as
Note : This line of code automatic open the dialog box if Location is not on. This piece of line is used in Google Map also
public class MainActivity extends AppCompatActivity
implements GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
LocationRequest mLocationRequest;
GoogleApiClient mGoogleApiClient;
PendingResult<LocationSettingsResult> result;
final static int REQUEST_LOCATION = 199;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
mGoogleApiClient.connect();
}
#Override
public void onConnected(Bundle bundle) {
mLocationRequest = LocationRequest.create();
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mLocationRequest.setInterval(30 * 1000);
mLocationRequest.setFastestInterval(5 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
builder.setAlwaysShow(true);
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(
MainActivity.this,
REQUEST_LOCATION);
} catch (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;
}
}
});
}
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
Log.d("onActivityResult()", Integer.toString(resultCode));
//final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode)
{
case REQUEST_LOCATION:
switch (resultCode)
{
case Activity.RESULT_OK:
{
// All required changes were successfully made
Toast.makeText(MainActivity.this, "Location enabled by user!", Toast.LENGTH_LONG).show();
break;
}
case Activity.RESULT_CANCELED:
{
// The user was asked to change settings, but chose not to
Toast.makeText(MainActivity.this, "Location not enabled, user cancelled.", Toast.LENGTH_LONG).show();
break;
}
default:
{
break;
}
}
break;
}
}
#Override
public void onConnectionSuspended(int i) {
}
#Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
}
Note : This line of code automatic open the dialog box if Location is not on. This piece of line is used in Google Map also
Since Android version 4.4, you can't enable/disable gps programatically. If you try the code proposed on this answer, an exception will be fired.
java.lang.SecurityException: Permission Denial: not allowed to send broadcast android.location.GPS_ENABLED_CHANGE
Above correct answer is very old it needs something new so Here is answer
As in last update we have androidx support so first include dependency in your app level build.gradle file
implementation 'com.google.android.gms:play-services-location:17.0.0'
then add in your manifest file:
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
don't forget to take user consent for these permissions if you are releasing
now here is code just use it
protected void createLocationRequest() {
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setInterval(10000);
locationRequest.setFastestInterval(5000);
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
SettingsClient client = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = client.checkLocationSettings(builder.build());
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
// All location settings are satisfied. The client can initialize
// location requests here.
// ...
Toast.makeText(MainActivity.this, "Gps already open",
Toast.LENGTH_LONG).show();
Log.d("location settings",locationSettingsResponse.toString());
}
});
task.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
if (e instanceof ResolvableApiException) {
// 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().
ResolvableApiException resolvable = (ResolvableApiException) e;
resolvable.startResolutionForResult(MainActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sendEx) {
// Ignore the error.
}
}
}
});
}
#Override
protected void onActivityResult(int requestCode, int resultCode, #Nullable Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(requestCode==REQUEST_CHECK_SETTINGS){
if(resultCode==RESULT_OK){
Toast.makeText(this, "Gps opened", Toast.LENGTH_SHORT).show();
//if user allows to open gps
Log.d("result ok",data.toString());
}else if(resultCode==RESULT_CANCELED){
Toast.makeText(this, "refused to open gps",
Toast.LENGTH_SHORT).show();
// in case user back press or refuses to open gps
Log.d("result cancelled",data.toString());
}
}
}
if something goes wrong please ping me
Short and easy solution with newest API, from https://developer.android.com/training/location/change-location-settings.html.
You will get nice Google AlertDialog with ok button without any need of going to settings.
Straight to the point. My code in Fragment:
override fun onResume() {
super.onResume()
checkGPSEnabled()
}
private fun checkGPSEnabled() {
val manager = requireContext().getSystemService(Context.LOCATION_SERVICE) as LocationManager
if (manager.isProviderEnabled(LocationManager.GPS_PROVIDER).not()) {
turnOnGPS()
}
}
private fun turnOnGPS() {
val request = LocationRequest.create().apply {
interval = 2000
priority = LocationRequest.PRIORITY_HIGH_ACCURACY
}
val builder = LocationSettingsRequest.Builder().addLocationRequest(request)
val client: SettingsClient = LocationServices.getSettingsClient(requireActivity())
val task: Task<LocationSettingsResponse> = client.checkLocationSettings(builder.build())
task.addOnFailureListener {
if (it is ResolvableApiException) {
try {
it.startResolutionForResult(requireActivity(), 12345)
} catch (sendEx: IntentSender.SendIntentException) {
}
}
}.addOnSuccessListener {
//here GPS is On
}
}
That's it. Just copy and paste. You will need also:
implementation 'com.google.android.gms:play-services-location:18.0.0' and in Manifest <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
An answer was developed in another question, but it was closed, and I'd like the community to try it out as well.
boolean gpsStatus = locmanager.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!gpsStatus) {
Settings.Secure.putString(getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED, "network,gps");
}
See this comment
This solution would require the WRITE_SETTINGS and WRITE_SECURE_SETTINGS permissions.
Maybe with reflection tricks around the class android.server.LocationManagerService.
Also, there is a method (since API 8) android.provider.Settings.Secure.setLocationProviderEnabled
This is the best solution provided by Google Developers. Simply call this method in onResume of onCreate after initializing GoogleApiClient.
private void updateMarkers() {
if (mMap == null) {
return;
}
if (mLocationPermissionGranted) {
// Get the businesses and other points of interest located
// nearest to the device's current location.
mGoogleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API).build();
mGoogleApiClient.connect();
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);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest
.Builder()
.addLocationRequest(mLocationRequest);
PendingResult<LocationSettingsResult> resultPendingResult = LocationServices
.SettingsApi
.checkLocationSettings(mGoogleApiClient, builder.build());
resultPendingResult.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(#NonNull LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
final LocationSettingsStates locationSettingsStates = locationSettingsResult.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 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(
MainActivity.this,
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
} 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;
}
}
});
#SuppressWarnings("MissingPermission")
PendingResult<PlaceLikelihoodBuffer> result = Places.PlaceDetectionApi
.getCurrentPlace(mGoogleApiClient, null);
result.setResultCallback(new ResultCallback<PlaceLikelihoodBuffer>() {
#Override
public void onResult(#NonNull PlaceLikelihoodBuffer likelyPlaces) {
for (PlaceLikelihood placeLikelihood : likelyPlaces) {
// Add a marker for each place near the device's current location, with an
// info window showing place information.
String attributions = (String) placeLikelihood.getPlace().getAttributions();
String snippet = (String) placeLikelihood.getPlace().getAddress();
if (attributions != null) {
snippet = snippet + "\n" + attributions;
}
mMap.addMarker(new MarkerOptions()
.position(placeLikelihood.getPlace().getLatLng())
.title((String) placeLikelihood.getPlace().getName())
.snippet(snippet));
}
// Release the place likelihood buffer.
likelyPlaces.release();
}
});
} else {
mMap.addMarker(new MarkerOptions()
.position(mDefaultLocation)
.title(getString(R.string.default_info_title))
.snippet(getString(R.string.default_info_snippet)));
}
}
Note : This line of code automatic open the dialog box if Location is not on. This piece of line is used in Google Map also
status.startResolutionForResult(
MainActivity.this,
PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION);
This code works on ROOTED phones:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String[] cmds = {"cd /system/bin" ,"settings put secure location_providers_allowed +gps"};
try {
Process p = Runtime.getRuntime().exec("su");
DataOutputStream os = new DataOutputStream(p.getOutputStream());
for (String tmpCmd : cmds) {
os.writeBytes(tmpCmd + "\n");
}
os.writeBytes("exit\n");
os.flush();
}
catch (IOException e){
e.printStackTrace();
}
}
}
For turning off GPS you can use this command instead
settings put secure location_providers_allowed -gps
You can also toggle network accuracy using the following commands:
for turning on use:
settings put secure location_providers_allowed +network
and for turning off you can use:
settings put secure location_providers_allowed -network
This one works for me.
It is a simpler solution than Rj0078's answer under this question, but that one is worked as well.
It shows a dialog like this:
(Written in Kotlin)
googleApiClient = GoogleApiClient.Builder(context!!)
.addApi(LocationServices.API).build()
googleApiClient!!.connect()
locationRequest = LocationRequest.create()
locationRequest!!.priority = LocationRequest.PRIORITY_HIGH_ACCURACY
locationRequest!!.interval = 30 * 1000.toLong()
locationRequest!!.fastestInterval = 5 * 1000.toLong()
val builder = LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest!!)
builder.setAlwaysShow(true)
result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build())
result!!.setResultCallback { result ->
val status: Status = result.status
when (status.statusCode) {
LocationSettingsStatusCodes.SUCCESS -> {
// Do something
}
LocationSettingsStatusCodes.RESOLUTION_REQUIRED ->
try {
startResolutionForResult(),
status.startResolutionForResult(
activity,
REQUEST_LOCATION
)
} catch (e: SendIntentException) {
}
LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE -> {
// Do something
}
}
}
Things have changed since this question was posted, now with new Google Services API, you can prompt users to enable GPS:
https://developers.google.com/places/android-api/current-place
You will need to request ACCESS_FINE_LOCATION permission in your manifest:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
Also watch this video:
https://www.youtube.com/watch?v=F0Kh_RnSM0w
This is a more statble code for all Android versions and possibly for new ones
void checkGPS() {
LocationRequest locationRequest = LocationRequest.create();
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder().addLocationRequest(locationRequest);
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
Task<LocationSettingsResponse> task = settingsClient.checkLocationSettings(builder.build());
task.addOnSuccessListener(this, new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
Log.d("GPS_main", "OnSuccess");
// GPS is ON
}
});
task.addOnFailureListener(this, new OnFailureListener() {
#Override
public void onFailure(#NonNull final Exception e) {
Log.d("GPS_main", "GPS off");
// GPS off
if (e instanceof ResolvableApiException) {
ResolvableApiException resolvable = (ResolvableApiException) e;
try {
resolvable.startResolutionForResult(ActivityMain.this, REQUESTCODE_TURNON_GPS);
} catch (IntentSender.SendIntentException e1) {
e1.printStackTrace();
}
}
}
});
}
And you can handle the GPS state changes here
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if(requestCode == Static_AppVariables.REQUESTCODE_TURNON_GPS) {
switch (resultCode) {
case Activity.RESULT_OK:
// GPS was turned on;
break;
case Activity.RESULT_CANCELED:
// User rejected turning on the GPS
break;
default:
break;
}
}
}
You just need to remove the LocationListener from LocationManager
manager.removeUpdates(listener);
Use This code Simple and Easy to Access:
Permissions:
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
Follow this Code to access the GPS programmatically:
LocationManager locationManager ;
boolean GpsStatus ;
GPSStatus();
if(GpsStatus == true)
{
textview.setText("Your Location Services Is Enabled");
}else
{textview.setText("Your Location Services Is Disabled");}
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
public void GPSStatus(){
locationManager = (LocationManager)context.getSystemService(Context.LOCATION_SERVICE);
GpsStatus = locationManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
}
I am trying to create an app for my own use that enables/disables certain features like WiFi, GPS, etc; my question pertains to GPS. Note that my phone is not rooted and I would like to keep it that way.
I have successfully enabled GPS using the following code:
public void toggleGPS() {
GoogleApiClient googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this)
.build();
LocationRequest locationRequest = new LocationRequest();
if (isGPSEnabled()) {
locationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
locationRequest.setInterval(60 * 60 * 1000);
locationRequest.setFastestInterval(60 * 60 * 1000);
} else {
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(1000);
locationRequest.setFastestInterval(1000);
}
googleApiClient.connect();
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(LocationSettingsResult result) {
Status status = result.getStatus();
LocationSettingsStates locationSettingsStates = result.getLocationSettingsStates();
if (status.getStatusCode() == LocationSettingsStatusCodes.RESOLUTION_REQUIRED) {
try {
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
status.startResolutionForResult(MainActivity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
}
}
}
});
}
So when GPS isn't on, this code prompts me to turn it on, as I want. However, it doesn't seem to shut off when I request Balanced Power and set the larger intervals and no other app is using GPS. I assumed that if my app no longer needs high accuracy, then GPS will automatically be switched off. Am I misunderstanding something? And is there any way to switch it off? I can sort of understand the security concerns for disallowing GPS to be ENABLED programmatically, but I don't understand why Android wouldn't allow it to be DISABLED.
Thanks in advance!
try this code it works on all versions, make a try ....
// automatic turn off the gps
public void turnGPSOff()
{
String provider = Settings.Secure.getString(ctx.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if(provider.contains("gps")){ //if gps is enabled
final Intent poke = new Intent();
poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
this.ctx.sendBroadcast(poke);
}
}
and code to enable is as follow you can use this..
public void turnGPSOn()
{
Intent intent = new Intent("android.location.GPS_ENABLED_CHANGE");
intent.putExtra("enabled", true);
this.ctx.sendBroadcast(intent);
String provider = Settings.Secure.getString(ctx.getContentResolver(), Settings.Secure.LOCATION_PROVIDERS_ALLOWED);
if(!provider.contains("gps")){ //if gps is disabled
final Intent poke = new Intent();
poke.setClassName("com.android.settings", "com.android.settings.widget.SettingsAppWidgetProvider");
poke.addCategory(Intent.CATEGORY_ALTERNATIVE);
poke.setData(Uri.parse("3"));
this.ctx.sendBroadcast(poke);
}
}
I am getting the longitude and latitude of my device, but it takes at 30 seconds to a minute to do so. Any suggestions to cut the time down?
public class MainActivity extends Activity
{
public String zipcode;
public double latG;
public double lonG;
#Override
protected void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
LocationManager service = (LocationManager) getSystemService(LOCATION_SERVICE);
boolean enabled = service.isProviderEnabled(LocationManager.GPS_PROVIDER);
if (!enabled)
{
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
}
LocationManager locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
locationManager.getLastKnownLocation(Context.LOCATION_SERVICE);
LocationListener locationListener = new LocationListener()
{
public void onLocationChanged(Location location)
{
if (location != null)
{
latG = location.getLatitude();
lonG = location.getLongitude();
Toast.makeText(MainActivity.this,
latG + " " + lonG,
Toast.LENGTH_LONG).show();
}
}
public void onProviderDisabled(String provider)
{
}
public void onProviderEnabled(String provider)
{
}
public void onStatusChanged(String provider, int status, Bundle extras)
{
}
};
locationManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locationListener);
Geocoder geocoder = new Geocoder(this, Locale.getDefault());
List<Address> addresses = null;
try
{
addresses = geocoder.getFromLocation(latG, lonG, 1);
}
catch (IOException e)
{
Context context = this;
AlertDialog.Builder alertDialogBuilder = new AlertDialog.Builder(context);
alertDialogBuilder.setTitle("Error");
alertDialogBuilder.setMessage("Error in getting address information.");
alertDialogBuilder.setCancelable(true);
}
for (Address address : addresses)
{
if(address.getPostalCode() != null)
{
zipcode = address.getPostalCode();
Toast.makeText(MainActivity.this, zipcode, Toast.LENGTH_LONG).show();
break;
}
}
}
}
You are using GPS_PROVIDER for fetching the GPS data. GPS_PROVIDER fetches details directly from the satellite so it takes time for the first time you load this. Moreover GPS_PROVIDER takes more than 30 seconds if your are not below the open sky. GPS_PROVIDER may return NULL when you are inside the office or in basement.
There is an alternative way for this is to use NETWORK_PROVIDER. This provider will give you GPS details based on your current Network state. This will not be much accurate like GPS_PROVIDER but it works faster.
hi you are using GPS PROVIDER which can take some time as it depends on several constraints like yours building position, physical position, weather as gps data is available from the satellite so use a network provider which may faster in yours case please have a look on the given code snippet at
http://www.androidhive.info/2012/07/android-gps-location-manager-tutorial/
Best option is to use Google Play Services and its LocationClient.
http://developer.android.com/google/play-services/location.html
This gives you a provider that automatically picks the best available information from all the provider types and can return the location immediately in some cases using getLastLocation()
try to run it in device rather than running it in the emulator.
try this
try {
gps_enabled = locManager.isProviderEnabled(LocationManager.GPS_PROVIDER);
} catch (Exception ex) {
}
try {
network_enabled = locManager.isProviderEnabled(LocationManager.NETWORK_PROVIDER);
} catch (Exception ex) {}
if (gps_enabled) {
locManager.requestLocationUpdates(LocationManager.GPS_PROVIDER, 0, 0, locListener);
}
if (network_enabled) {
locManager.requestLocationUpdates(LocationManager.NETWORK_PROVIDER, 0, 0, locListener);
It will give the response what ever the service is available.Even you can place your priority
Use this code to fetch faster,
String provider;
locationManager = (LocationManager) getSystemService(Context.LOCATION_SERVICE);
Criteria criteria = new Criteria();
provider = locationManager.getBestProvider(criteria, false);
if (provider != null && !provider.equals("")) {
Location location = locationManager.getLastKnownLocation(provider);
locationManager.requestLocationUpdates(provider, 20000, 1, this);
if (location != null)
{
onLocationChanged(location);
//your remaining code
}