我正在尝试访问在Android WebView中可用的HTML Geolocation API(使用SDK版本24)。
主要问题是,JavaScript中调用navigator.geolocation.getCurrentPosition()
从不返回(无论是错误还是位置数据),而在应用程序端,我检查权限并正确地将其传递给WebView,使用android.webkit.GeolocationPermissions.Callback
类。
更新:这里需要澄清的是,“从不返回”的意思是指两个提供的回调函数navigator.geolocation.getCurrentPosition(success, error)
都没有被调用。
在我构建的一个用于测试此问题的示例应用程序中(只有一个小活动托管WebView),我在清单中声明了权限,并在应用启动时正确请求了它们。我看到提示框,可以授予或拒绝位置信息权限。
清单:
<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帮助页面,此处略有删减):
function geoFindMe() {
function success(position) {}
function error() {}
navigator.geolocation.getCurrentPosition(success, error);
}
我的观察是,JavaScript中的navigator.geolocation.getCurrentPosition(success, error)
调用从未返回。我注意到Java中的onGeolocationPermissionsShowPrompt()
方法被正确地调用,并且我在那里检查权限时始终获得结果0,即PackageManager.PERMISSION_GRANTED
,因此每次调用都会执行callback.invoke(origin, true, true)
。如果我尝试几次,我就能看到我的Java代码多次调用。然而,在我调用invoke()
之后,JavaScript这方面仍然没有任何反应。
我添加了检查授予权限的代码,使用了在GeolocationPermissions
类中调用getOrigins(ValueCallback<Set<String>> callback)
,如文档这里所述。我在回调中看到我的来源已被允许请求位置(它们被列在集合中)。
有什么想法可能出了问题?