Android WebChromeClient WebView onGeolocationPermissionsShowPrompt никогда не срабатывает

У меня есть веб-страница с вызовом WatchPosition, который отлично работает в обычных браузерах. Однако диалоговое окно для запроса разрешения GPS никогда не отображается, когда веб-страница загружается из WebView с помощью WebChromeClient и никогда не вызывается onGeolocationPermissionsShowPrompt.

public class GeoWebChromeClient extends WebChromeClient {
     public void onGeolocationPermissionsShowPrompt(String origin, android.webkit.GeolocationPermissions.Callback callback) {
         Log.d("geolocation permission", "permission >>>"+origin);
         callback.invoke(origin, true, false);
     }
}

 public class GeoWebViewClient extends WebViewClient {

    @Override
    public void onReceivedSslError (WebView view, SslErrorHandler handler, SslError error) {
        handler.proceed();
    }

    public boolean shouldOverrideUrlLoading(WebView view, String url) {
        // When user clicks a hyperlink, load in the existing WebView
        view.loadUrl(url);
        return true;
    }
}

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

    WebView Browser = (WebView) findViewById(R.id.Browser);

    WebSettings webSettings = Browser.getSettings();

    webSettings.setJavaScriptEnabled(true);
    webSettings.setJavaScriptCanOpenWindowsAutomatically(true);
    webSettings.setAppCacheEnabled(true);
    webSettings.setDomStorageEnabled(true);
    webSettings.setGeolocationEnabled(true);

    Browser.setWebViewClient(new GeoWebViewClient());
    Browser.setWebChromeClient(new GeoWebChromeClient());

    Browser.loadUrl("http://192.168.1.102/");


}

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
<uses-permission android:name="android.permission.ACCESS_GPS" />
<uses-permission android:name="android.permission.ACCESS_ASSISTED_GPS" />
<uses-permission android:name="android.permission.ACCESS_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

1 ответ

Решение

onGeolocationShowPrompt на самом деле не показывает само приглашение, это просто метод, который вызывается, когда страница запрашивает ваше геолокацию. Вам необходимо создать собственное приглашение для пользователя, как показано ниже (размещено внутри метода onGeolocatioonShowPrompt):

final boolean remember = true;
AlertDialog.Builder builder = new AlertDialog.Builder(this);
builder.setTitle("Locations");
builder.setMessage(origin + " Would like to use your Current Location").setCancelable(true).setPositiveButton("Allow",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog,
                                        int id) {
                                    // origin, allow, remember
                                    callback.invoke(origin, true, remember);
                                }
                            })
                    .setNegativeButton("Don't Allow",
                            new DialogInterface.OnClickListener() {
                                @Override
                                public void onClick(DialogInterface dialog,
                                        int id) {
                                    // origin, allow, remember
                                    callback.invoke(origin, false, remember);
                                }
                            });
AlertDialog alert = builder.create();
alert.show();

Хорошо, если местоположение отключено и если сайт запрашивает местоположение, то webview вызов onGeolocationPermissionsShowPromptно только один раз. Чтобы заставить это работать, значит позвонитьonGeolocationPermissionsShowPrompt каждый раз, когда сайт запрашивал местоположение, я делал это:

inner class MyChromeClient: WebChromeClient()
    {

        override fun onGeolocationPermissionsShowPrompt(origin: String?, callback: GeolocationPermissions.Callback?) {
            // Geolocation permissions coming from this app's Manifest will only be valid for devices with API_VERSION < 23.
            // On API 23 and above, we must check for permission, and possibly ask for it.
            //callback?.invoke(origin,true,false)

            val permission=Manifest.permission.ACCESS_FINE_LOCATION

            if (Build.VERSION.SDK_INT<Build.VERSION_CODES.M || ContextCompat.checkSelfPermission(applicationContext,permission)==PackageManager.PERMISSION_GRANTED)
            {
                // we're on SDK < 23 OR user has already granted permission
                callback?.invoke(origin,true,false)
            }
            else{

                if (!ActivityCompat.shouldShowRequestPermissionRationale(this@WebViewActivity,permission))
                {
                    // user clicked on don't asked again
                    alert("Allow location permission to access this feature"){
                        yesButton {
                            val intent=Intent()
                            intent.action = Settings.ACTION_APPLICATION_DETAILS_SETTINGS
                            intent.data= Uri.fromParts("package",packageName,null)
                            startActivity(intent)
                            callback?.invoke(origin,false,false)
                        }
                        noButton {
                            callback?.invoke(origin,false,false)
                        }
                    }.show()
                }
                else{
                    // permission not granted yet
                    this@WebViewActivity.callback=callback
                    this@WebViewActivity.origin=origin
                    ActivityCompat.requestPermissions(this@WebViewActivity, arrayOf(permission),100)
                }
            }
        }
    }

Добавьте код onRequestPermissionsResult:

override fun onRequestPermissionsResult(requestCode: Int, permissions: Array<out String>, grantResults: IntArray) {
        super.onRequestPermissionsResult(requestCode, permissions, grantResults)
        if (grantResults.isNotEmpty() && requestCode==100)
        {
            if (grantResults[0]==PackageManager.PERMISSION_GRANTED)
            {
                if (callback!=null)
                    callback?.invoke(origin,true,false)
                return
            }
            else{
                callback?.invoke(origin,false,false)
            }
        }
        callback?.invoke(origin,false,false)
    }

Дело в том, что если вы этого хотите onGeolocationPermissionsShowPrompt должен позвонить снова, тебе нужно позвонить callback?.invoke(origin,false,false), с этим точным значением в параметре внутри onGeolocationPermissionsShowPrompt

Это должно помочь всем, кто ищет, как исправить сообщение "onGeolocationPermissionsShowPrompt никогда не используется", как я. Если это ваша проблема, не имеет значения, что помещено в метод, если он никогда не вызывается.

В вашем onCreate:

webView = findViewById(R.id.webView);
webView.setWebViewClient(new customWebView());
webView.setWebChromeClient(new customChromeClient());

Пользовательские классы:

private class customChromeClient extends WebChromeClient {
    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);

        //check for permissions or show your dialog etc
    }
}

//other methods you may want to override
private class customWebView extends WebViewClient {
    @Override
    public void onPageFinished(WebView view, String url) {

    }

    @Override
    public boolean shouldOverrideUrlLoading(WebView webView, String url) {
        return true;
    }
}

Надеюсь, это поможет кому-то в будущем.

Пример и где я нашел ответ:https://gist.github.com/Cheesebaron/ad84740c9bffa7e255c8

Другие вопросы по тегам