Widget Common Questions - Geolocation in Embedded Apps

WebView Setup Guidelines

Overview

This document outlines the required configuration for iOS and Android WebViews to properly support geolocation functionality when embedding the Coinme Orchestrator Platform. Improper WebView setup is the most common cause of location-related features failing in embedded environments.

Common Issue: Geolocation Not Working in Embedded Apps

Symptoms:

  • Location-dependent features (like Discover flow) fail to load or fetch data
  • The map displays but location-based searches don't trigger
  • Works in standalone browser but fails in your native app's WebView

Root Cause: WebViews require explicit configuration to enable the JavaScript Geolocation API (navigator.geolocation). Without proper setup, geolocation calls fail silently or throw permission errors, preventing location-dependent features from functioning.


iOS (WKWebView) Setup

Understanding iOS Geolocation in WebViews

iOS WKWebView requires both native app-level permissions AND proper WebView configuration to enable web-based geolocation. The web page uses the JavaScript Geolocation API (navigator.geolocation.getCurrentPosition()), which the WebView must be configured to support.

Required Implementation

1. Add Location Permission to Info.plist

This is mandatory. Without this entry, geolocation requests from the WebView will be silently blocked or hang indefinitely, causing loading indicators in the web application to never complete.

Open your Info.plist file and add one or both of these keys with a user-facing description:

<key>NSLocationWhenInUseUsageDescription</key>
<string>We need your location to find nearby cryptocurrency services and ATMs</string>

Or for background location access:

<key>NSLocationAlwaysAndWhenInUseUsageDescription</key>
<string>We need your location to provide location-based cryptocurrency services</string>

<key>NSLocationWhenInUseUsageDescription</key>
<string>We need your location to find nearby cryptocurrency services</string>

Important Notes:

  • The description string will be shown to users in the permission prompt
  • Be specific about why you need location access
  • Most apps only need "When In Use" permission
  • Without this key, the app will crash when geolocation is requested

2. Request Location Permission at App Level

Your app must request location permission using CLLocationManager before the WebView can access location:

import UIKit
import WebKit
import CoreLocation

class YourViewController: UIViewController, CLLocationManagerDelegate {
    private let locationManager = CLLocationManager()
    private var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Setup location manager
        locationManager.delegate = self
        
        // Request location permission
        // This must be done BEFORE loading the WebView content
        if CLLocationManager.authorizationStatus() == .notDetermined {
            locationManager.requestWhenInUseAuthorization()
        }
        
        setupWebView()
    }
    
    // Optional: Handle authorization changes
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        switch manager.authorizationStatus {
        case .authorizedWhenInUse, .authorizedAlways:
            print("Location permission granted")
        case .denied, .restricted:
            print("Location permission denied")
        case .notDetermined:
            print("Location permission not determined")
        @unknown default:
            break
        }
    }
}

3. Configure WKWebView

func setupWebView() {
    let configuration = WKWebViewConfiguration()
    let preferences = WKWebPreferences()
    
    // Enable JavaScript (required for geolocation)
    preferences.javaScriptEnabled = true
    configuration.preferences = preferences
    
    // Enable inline media playback (recommended)
    configuration.allowsInlineMediaPlayback = true
    
    // Create WebView
    webView = WKWebView(frame: view.bounds, configuration: configuration)
    webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
    view.addSubview(webView)
    
    // Load your URL
    if let url = URL(string: "https://your-coinme-url.com") {
        webView.load(URLRequest(url: url))
    }
}

4. Important: Understanding iOS Geolocation Behavior

When a webpage in WKWebView calls navigator.geolocation.getCurrentPosition():

  1. First time: iOS shows a permission dialog if the app has "When In Use" permission
  2. The dialog will show the webpage's URL (e.g., "https://your-domain.com would like to use your current location")
  3. User must approve this second dialog for the webpage to access location
  4. This permission is remembered per-origin (domain)

Note: This is standard iOS behavior for WKWebView. The webpage-level prompt is separate from the app-level permission and is a security feature to ensure users know which specific website is accessing their location.

5. Complete iOS Example

import UIKit
import WebKit
import CoreLocation

class CoinmeWebViewController: UIViewController, CLLocationManagerDelegate {
    private let locationManager = CLLocationManager()
    private var webView: WKWebView!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        // Setup location manager
        locationManager.delegate = self
        
        // Request permission before setting up WebView
        requestLocationPermission()
        
