Activity.RESULT_CANCELED (value == 0 )always getting called in onActivityResult() even when OK is pressed on Location Dialog
I am showing location dialog to the user if the location is turned off in the device setting.
Following code is used -
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder();
builder.addLocationRequest(new LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY));
builder.setAlwaysShow(true);
mLocationSettingsRequest = builder.build();
mSettingsClient = LocationServices.getSettingsClient(WifiList_Activity.this);
mSettingsClient
.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
//Success Perform Task Here
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
ResolvableApiException rae = (ResolvableApiException) e;
rae. startResolutionForResult(WifiList_Activity.this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException sie) {
Logger.log("GPS Unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
Logger.log("GPS Location settings are inadequate, and cannot be fixed here. Fix in Settings.");
}
}
});
And the code in onActivityResult() is as below ,
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_CHECK_SETTINGS) {
switch (resultCode) {
case Activity.RESULT_CANCELED:
Logger.log("Result code in onACtivityresult CANCELED::"+resultCode);
Logger.log("GPS User denied to access location");
finish();
break;
case Activity.RESULT_OK:
//Success Perform Task Here
Logger.log("Result code in onACtivityresult OK::"+resultCode);
break;
}
}
}
But the problem is even if the user presses OK on the Location dialog, Acivity.RESULT_CANCELED is always getting called as the received resultCode is 0.
I have targeted the App for Android Q,
compileSDKVersion "android-Q'
targetSDKVersion 'Q'
Also, running the App on Android Q beta on a Pixel device.
Expected - on OK press of location dialog, resultCode -1 should be
returned in onActivityResult.
Actual - Even if ok is pressed, the resultCode 0 is returned in
onActivityResult.
Related
My app works fine in turning location on and setPriority to HIGH when the Location setting is off, but it crashes when the location is set as GPS LocationRequest.PRIORITY_LOW_POWER instead of displaying the dialog to change to LocationRequest.PRIORITY_HIGH_ACCURACY
Here is the method that access the SettingClient
public void locationSettingRequest() {
LocationRequest mLocationRequestHighAccuracy = new LocationRequest().setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
LocationRequest mLocationRequestBalancedPowerAccuracy = new LocationRequest().setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequestHighAccuracy)
.addLocationRequest(mLocationRequestBalancedPowerAccuracy);
Task<LocationSettingsResponse> result =
LocationServices.getSettingsClient(this).checkLocationSettings(builder.build());
result.addOnCompleteListener(task -> {
try {
LocationSettingsResponse response = task.getResult(ApiException.class);
// All location settings are satisfied. The client can initialize location
// requests here.
getLoc();
} catch (ApiException exception) {
switch (exception.getStatusCode()) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
// Location settings are not satisfied. But could be fixed by showing the
// user a dialog.
try {
// Cast to a resolvable exception.
ResolvableApiException resolvable = (ResolvableApiException) exception;
// Show the dialog by calling startResolutionForResult(),
// and check the result in onActivityResult().
resolvable.startResolutionForResult(
SignUpActivity.this,
REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
// Ignore the error.
} catch (ClassCastException e) {
// Ignore, should be an impossible 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;
}
}
});
}
and I received the response in the OnActivityResult
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
if (requestCode == REQUEST_CHECK_SETTINGS) {
switch (resultCode) {
case Activity.RESULT_OK:
// All required changes were successfully made
getLoc();
break;
case Activity.RESULT_CANCELED:
finish();
break;
default:
break;
}
}
super.onActivityResult(requestCode, resultCode, data);
}
How do I get the location to change from LocationRequest.PRIORITY_LOW_POWER to HIGH_ACCURACY?
This is how I solved it, I checked if the LocationManager.NETWORK_PROVIDER is enable. If it not, I display a message to prompt user to change location mode to HIGH_ACCURACY. I then call settingRequest if NETWORK_PROVIDER is enable.
Not sure if it's the right way, but it worked.
public void checkLocationMode() {
LocationManager loc = (LocationManager) this.getSystemService(Context.LOCATION_SERVICE);
if (!loc.isProviderEnabled(LocationManager.NETWORK_PROVIDER)) {
Toast.makeText(this, "Turn location mode to High Accuracy.", Toast.LENGTH_LONG).show();
Intent myIntent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(myIntent);
} else {
settingRequest();
}
}
I'm using FusedLocationAPI it is working properly but when user disabled location i'm using SettingsApi to show dialog to user to enable location.
In marshmallow and above devices it is working fine but in kitkat if location is enabled or disabled, it is always triggering LocationSettingsStatusCodes.RESOLUTION_REQUIRED.
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(mLocationRequest);
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(mGoogleApiClient, builder.build());
result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
#Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
Log.e("status",status.getStatusCode()+"\n"+status.getStatus()+"\n"+status.getStatusMessage());
final LocationSettingsStates LS_state = locationSettingsResult.getLocationSettingsStates();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// All location settings are satisfied. The client can initialize location
// requests here.
startLocationUpdates();
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_CHECK_SETTINGS);
} 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;
}
}
});
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == REQUEST_PERMISSION_SETTING) {
if (ActivityCompat.checkSelfPermission(MainActivity.this, permissionsRequired[0]) == PackageManager.PERMISSION_GRANTED) {
//Got Permission
proceedAfterPermission();
}
} else if (requestCode == REQUEST_CHECK_SETTINGS) {
switch (resultCode) {
case RESULT_OK:
// All required changes were successfully made
startLocationUpdates();
break;
case RESULT_CANCELED:
// The user was asked to change settings, but chose not to
Toast.makeText(this, "User cancelled location enabled", Toast.LENGTH_SHORT).show();
break;
default:
break;
}
}
}
In kitkat it is showing dialog like this but when clicking on ok it is triggering user cancelled location
In my app if the user doesn't have the location turned on I am prompting with a dialog and then trying to return that result (probably incorrectly) by overriding on activity result.
This is inside a fragment so not sure how that changes things:
This is how I am calling it the dialog with startResolutionForResult:
public void checkDeviceLocationIsOn()
{
System.out.println("Test running setting request" );
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(LocationRequest.PRIORITY_LOW_POWER);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
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.
System.out.println("Test setting all fine starting location request" );
getLocation();
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(getActivity(), LOCATION_SETTINGS_REQUEST_CODE);
System.out.println("Test setting not met starting dialog to prompt user" );
} 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;
}
}
});
}
And then I try to get the result like this below it (This never gets called):
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
switch (requestCode) {
// Check for the integer request code originally supplied to startResolutionForResult().
case LOCATION_SETTINGS_REQUEST_CODE:
switch (resultCode) {
case Activity.RESULT_OK:
System.out.println("test user has turned the gps back on");
getLocation();
break;
case Activity.RESULT_CANCELED:
System.out.println("test user has denied the gps to be turned on");
Toast.makeText(getActivity(), "Location is required to order stations", Toast.LENGTH_SHORT).show();
break;
}
break;
}
}
Thanks in advance for your help
Call the fragment method
startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CODE_LOCATION_SETTING, null, 0, 0, 0, null);
instead of
status.startResolutionForResult(...)
To start resolution for result in your fragment you should use the new API
first, create the ActivityResultLanucher
private val resolutionForResult =
registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { activityResult ->
if (activityResult.resultCode == RESULT_OK)
//startLocationUpdates() or do whatever you want
else {
showMessage("we can't determine your location")
}
}
then use it like this
val intentSenderRequest = IntentSenderRequest.Builder(exception.resolution).build()
resolutionForResult.launch(intentSenderRequest)
in Super Activity Perform this Method...
in MainActivity
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
final int REQUEST_CHECK_SETTINGS = 100;//check GPS setting
Log.d("onActivityResult()", Integer.toString(resultCode));
//final LocationSettingsStates states = LocationSettingsStates.fromIntent(data);
switch (requestCode)
{
case REQUEST_CHECK_SETTINGS:
switch (resultCode)
{
case Activity.RESULT_OK:
{
// All required changes were successfully made
Toast.makeText(this, "Location enabled by user!", Toast.LENGTH_LONG).show();
ContactFragment.isGPSEnabled=true;
ContactFragment.click();
break;
}
case Activity.RESULT_CANCELED:
{
// The user was asked to change settings, but chose not to
Toast.makeText(this, "Location not enabled, user cancelled.", Toast.LENGTH_LONG).show();
ContactFragment.isGPSEnabled=false;
break;
}
default:
{
break;
}
}
break;
}
}
inside ContactFragment
#Override
public void onConnected(#Nullable 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(googleApiClient, builder.build());
result.setResultCallback(this);
}
#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(
getActivity(),
REQUEST_CHECK_SETTINGS);
} 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;
}
}
Maybe an easy solution is to use two activities and show one like a dialog by using any dialog theme on the Manifest
<activity
android:name=".LocationDialogActivity"
android:theme="#style/DialogStyle"></activity>
them just use the onActivityResult as you used it always.
DialogActivity
private void setLocation() {
Intent intentResult = new Intent();
intentResult.putExtra("latitude", "valueLat");
intentResult.putExtra("longitude", "valueLon");
setResult(RESULT_OK, intentResult);
finish();
}
MainActivity
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//super.onActivityResult(requestCode, resultCode, data);
if (resultCode == RESULT_OK) {
/*Take your data*/
latitude = data.getExtras().getString("latitude");
longitude = data.getExtras().getString("longitude");
}
}
I've seen this Q&A LocationSettingsRequest dialog - onActivityResult() skipped. It isn't the same issue because everything is being done in an Activity already.
The code used is almost verbatim what is given in the Google Play Services examples.
I have an activity, LocationActivity, that connects to GoogleApiClient for getting the user's location. Once connected I create a LocationSettingsRequest to make sure that location settings are turned on. The activity is implementing ResultCallback<LocationSettingsResult>.
ResultCallback<LocationSettingsResult>.onResult() is called and if result.getStatus().getStatusCode() == LocationSettingsStatusCodes.RESOLUTION_REQUIRED then status.startResolutionForResult(this, REQUEST_CHECK_SETTINGS) is called and the dialog is shown. The problem, no matter what is selected, onActivityResult() is never called.
#Override
public void onConnected(Bundle connectionHint) {
Log.i(TAG, "GoogleApiClient connected");
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(new LocationRequest().setPriority(LocationRequest.PRIORITY_LOW_POWER));
PendingResult<LocationSettingsResult> result =
LocationServices.SettingsApi.checkLocationSettings(googleApiClient, builder.build());
result.setResultCallback(this);
}
.
#Override
public void onResult(LocationSettingsResult result) {
final Status status = result.getStatus();
Log.d(TAG, "onResult() called with: " + "result = [" + status.getStatusMessage() + "]");
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
getLocation();
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(this, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
Log.d(TAG, "", e);
// Ignore the error.
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
showManualInputDialog();
break;
}
}
I never get here:
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
Log.d(TAG, "onActivityResult() called with: " + "requestCode = [" + requestCode + "], resultCode = [" + resultCode + "], data = [" + data + "]");
switch (requestCode) {
case REQUEST_CODE_RESOLUTION:
retryConnecting();
break;
case REQUEST_CHECK_SETTINGS:
if (resultCode == Activity.RESULT_OK) {
getLocation();
} else {
showManualInputDialog();
}
break;
default:
super.onActivityResult(requestCode, resultCode, data);
break;
}
}
As an aside. It worked a few times on my S3. From what I can tell it stopped working when I chose to never ask again. But, it hasn't ever worked on an emulator or a Tab 10 and it no longer works on my S3.
If you are running this code in Fragment than don't use startResolutionForResult(). Instead use
startIntentSenderForResult(status.getResolution().getIntentSender(), REQUEST_CODE_LOCATION_SETTING, null, 0, 0, 0, null);
and overrider onaActivityResult() in your fragment.
Result will be delivered to this method only.
Well I feel silly. My Activity had noHistory="true" in the Manifest so when the other Activity was started there was nothing to come back to.
In my case there was this error:
I've used
public abstract class AGoogleDriveBase extends ABase implements
GoogleApiClient.ConnectionCallbacks,
GoogleApiClient.OnConnectionFailedListener {
//...
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
//...
and this function not called using
try {
result.startResolutionForResult(this, REQUEST_CODE_RESOLUTION);
} catch (SendIntentException e) {
Log.e(TAG, "Exception while starting resolution activity", e);
}
because when I used a main activity
public class myAct extends AGoogleDriveBase implements ... {
//...
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
the super method not called (not existed this string):
super.onActivityResult(requestCode, resultCode, data);
You can use the registerActivityForResult API and bypass the activity alltogether.
val registration: ActivityResultLauncher<IntentSenderRequest> = fragment.registerForActivityResult(ActivityResultContracts.StartIntentSenderForResult()) { // callback
Then when capturing the exception
when (exception.statusCode) {
LocationSettingsStatusCodes.RESOLUTION_REQUIRED ->
try {
if (exception is ResolvableApiException) {
val request: IntentSenderRequest = IntentSenderRequest.Builder(
exception.resolution.intentSender
).setFillInIntent(Intent())
.setFlags(0, 0)
.build()
registration.launch(request)
}
} catch (e: SendIntentException) {
```
You can check out the Google Play Location Sample since your code is quite similar it.
From what I can tell on your samples, onResult() may not be called because the case is not LocationSettingsStatusCodes.RESOLUTION_REQUIRED. Its not calling the startResolutionForResult or an underlying setActivityForResult inside it.
If anyone has stumbled on to this problem, gianlucaparadise's answer is one of the better way's of solving this problem. Although the answer is deleted, it adds a lot of value.
In my application I'm checking whether the GPS is enabled on the user's device, and if not I would like to send him to the Settings to let him turn it on.
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivityForResult(intent, LocationHelper.LOCATION_SETTINGS_REQUEST_CODE);
After the user closes Settings screen, I would to perform an action right inside the onActivityResult().
#Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == LocationHelper.LOCATION_SETTINGS_REQUEST_CODE) {
LogUtils.d("onActivityResult from settings");
fetchCurrentLocation();
}
}
However, the onActivityResult() doesn't get called. Am I doing something wrong or this approach doesn't work in general? Thanks in advance.
lauch the setting intent :
Intent intent = new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS);
startActivity(intent);
and fetch the current location in onResume method :
public void onResume(){
super.onResume();
if(isGPSEnabled){
fetchCurrentLocation();
}
}
after backing from setting screen , your onResume method will be call and here you can fetch your location.
Enable GPS programmatically using the following code,
private void askToEnableGPS(){
LocationRequest locationRequest = LocationRequest.create();
locationRequest.setPriority(Priority.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(10 * 1000);
locationRequest.setFastestInterval(2 * 1000);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
LocationSettingsRequest mLocationSettingsRequest = builder.build();
SettingsClient settingsClient = LocationServices.getSettingsClient(this);
settingsClient.checkLocationSettings(mLocationSettingsRequest)
.addOnSuccessListener(new OnSuccessListener<LocationSettingsResponse>() {
#Override
public void onSuccess(LocationSettingsResponse locationSettingsResponse) {
}
})
.addOnFailureListener(new OnFailureListener() {
#Override
public void onFailure(#NonNull #NotNull Exception e) {
int statusCode = ((ApiException) e).getStatusCode();
switch (statusCode) {
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
// Show the dialog by calling startResolutionForResult(), and check the
// result in onActivityResult().
ResolvableApiException rae = (ResolvableApiException) e;
rae.startResolutionForResult(MainActivity.this, 5678);
} catch (IntentSender.SendIntentException sie) {
Log.i(TAG, "PendingIntent unable to execute request.");
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
String errorMessage = "Location settings are inadequate, and cannot be " +
"fixed here. Fix in Settings.";
Log.e(TAG, errorMessage);
// notify user
new androidx.appcompat.app.AlertDialog.Builder(new ContextThemeWrapper(MainActivity.this,
R.style.Theme_MaterialComponents_DayNight_DarkActionBar)).setMessage("Please enable location services").setCancelable(false).setPositiveButton("Open location settings", (dialog, which) -> {
startActivity(new Intent(Settings.ACTION_LOCATION_SOURCE_SETTINGS));
}).create().show();
break;
}
}
});
}
And get the results in onActivityResult with Request Code 5678.
#Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if (requestCode == 5678 && resultCode == RESULT_OK) {
// GPS Enabled
}
}
Have you defined ACCESS_FINE_LOCATION permission in your manifest?
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"></uses-permission>