How to get HTML5 position in WebView updated at a regular interval (with FINE_ACCURACY)
I've found that phones (at least with iPhones) usually need three checks to get an accurate reading, almost as if they are triangulating the position. The problem, as you have discovered, is that each new call to getCurrentPosition()
seems to start "blind", so it doesn't get any more accurate (results vary when you're running this function on a desktop/laptop).
The solution is geolocation.watchPosition()
. That function uses previous calls to improve accuracy. After about five seconds, it's as accurate as it's going to get (if you're not moving), so you stop checking. Also, it will stop checking any time it thinks it won't get any more accurate. Use window.setTimeout()
to control the interval.
Demo: http://jsfiddle.net/ThinkingStiff/yn3Bq/
HTML:
<div id="result"></div>
Script:
var latitude, longitude, accuracy;
function setGeolocation() {
var geolocation = window.navigator.geolocation.watchPosition(
function ( position ) {
latitude = position.coords.latitude;
longitude = position.coords.longitude;
accuracy = position.coords.accuracy;
document.getElementById( 'result' ).innerHTML +=
'lat: ' + latitude + ', '
+ 'lng: ' + longitude + ', '
+ 'accuracy: ' + accuracy + '<br />';
}, function () {
/*error*/
}, {
maximumAge: 250,
enableHighAccuracy: true
}
);
window.setTimeout( function () {
window.navigator.geolocation.clearWatch( geolocation )
},
5000 //stop checking after 5 seconds
);
};
setGeolocation();
window.setTimeout( function () {
setGeolocation();
},
30000 //check every 30 seconds
);
Output:
lat: 35.5830119, lng: -124.4871223, accuracy: 40
lat: 35.5829974, lng: -124.4871525, accuracy: 30
Android Webview: navigator.geolocation API is not working, throwing exception POSITION_UNAVAILABLE
Let's check the permission code the issue is in calling of it. and I don't know why you're calling permission in this way as, we've lot of mediums by which you can easily call it. Let's use nabinbhandari/Android-Permissions it's easy to use.
Call in this way:
@Override
protected void onCreate(Bundle savedInstanceState) {
.....................
String[] permissions = {Manifest.permission.ACCESS_FINE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION};
Permissions.check(this/*context*/, permissions, null/*rationale*/, null/*options*/, new
PermissionHandler() {
@Override
public void onGranted() {
// call your task
// webview initilization
webView = (WebView) findViewById(R.id.webview);
webView.setWebViewClient(new GeoWebViewClient());
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setAppCacheEnabled(false);
webView.getSettings().setDatabaseEnabled(true);
webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setGeolocationEnabled(true);
/// Below required for geolocation
webView.setWebChromeClient(new GeoWebChromeClient());
webView.getSettings().setGeolocationDatabasePath(getFilesDir().getPath());
webView.loadUrl("<my_webapp_url>");
}
@Override
public void onDenied(Context context, ArrayList<String> deniedPermissions) {
// permission denied, block the feature.
Toast.makeText(this,"Permission denied",Toast.LENGTH_SHORT);
}
});
Or implement these permission overrides function on basis of your need.
Android WebView using GeolocationPermissions
It is rather simple when the html is your own. There are a couple of ways, I will give you 2 of them.
Simple way using GET
Idea is to send the location in the URL (you might need some encoding but as long as it's only numbers and no spaces you are fine
Some editing for your shouldOverridUrlLoading
public boolean shouldOverrideUrlLoading(WebView view, String url){
if (url.needs_geo) //meaning if this is the url that needs the geo location
url += "?geo=" + your_location;
view.loadUrl(url);
return true;
}
In your JavaScript:
function getParam(name)
{
name = name.replace(/[\[]/,"\\\[").replace(/[\]]/,"\\\]");
var regexS = "[\\?&]"+name+"=([^]*)";
var regex = new RegExp( regexS );
var results = regex.exec( window.location.href );
if( results == null )
return "";
else
return results[1];
}
then
var geo_location = getParam('geo');
Using WebView.addJavascriptInterface
(I have never tried to pass values from Java to JavaScript but will probably work as well). The idea is to provide for your JavaScript a Java class that can be accessed to get the parameters you want to pass to JavaScript.
Inside your Activity class:
public String location; //as an example
public class SherifJS {
public String getLocation(){
return location;
}
}
//bla bla
SherifJS loc = new SherifJS();
yourWebView.addJavascriptInterface(loc, "locationProvider");
Inside your JavaScript:
<script type="text/javascript">
<!--
function sherifJS() {
document.getElementById("locationHolder").innerHTML =
window.locationProvider.getLocation();
}
-->
</script>
Android WebView utilizing Camera and GPS
It might be a bit late, but just in case I will give you an example to do that.
(Camera)
1////add this to your webChromeClient
myWebView.setWebChromeClient(new WebChromeClient()
{
public void openFileChooser( ValueCallback<Uri> uploadMsg, String acceptType )
{
mUploadMessage = uploadMsg;
Intent cameraIntent = new Intent("android.media.action.IMAGE_CAPTURE");
Calendar cal = Calendar.getInstance();
cal.getTime();
SimpleDateFormat sdf = new SimpleDateFormat("HHmmss");
File photo = new File(Environment.getExternalStorageDirectory(), sdf.format(cal.getTime()) +".jpg");
cameraIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(photo));
picUri = Uri.fromFile(photo);
startActivityForResult(cameraIntent, TAKE_PICTURE);
}
});
2///add this function
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data)
{
switch(requestCode)
{
case TAKE_PICTURE:
if(resultCode == Activity.RESULT_OK)
{
Uri mypic = picUri;
mUploadMessage.onReceiveValue(mypic);
mUploadMessage = null;
}
else
{
mUploadMessage.onReceiveValue(null);
mUploadMessage = null;
return;
}
default:
{
return;
}
}
}
3// and the HTML looks like this
<input type="file" id="files" name="files" accept="image/*" capture="camera" >
The above code will open the native camera app.
P.S. This is a mix of code from different sources.
Related Topics
How to Stack Firebase Cloud Messaging Notifications When the Application Is Not Running
Android-Textview Settext in HTML.Fromhtml to Display Image and Text
Integrating Video File in Android App as App Background
Attempt to Reopen an Already-Closed Object SQLitedatabase
Getting Net::Err_Unknown_Url_Scheme While Calling Telephone Number from HTML Page in Android
Android App Installation Failed: Package Com.My.App Has No Certificates at Entry Androidmanifest.Xml
How to Setup Alertbox from Broadcastreceiver
Intercept and Override Http Requests from Webview
Vectordrawablecompat Resources$Notfoundexception on Kitkat and Below
How to Load The Listview "Smoothly" in Android
How to Filter Listview Using Getfilter() in Baseadapter
Onitemclicklistener and Onclicklistener Not Working for Listview
Android Studio - Processdebugresources Failed
Play-Services-Ads Conflicts with Appcompat
Disable Android Browser's Input Overlays
How to Update Google Play Services for Android Studio 2.2 Emulators