        // Setup WebView
        setupWebView()
    }
    
    private func requestLocationPermission() {
        let status = CLLocationManager.authorizationStatus()
        
        switch status {
        case .notDetermined:
            // First time - request permission
            locationManager.requestWhenInUseAuthorization()
        case .restricted, .denied:
            // User has denied or restricted location access
            // Consider showing an alert explaining why you need location
            showLocationDisabledAlert()
        case .authorizedWhenInUse, .authorizedAlways:
            // Already authorized
            print("Location access authorized")
        @unknown default:
            break
        }
    }
    
    private func setupWebView() {
        let configuration = WKWebViewConfiguration()
        configuration.preferences.javaScriptEnabled = true
        configuration.allowsInlineMediaPlayback = true
        
        webView = WKWebView(frame: view.bounds, configuration: configuration)
        webView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        view.addSubview(webView)
        
        // Load Coinme Orchestrator Platform
        if let url = URL(string: "https://your-coinme-orchestrator-url.com") {
            webView.load(URLRequest(url: url))
        }
    }
    
    private func showLocationDisabledAlert() {
        let alert = UIAlertController(
            title: "Location Access Disabled",
            message: "Please enable location access in Settings to use location-based features.",
            preferredStyle: .alert
        )
        
        alert.addAction(UIAlertAction(title: "Settings", style: .default) { _ in
            if let settingsURL = URL(string: UIApplication.openSettingsURLString) {
                UIApplication.shared.open(settingsURL)
            }
        })
        
        alert.addAction(UIAlertAction(title: "Cancel", style: .cancel))
        
        present(alert, animated: true)
    }
    
    func locationManagerDidChangeAuthorization(_ manager: CLLocationManager) {
        let status = manager.authorizationStatus
        print("Location authorization status changed: \(status.rawValue)")
    }
}

Android (WebView) Setup

Android WebView setup is more straightforward but still requires specific configuration in multiple places.

Required Implementation

1. Add Permissions to AndroidManifest.xml

Open your AndroidManifest.xml file (typically in app/src/main/AndroidManifest.xml) and add these permissions inside the <manifest> tag but outside the <application> tag:

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.yourcompany.yourapp">

    <!-- Required for WebView to load content -->
    <uses-permission android:name="android.permission.INTERNET"/>

    <!-- Required for geolocation functionality -->
    <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
    <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>

    <application
        android:allowBackup="true"
        android:icon="@mipmap/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme">

        <activity android:name=".MainActivity">
            <!-- Your activity configuration -->
        </activity>

    </application>

</manifest>

Important Notes:

  • INTERNET permission is required for the WebView to load any web content
  • ACCESS_FINE_LOCATION enables GPS-based location (most accurate)
  • ACCESS_COARSE_LOCATION enables network-based location (less accurate, works without GPS)
  • Both location permissions should be included for best compatibility

2. Request Runtime Permissions (Android 6.0+)

Starting with Android 6.0 (API level 23), you must request dangerous permissions at runtime, not just in the manifest. Location is considered a dangerous permission.

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Check if location permission is already granted
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            // Permission already granted, setup WebView
            setupWebView();
        } else {
            // Request permission
            ActivityCompat.requestPermissions(this,
                new String[]{
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION
                },
                LOCATION_PERMISSION_REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String[] permissions,
                                           int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                // Permission granted, setup WebView
                setupWebView();
            } else {
                // Permission denied
                Toast.makeText(this,
                    "Location permission is required for location-based features",
                    Toast.LENGTH_LONG).show();
                // You may still setup WebView, but location features won't work
                setupWebView();
            }
        }
    }

    private void setupWebView() {
        // Implementation in next section
    }
}

3. Configure WebView Settings (CRITICAL)

This is the most important step. Without these settings, geolocation will not work even if you have all permissions granted.

import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;

