Search code examples
javascriptjavaw3c-geolocation

Wait for a function to end


I have this code:

function getLocation() {
  //function executed if started by webview
  if (typeof Jinterface != 'undefined') {
    Jinterface.displayGPSRequest();
  }

  if (navigator.geolocation) {
    navigator.geolocation.getCurrentPosition(showPosition, showError, {
      enableHighAccuracy: true
    });
  } else {
    alert("Geolocation is not supported by this browser.");
  }
}

I need JavaScript to wait for the function Jinterface.displayGPSRequest() to end before continuing with the code. I tried async/await but being the function called from a Java file in Android Studio (where I’ve got a webview of my site) I can’t name it with async statement because Java doesn’t recognise it. Any help?

Java function:

 @JavascriptInterface
    public void displayGPSRequest() {
        Context context = getApplicationContext();
        GoogleApiClient googleApiClient = new GoogleApiClient.Builder(context)
                .addApi(LocationServices.API).build();
        googleApiClient.connect();
        final String TAG = "YOUR-TAG-NAME";
        final int REQUEST_CHECK_SETTINGS = 0x1;

        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(TAG, "All location settings are satisfied.");
                        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(MainActivity.this, 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;
                }
            }
        });
    }

Solution

  • displayGPSRequest will need to provide a means of knowing when it finishes. If it doesn't currently, you'll need to edit it to add one (or use polling, which isn't a good idea).

    The usual ways are:

    1. Via a promise.

    2. Via a raw callback.

    So if displayGPSRequest returns a promise (or you edit it to):

    JInterface.displayGPSRequest()
        .then(function() {
            // The code that should run when it finishes
        })
        .catch(function() {
            // It failed
        });
    

    If displayGPSRequest uses a raw callback (or you edit it to), then:

    JInterface.displayGPSRequest(function() {
        // The code that should run when it finishes
        // It should also have some way of telling the callback it failed
    });
    

    If it doesn't provide a means of notifying you when it finishes and you can't add one, you'd have to use polling for some side-effect it produces, which is very much a last-resort situation:

    var timer = setInterval(function() {
        if (/*...the side effect is present and so you know it's done..*/) {
            clearInterval(timer);
            timer = 0;
            // The code that should run when it finishes
        }
    }, 100); // 100ms = ten times a second, adjust as appropriate
    setTimeout(function() {
        if (timer) {
            // Give up
            clearInterval(timer);
            timer = 0;
        }
    }, 5000); // 5000ms = five seconds