gpt4 book ai didi

javascript - navigator.geolocation.getCurrentPosition() 在 Android 上的 WebView 中永远不会返回

转载 作者:IT老高 更新时间:2023-10-28 23:24:31 26 4
gpt4 key购买 nike

我正在尝试访问 Android WebView 中可用的 HTML Geolocation API(使用 SDK 版本 24)。

主要问题是 navigator.geolocation.getCurrentPosition() 的调用在 JavaScript 中永远不会返回(既没有错误,也没有位置数据),而在应用程序端,我检查权限并使用 android.webkit.GeolocationPermissions.Callback 正确地将它们传递给 WebView类。

更新:在这里澄清一下,“永不返回”是指两个提供的回调都没有 navigator.geolocation.getCurrentPosition(success, error)曾经被调用过。

在我构建的一个示例应用程序中(只有一个托管 WebView 的小 Activity )我在 list 中声明权限并在应用程序启动时正确请求它们。我看到提示,可以授予或拒绝位置信息的权限。

list :

<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" />

主窗体中的代码:

public boolean checkFineLocationPermission() {
if (ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION)
!= PackageManager.PERMISSION_GRANTED) {

if (ActivityCompat.shouldShowRequestPermissionRationale(this,
Manifest.permission.ACCESS_FINE_LOCATION) && !mIsPermissionDialogShown) {
showPermissionDialog(R.string.dialog_permission_location);
} else {
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION},
PERMISSION_ACCESS_FINE_LOCATION);
}
return false;
} else {
return true;
}
}

我可以在运行时使用 Context.checkSelfPermission() 检查权限我看到我的应用程序获得了相应的权限。

然后我尝试在 WebView 中打开一个网页控制。我在设置中启用了所有必需的选项:

    mWebSettings.setJavaScriptEnabled(true);
mWebSettings.setAppCacheEnabled(true);
mWebSettings.setDatabaseEnabled(true);
mWebSettings.setDomStorageEnabled(true);
mWebSettings.setGeolocationEnabled(true);
mWebSettings.setJavaScriptCanOpenWindowsAutomatically(true);
mWebSettings.setSupportZoom(true);

我使用以下 WebChromeClient处理来自 JavaScript 的地理定位请求的重载:

protected class EmbeddedChromeClient extends android.webkit.WebChromeClient {
@Override
public void onGeolocationPermissionsShowPrompt(String origin,
android.webkit.GeolocationPermissions.Callback callback) {

// do we need to request permissions ?
if (ContextCompat.checkSelfPermission(EmbeddedBrowserActivity.this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
// this should never happen, it means user revoked permissions
// need to warn and quit?
callback.invoke(origin, false, false);
}
else {
callback.invoke(origin, true, true);
}
}
}

为了测试这一点,我使用了以下代码(取自 Mozilla API help page,在此处缩短):

function geoFindMe() {
function success(position) {}
function error() {}
navigator.geolocation.getCurrentPosition(success, error);
}

我看到的是 navigator.geolocation.getCurrentPosition(success, error) 的调用在 JavaScript 中永远不会返回。我看到 onGeolocationPermissionsShowPrompt() Java 中的方法被正确调用,当我在那里检查权限时,我总是得到结果 0,即 PackageManager.PERMISSION_GRANTED , 所以 callback.invoke(origin, true, true)在每次调用时执行。如果我尝试多次,我会看到对我的 Java 代码的多次调用。尽管如此,在我调用 invoke() 之后,JavaScript 端没有任何反应。 .

我添加了代码以使用 getOrigins(ValueCallback<Set<String>> callback) 的调用检查授予的权限在 GeolocationPermissions类,如 here in the documentation 所述.我在回调中看到允许我的来源请求位置(它们在集合中列出)。

你有什么想法吗?

最佳答案

尝试使用选项设置超时(source):

var options = {
enableHighAccuracy: true,
timeout: 10000,
maximumAge: 0
};

navigator.geolocation.getCurrentPosition(success, error, options);

如果失败,则尝试覆盖 getCurrentPosition (source):

(function() {

if (navigator.geolocation) {
function PositionError(code, message) {
this.code = code;
this.message = message;
}

PositionError.PERMISSION_DENIED = 1;
PositionError.POSITION_UNAVAILABLE = 2;
PositionError.TIMEOUT = 3;
PositionError.prototype = new Error();

navigator.geolocation._getCurrentPosition = navigator.geolocation.getCurrentPosition;

navigator.geolocation.getCurrentPosition = function(success, failure, options) {
var successHandler = function(position) {
if ((position.coords.latitude == 0 && position.coords.longitude == 0) ||
(position.coords.latitude == 37.38600158691406 && position.coords.longitude == -122.08200073242188))
return failureHandler(new PositionError(PositionError.POSITION_UNAVAILABLE, 'Position unavailable'));

failureHandler = function() {};
success(position);
}

var failureHandler = function(error) {
failureHandler = function() {};
failure(error);
}

navigator.geolocation._getCurrentPosition(successHandler, failureHandler, options);

window.setTimeout(function() { failureHandler(new PositionError(PositionError.TIMEOUT, 'Timed out')) }, 10000);
}
}
})();

作为第三个选项,在 EmbeddedChromeClient 中使用 @JavascriptInterface (source) 进行注释

还要在代码中的适当位置添加:

mWebSettings.setJavaScriptEnabled(true);
//...
mWebSettings.setSupportZoom(true);
webView.addJavascriptInterface(new EmbeddedChromeClient(webView), "injectedObject");
webView.loadData("html here", "text/html", null);

最后一个选项只是在html中使用标签,从磁盘存储中加载html,在调用函数中替换标签,在webView中加载html/string。我之前在 Android 中使用过这种方法,因为定位让我感到非常沮丧。那么你也不必担心https。

关于javascript - navigator.geolocation.getCurrentPosition() 在 Android 上的 WebView 中永远不会返回,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/51716528/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com