private void setupWebView() {
    webView = findViewById(R.id.webView);

    // Get WebView settings
    WebSettings settings = webView.getSettings();

    // ==========================================
    // CRITICAL SETTINGS FOR GEOLOCATION
    // ==========================================

    // 1. Enable JavaScript (required for web apps)
    settings.setJavaScriptEnabled(true);

    // 2. Enable Geolocation (MUST BE SET)
    settings.setGeolocationEnabled(true);

    // 3. Enable DOM Storage (required by many web apps)
    settings.setDomStorageEnabled(true);

    // 4. Enable Database (may be needed for geolocation caching)
    settings.setDatabaseEnabled(true);

    // ==========================================
    // RECOMMENDED SETTINGS
    // ==========================================

    // Allow JavaScript to open windows
    settings.setJavaScriptCanOpenWindowsAutomatically(true);

    // Enable zoom controls (optional, but recommended)
    settings.setBuiltInZoomControls(true);
    settings.setDisplayZoomControls(false); // Hide the zoom buttons

    // Use wide viewport (recommended for responsive web apps)
    settings.setUseWideViewPort(true);
    settings.setLoadWithOverviewMode(true);

    // Enable mixed content (if your site uses HTTPS but loads some HTTP resources)
    // Only use if necessary, as it reduces security
    // settings.setMixedContentMode(WebSettings.MIXED_CONTENT_ALWAYS_ALLOW);

    // ==========================================
    // SET WEBCLIENT (handles navigation)
    // ==========================================

    webView.setWebViewClient(new WebViewClient() {
        @Override
        public boolean shouldOverrideUrlLoading(WebView view, String url) {
            // Load URLs within the WebView instead of external browser
            view.loadUrl(url);
            return true;
        }
    });

    // ==========================================
    // SET WEBCHROMECLIENT (REQUIRED FOR GEOLOCATION)
    // ==========================================

    // This is CRITICAL - without this, geolocation will not work
    webView.setWebChromeClient(new WebChromeClient() {
        @Override
        public void onGeolocationPermissionsShowPrompt(
                String origin,
                GeolocationPermissions.Callback callback) {

            // Grant permission to the webpage to use geolocation
            // Since user already granted permission at the app level,
            // we automatically grant it to the webpage

            // Parameters:
            // - origin: The origin of the webpage requesting permission
            // - allow: true to grant permission
            // - retain: false to not remember this decision (ask each time)
            //           true to remember (don't ask again for this origin)

            callback.invoke(origin, true, false);
        }
    });

    // Load the Coinme Orchestrator Platform
    webView.loadUrl("https://your-coinme-orchestrator-url.com");
}

4. Handle WebView Lifecycle

Add these methods to properly handle the back button and WebView lifecycle:

@Override
public void onBackPressed() {
    // Allow user to navigate back in WebView history
    if (webView.canGoBack()) {
        webView.goBack();
    } else {
        super.onBackPressed();
    }
}

@Override
protected void onDestroy() {
    if (webView != null) {
        webView.destroy();
    }
    super.onDestroy();
}

5. Complete Android Example

Here's a complete working example:

package com.yourcompany.yourapp;

import android.Manifest;
import android.content.pm.PackageManager;
import android.os.Bundle;
import android.webkit.GeolocationPermissions;
import android.webkit.WebChromeClient;
import android.webkit.WebSettings;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.widget.Toast;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.app.ActivityCompat;
import androidx.core.content.ContextCompat;

public class MainActivity extends AppCompatActivity {
    private static final int LOCATION_PERMISSION_REQUEST_CODE = 1;
    private WebView webView;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        // Find WebView in layout
        webView = findViewById(R.id.webView);

        // Check and request location permission
        if (ContextCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION)
                == PackageManager.PERMISSION_GRANTED) {
            setupWebView();
        } else {
            ActivityCompat.requestPermissions(this,
                new String[]{
                    Manifest.permission.ACCESS_FINE_LOCATION,
                    Manifest.permission.ACCESS_COARSE_LOCATION
                },
                LOCATION_PERMISSION_REQUEST_CODE);
        }
    }

    @Override
    public void onRequestPermissionsResult(int requestCode,
                                           String[] permissions,
                                           int[] grantResults) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults);

        if (requestCode == LOCATION_PERMISSION_REQUEST_CODE) {
            if (grantResults.length > 0
                    && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
                setupWebView();
            } else {
                Toast.makeText(this,
                    "Location permission is required for location features",
                    Toast.LENGTH_LONG).show();
                setupWebView(); // Still setup, but location won't work
            }
        }
    }

    private void setupWebView() {
        WebSettings settings = webView.getSettings();

        // CRITICAL: Enable these for geolocation to work
        settings.setJavaScriptEnabled(true);
        settings.setGeolocationEnabled(true);
        settings.setDomStorageEnabled(true);
        settings.setDatabaseEnabled(true);

        // Recommended settings
        settings.setJavaScriptCanOpenWindowsAutomatically(true);
        settings.setBuiltInZoomControls(true);
        settings.setDisplayZoomControls(false);
        settings.setUseWideViewPort(true);
        settings.setLoadWithOverviewMode(true);

        // Handle navigation within WebView
        webView.setWebViewClient(new WebViewClient() {
            @Override
            public boolean shouldOverrideUrlLoading(WebView view, String url) {
                view.loadUrl(url);
                return true;
            }
        });

        // CRITICAL: Handle geolocation permission requests from webpage
        webView.setWebChromeClient(new WebChromeClient() {
            @Override
            public void onGeolocationPermissionsShowPrompt(
                    String origin,
                    GeolocationPermissions.Callback callback) {
                // Automatically grant permission since user approved at app level
                callback.invoke(origin, true, false);
            }
        });

        // Load the Coinme Orchestrator Platform
        webView.loadUrl("https://your-coinme-orchestrator-url.com");
    }

    @Override
    public void onBackPressed() {
        if (webView.canGoBack()) {
            webView.goBack();
        } else {
            super.onBackPressed();
        }
    }

    @Override
    protected void onDestroy() {
        if (webView != null) {
            webView.destroy();
        }
        super.onDestroy();
    }
}

