Android: Using HTML5 to Determine Geolocation in Webview with JavaScript API

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



Leave a reply



Submit