Forum Xamarin.Android

OnActivityResult always receives resultCode = Result.Canceled

elefpelefp GRMember ✭✭

I am trying to check the location/connection settings of the user's device to take advantage of Google Fused API and provide the user's location. I've read a lot of samples such as the one at: (https://github.com/googlesamples/android-play-location/blob/master/LocationSettings/app/src/main/java/com/google/android/gms/location/sample/locationsettings/MainActivity.java)
I've simplified my project to let the MainActivity do all the job (implement Google interfaces etc.) but still face the same problem.

When the device has not all the prerequisite settings (Location enabled and set at High Accuracy & WiFi scanning always on), I attempt to initiate a resolution. The problem is that when the user clicks Ok, OnActivityResult always receives resultCode = Result.Canceled. The strange thing is that the device settings are changed indeed after Ok is clicked to the ones that satisfy Google's prerequisites for Fused API to work.

There's a similar post: https://forums.xamarin.com/discussion/81994/locationsettings-kitkat-emulator-result-canceled, but no reply yet for this behavior. I would be grateful if anyone could let us know what is going wrong.

Posts

  • @elefp
    What exactly are you trying to do? If you just want to grab GPS coordinates and possibly display an address, there's much easier ways to do so. A location listener combined with a Geocoder will do just that. If I can get a little bit better background of what you're trying to do I'd be glad to help! Typically if you get a result canceled, it's just that. Whatever activity you're calling isn't returning the proper information, and cancelling. If you're calling some library and can't see the code, something is either broken in their code or you're possibly doing something wrong with how you're calling it. Again, it's hard for me to know without seeing code snippets or know exactly what's happening!

  • elefpelefp GRMember ✭✭

    @JustinWojciechowski Thanks a lot for willing to help. I am not going to waste your time describing the whole of the app. My current issue is that I want to get the user's coordinates as accurate as possible to provide a map with a route towards a point of interest and next I am going to track the user's coordinates on that route updating their marker on the map. I've already accomplished that using the "old" way, i.e. implementing Android.Locations.ILocationListener and so on. However, when I came across the Fused API of Google, I thought of taking advantage of that. It proved much more accurate which is crucial for my app. Initially I tried to combine both "ways" so that I could serve even the most "strange" client that would refuse any of: a) open WiFi or b) set "Scanning WiFi" always on or c) set Location to "High Accuracy" level. I realized though that anything apart from the Fused API resulted to very poor accuracy and decided to take advantage of the resolution mechanism to actually "force" the user accept the prerequisites for Fused API. As I've already mentioned during trial & error attempts I have even simplified the Android part of the project to just one Activity that does everything (my actual wish is to have the location related code in another class that would implement an interface in the PCL project, so that I do similar things in all platforms (Android, iOS, Windows)).
    I'll paste the code of the simplest trial, so that you can review it and let me know what I am doing wrong. Do not bother with the not implemented methods. Please just focus on the fact that StartResolutionForResult always ends up in OnActivityResult with resultCode = Result.Canceled, despite the fact that the user has clicked Ok and despite the fact that this click has caused the necessary changes. What I mean by the last statement is that even if the Location is totally deactivated, the WiFi is Off and the "Scanning WiFi" setting is off, this "Ok" click activates the Location Service placing the level at "High Accuracy" and sets "Scanning WiFi" setting to on. However, this information never ends up in OnActivityResult. I am testing on an actual ZTE device with Android 5.0. Thanks again for your time.

    `[Activity(Label = "TestLocation",
    Icon = "@drawable/icon",
    Theme = "@style/MainTheme",
    MainLauncher = true,
    ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
    public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity,
    GoogleApiClient.IConnectionCallbacks,
    GoogleApiClient.IOnConnectionFailedListener,
    Android.Gms.Location.ILocationListener
    {
    private GoogleApiClient locationClient;
    private LocationRequest locationRequest;
    private LocationSettingsRequest locationSettingsRequest;
    private const int MIN_TIME_BW_UPDATES = 1000 * 3;
    private const int REQUEST_CHECK_SETTINGS = 9000;

        public async void OnConnected(Bundle connectionHint)
        {
            await CheckFusedApiSettings();
        }
    
        public void OnConnectionFailed(ConnectionResult result)
        {
            throw new NotImplementedException();
        }
    
        public void OnConnectionSuspended(int cause)
        {
            throw new NotImplementedException();
        }
    
        public void OnLocationChanged(Location location)
        {
            throw new NotImplementedException();
        }
    
        protected override void OnCreate(Bundle bundle)
        {
            TabLayoutResource = Resource.Layout.Tabbar;
            ToolbarResource = Resource.Layout.Toolbar;
    
            base.OnCreate(bundle);
    
            InitiateClient();
            InitiateRequests();
    
            global::Xamarin.Forms.Forms.Init(this, bundle);
            LoadApplication(new App());
        }
    
        protected override void OnStart()
        {
            base.OnStart();
            locationClient.Connect();
        }
    
        protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
        {
            base.OnActivityResult(requestCode, resultCode, data);
            if (requestCode == REQUEST_CHECK_SETTINGS)
            {
                switch (resultCode)
                {
                    case Result.Canceled:
                    Toast.MakeText(this, "RESULT CANCEL", ToastLength.Short).Show();
                        break;
    
                    case Result.Ok:
                        Toast.MakeText(this, "RESULT OK", ToastLength.Short).Show();
                        break;
    
                    case Result.FirstUser:
                    default:
                        break;
                }
            }
        }
    
        private void InitiateClient()
        {
            locationClient = new GoogleApiClient.Builder(this, this, this)
                            .AddApi(LocationServices.API)
                            .Build();
            locationClient.Connect();
        }
        private void InitiateRequests()
        {
            locationRequest = new LocationRequest();
            locationRequest.SetPriority(LocationRequest.PriorityHighAccuracy);
            locationRequest.SetFastestInterval(MIN_TIME_BW_UPDATES / 2);
            locationRequest.SetInterval(MIN_TIME_BW_UPDATES);
    
            LocationSettingsRequest.Builder settingsBuilder = new LocationSettingsRequest.Builder();
            settingsBuilder.AddLocationRequest(locationRequest);
            locationSettingsRequest = settingsBuilder.Build();
        }
        private async Task CheckFusedApiSettings()
        {
            var locationSettingsResult = await LocationServices.SettingsApi.CheckLocationSettingsAsync(locationClient, locationSettingsRequest);
    
            switch (locationSettingsResult.Status.StatusCode)
            {
                case LocationSettingsStatusCodes.Success:
                    Toast.MakeText(this, "SUCCESS", ToastLength.Short).Show();
                    break;
    
                case LocationSettingsStatusCodes.ResolutionRequired:
                    try
                    {
                        locationSettingsResult.Status.StartResolutionForResult(this, REQUEST_CHECK_SETTINGS);
                    }
                    catch (Exception e)
                    {
                        Toast.MakeText(this, "CANCEL: " + e.Message, ToastLength.Short).Show();
                    }
                    break;
    
                default:
                    locationClient.Disconnect();
                    break;
            }
        }
    }
    

    `

  • AlexanderFearAlexanderFear GBMember ✭✭

    Hi. Did you ever resolve this?
    I am having a similar issue with the GoogleSignInAPI via the GooglePlayServices.Auth plugin for Android.
    Even though the sign in has succeeded (as evidenced by my test google account that I log in with receiving access to the WebApp API which is linked to the Project).

  • elefpelefp GRMember ✭✭
    edited May 2017

    @AlexanderFear and rest friends that may have reached this post,

    After 7 months of struggling with this issue, I can post a conclusion. The problem is that Android fails to actually initiate GPS receiver despite displaying that it has done so. As I had explained, the code receives Result.Canceled in OnActivityResult when the users presses Ok. Despite that, the Location setting is activated and its mode is set to "High accuracy". This however is a faulty indication. NOTHING is actually activated !!!! At the same time, the "Scanning always available" setting under WiFi Advanced settings is also activated. This is INDEED so !!!

    The proof for the above comes as follows: If I activate the Location setting myself before starting my app but have WiFi switched off and the "Scanning always available" setting under WiFi Advanced settings off too, then the flow ends in OnActivityResult again and the code receives Result.Ok on a user's Ok hit. Furthermore, if I move on with the implementation and call await LocationServices.FusedLocationApi.RequestLocationUpdates(locationClient, locationRequest, this); then my app starts receiving very accurate coordinates from the Fused API in less than 6 seconds !!!

    So, for some unexplained to me up to now reason, Android fails to actually activate Location through Google native Resolution suggestion mechanism despite displaying that it has succeeded to do so. On the contrary, it succeeds activating "Scanning always available" setting under WiFi Advanced settings.

    I do not know whether this is an Android or a Xamarin problem. I bet on the second and this is so because I've met the code posted above on more than 10 Android related sites written in Java. There was no complain underneath those posts that something goes wrong. I haven't tried myself though in native Java Android. I posted the issue to stackoverflow, but nobody suggested a thing. I even inboxed one of the Xamarin main developers about this issue, but he refused to help saying he had no time to answer all potential requests.

    My workaround is to use a method as the following one to check whether the Location is activated by the user and whether it is set to "High accuracy". If this method returns false, I ask the user to activate Location and make sure s/he sets its mode to "High accuracy" and start the app again. It is definitely NOT the most elegant treatment, but I cannot think of anything else since the obvious is not working!
    private bool IsLocationServiceOn() { bool locationOnHighAccuracy = false, gpsOn = false, networkOn = false; if (googleClientConnected) { LocationManager lm = (LocationManager)ApplicationContext.GetSystemService(Context.LocationService); try { gpsOn = lm.IsProviderEnabled(LocationManager.GpsProvider); networkOn = lm.IsProviderEnabled(LocationManager.NetworkProvider); if (gpsOn && networkOn) locationOnHighAccuracy = true; } catch (Exception locException) { return false; } } return locationOnHighAccuracy; }

    @AlexanderFear I hope the above story gives a hint for your issue as well. Unfortunately I do not have any experience on the specific issue you described to help otherwise. However, I've met quite a few posts in the forum relative to signing-in issues. I wish you just haven't reached all of them yet and the solution is somewhere there. Otherwise, I suppose it's one more bug!

    P.S. I hate this coding editor....

  • OmkarOmkar INMember ✭✭

    Hi @elefp
    I've used code to display an Location setting pop up to enable Location Services. But unfortunately its not working out for me. Actually the issue is, no Alert getting popped up. Also debugger is not hitting OnActivityResult. Can you please help me out. I'm using Xamarin forms and written the code in Xamarin Android MainActivity.cs . I'm testing this application on VS Emulator. Thanks

  • elefpelefp GRMember ✭✭

    Hi @Omkar
    I apologize for the very late reply. I haven't logged on here for quite a while. If you haven't yet solved your issue, post your code here so either me or somebody else helps out. You say you cannot even pop-up the notification for Location changing. This seems strange. There are hundreds of such samples online and it seems that there is actually only one way to achieve that. As far as the OnActivityResult method is concerned, it is reasonable that your debugger never reaches it since the pop-up did never actually pop! OnActivityResult will ONLY be called after user reacts on the pop-up notification.

Sign In or Register to comment.