6. Layout File (activity_main.xml)

Your layout should include the WebView:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent">

    <WebView
        android:id="@+id/webView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

</RelativeLayout>

Testing Your Implementation

Create a Test Page

Use this simple HTML page to verify geolocation is working before testing with the Coinme Orchestrator Platform:

<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Geolocation Test</title>
    <style>
        body {
            font-family: Arial, sans-serif;
            padding: 20px;
            max-width: 600px;
            margin: 0 auto;
        }
        button {
            background: #007AFF;
            color: white;
            border: none;
            padding: 15px 30px;
            font-size: 16px;
            border-radius: 5px;
            cursor: pointer;
            margin: 10px 0;
        }
        button:active {
            background: #0051D5;
        }
        #result {
            margin-top: 20px;
            padding: 15px;
            background: #f5f5f5;
            border-radius: 5px;
            word-wrap: break-word;
        }
        .success {
            color: green;
        }
        .error {
            color: red;
        }
    </style>
</head>
<body>
    <h1>Geolocation Test</h1>
    <p>Click the button below to test if geolocation is working in your WebView.</p>

    <button onclick="testGeolocation()">Test Geolocation</button>

    <div id="result"></div>

    <script>
        function testGeolocation() {
            const result = document.getElementById('result');

            // Check if geolocation is supported
            if (!navigator.geolocation) {
                result.innerHTML = '<p class="error"><strong>Error:</strong> Geolocation is not supported by this browser/WebView.</p>';
                return;
            }

            result.innerHTML = '<p>Requesting location...</p>';

            // Request current position
            navigator.geolocation.getCurrentPosition(
                // Success callback
                function(position) {
                    result.innerHTML = `
                        <h2 class="success">✓ Success!</h2>
                        <p><strong>Latitude:</strong> ${position.coords.latitude}</p>
                        <p><strong>Longitude:</strong> ${position.coords.longitude}</p>
                        <p><strong>Accuracy:</strong> ${position.coords.accuracy} meters</p>
                        <p><strong>Timestamp:</strong> ${new Date(position.timestamp).toLocaleString()}</p>
                    `;
                },
                // Error callback
                function(error) {
                    let errorMessage = '';

                    switch(error.code) {
                        case error.PERMISSION_DENIED:
                            errorMessage = 'User denied the request for geolocation.';
                            break;
                        case error.POSITION_UNAVAILABLE:
                            errorMessage = 'Location information is unavailable.';
                            break;
                        case error.TIMEOUT:
                            errorMessage = 'The request to get user location timed out.';
                            break;
                        case error.UNKNOWN_ERROR:
                            errorMessage = 'An unknown error occurred.';
                            break;
                    }

                    result.innerHTML = `
                        <h2 class="error">✗ Error</h2>
                        <p><strong>Code:</strong> ${error.code}</p>
                        <p><strong>Message:</strong> ${errorMessage}</p>
                    `;
                },
                // Options
                {
                    enableHighAccuracy: true,
                    timeout: 10000,
                    maximumAge: 0
                }
            );
        }
    </script>
</body>
</html>

Verification Checklist

Use this checklist to verify your implementation:

iOS:

  • NSLocationWhenInUseUsageDescription (or NSLocationAlwaysAndWhenInUseUsageDescription) is present in Info.plist
  • App requests location permission using CLLocationManager.requestWhenInUseAuthorization()
  • WKWebView has JavaScript enabled (preferences.javaScriptEnabled = true)
  • User sees native iOS permission dialog when app first launches
  • User sees webpage permission dialog when geolocation is first accessed in WebView
  • Test page successfully displays latitude/longitude

Android:

  • ACCESS_FINE_LOCATION and ACCESS_COARSE_LOCATION permissions in AndroidManifest.xml
  • INTERNET permission in AndroidManifest.xml
  • Runtime permission request implemented for Android 6.0+
  • setJavaScriptEnabled(true) called on WebView settings
  • setGeolocationEnabled(true) called on WebView settings
  • setDomStorageEnabled(true) called on WebView settings
  • WebChromeClient is set with onGeolocationPermissionsShowPrompt override
  • User sees permission dialog when app first launches
  • Test page successfully displays latitude/longitude

Both Platforms:

  • Test page loads successfully in WebView
  • Clicking "Test Geolocation" button shows success message with coordinates
  • Coinme Orchestrator Platform loads correctly
  • Location-based features (like Discover flow) work as expected

Troubleshooting

iOS Issues

Problem: App crashes when geolocation is requested

  • Solution: Verify NSLocationWhenInUseUsageDescription is in Info.plist. This is mandatory.

Problem: Geolocation times out or fails with "permission denied"

  • Possible causes:
    • User denied location permission at app level → Check Settings > Your App > Location
    • User denied location permission at webpage level → User needs to clear website data and try again
    • Location services are disabled on device → Check Settings > Privacy > Location Services

Problem: Permission prompt never appears

  • Solution: Ensure locationManager.requestWhenInUseAuthorization() is called before loading WebView content

Problem: Second permission prompt (webpage-level) never appears

  • Solution: This is expected behavior for WKWebView. The webpage prompt should appear automatically when navigator.geolocation.getCurrentPosition() is called for the first time. If it doesn't appear, JavaScript may be disabled or there may be an error in the web page code.

Android Issues

Problem: Geolocation fails with "User denied Geolocation"

  • Possible causes:
    • WebChromeClient is not set → Verify setWebChromeClient() is called
    • onGeolocationPermissionsShowPrompt is not overridden → Verify the override exists
    • callback.invoke() is not called → Verify you're calling callback.invoke(origin, true, false)

Problem: JavaScript console shows "navigator.geolocation is undefined"

  • Solution: Ensure setJavaScriptEnabled(true) and setGeolocationEnabled(true) are both called

Problem: Runtime permission dialog never appears

  • Solution:
    • Check that your targetSdkVersion is 23 or higher
    • Verify permission check and request code is being executed
    • Ensure permissions are declared in AndroidManifest.xml

Problem: WebView shows blank screen

  • Possible causes:
    • Missing INTERNET permission in manifest
    • JavaScript is not enabled
    • Network connectivity issues
    • Invalid URL

Problem: Test page shows "Position unavailable" error

  • Solution:
    • Verify device GPS is enabled
    • Ensure device has network connectivity (needed for assisted GPS)
    • Test outside in clear view of sky if indoors
    • Try on a different device to rule out hardware issues

General Issues

Problem: Works in mobile browser but not in WebView

  • Solution: Compare your WebView configuration against this guide point-by-point. Most likely JavaScript or geolocation is not enabled in WebView settings.

Problem: Map shows location but Discover flow doesn't load results

  • Explanation: The map may use IP-based geolocation as a fallback. Verify that the JavaScript Geolocation API actually works using the test page. The Discover flow likely requires the more accurate GPS-based location from navigator.geolocation.

Problem: Works on one platform but not the other

  • Solution: Follow the platform-specific checklist above to identify missing configuration steps.

Problem: Works first time but not after denying permission

  • Solution:
    • iOS: User must clear website data or reset location permissions in Settings > Safari > Advanced > Website Data
    • Android: User must clear app data or reinstall the app to reset the webpage-level permission

Security Considerations

Best Practices

  1. Only request "When In Use" permission unless you genuinely need background location access
  2. Be transparent about why you need location access in your permission description
  3. Handle permission denial gracefully with clear user messaging
  4. Don't request permission unnecessarily - only request when user attempts to use a location feature
  5. Respect user privacy - only use location data for stated purposes

Android Manifest Best Practices

<!-- Use ACCESS_COARSE_LOCATION if you don't need precise GPS -->
<!-- For cryptocurrency ATM location, ACCESS_FINE_LOCATION is appropriate -->
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

<!-- Don't request background location unless truly needed -->
<!-- <uses-permission android:name="android.permission.ACCESS_BACKGROUND_LOCATION"/> -->

WebChromeClient Security Note

The example code automatically grants geolocation permission to any website loaded in the WebView:

callback.invoke(origin, true, false);

If you load multiple different websites in your WebView, you may want to check the origin first:

@Override
public void onGeolocationPermissionsShowPrompt(
        String origin,
        GeolocationPermissions.Callback callback) {

    // Only grant permission to your specific domain
    if (origin.startsWith("https://your-coinme-domain.com")) {
        callback.invoke(origin, true, false);
    } else {
        callback.invoke(origin, false, false);
    }
}

Additional Resources

Documentation Links

Common Error Codes

JavaScript Geolocation Errors:

  • PERMISSION_DENIED (1) - User denied permission
  • POSITION_UNAVAILABLE (2) - Unable to determine position
  • TIMEOUT (3) - Request timed out