Android WebView using GeolocationPermissions
I’ve looked at the various questions regarding this problem on here such as:
- Using navigator.geolocation.getCurrentPosition in WebView on Android 2.0+ (PhoneGap related)
- android webview geolocation
- Android: Using html5 to determine geolocation in webview with javascript api
But I’m still a bit confused, I know that I am supposed to create my own class from the abstract class WebChromeClient
. Which gets the location, but how exactly from there does this object send the webView
the geolocation/how do they communicate?
Here is my code: (is this at least on the right track?)
import android.app.Activity;
import android.app.AlertDialog;
import android.content.Intent;
import android.net.Uri;
import android.os.Bundle;
import android.util.Log;
import android.view.KeyEvent;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.webkit.GeolocationPermissions.Callback;
import android.webkit.JsResult;
import android.webkit.WebChromeClient;
import android.webkit.WebView;
import android.webkit.WebViewClient;
import android.webkit.GeolocationPermissions;
public class site extends Activity {
WebView engine;
/** Called when the activity is first created. */
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
WebViewClient yourWebClient = new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
if (url.contains("tel:") == true) {
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse(url));
startActivity(intent);
}
else if(url.contains("visitchicagosouthland") == true) {
view.loadUrl(url);
}
//Here is where I create my object, I did this because I only need the location when this
//page is loaded. Could this be part of the problem?
else if(url.contains("directions.cfm") == true) {
GeoClient geo = new GeoClient();
engine.setWebChromeClient(geo);
String origin = ""; //how to get origin in correct format?
Callback call = null;
geo.onGeolocationPermissionsShowPrompt(origin, call );
}
else {
/*Intent browserIntent = new Intent(Intent.ACTION_VIEW, Uri.parse("url"));
startActivity(browserIntent);*/
}
return true;
}
};
engine = (WebView) findViewById(R.id.web_engine);
engi开发者_运维知识库ne.getSettings().setJavaScriptEnabled(true);
engine.getSettings().setBuiltInZoomControls(true);
engine.getSettings().setSupportZoom(true);
engine.getSettings().setJavaScriptCanOpenWindowsAutomatically(true);
engine.getSettings().setGeolocationEnabled(true);
engine.setWebViewClient(yourWebClient);
engine.setScrollBarStyle(WebView.SCROLLBARS_OUTSIDE_OVERLAY);
engine.loadUrl("http://www.visitchicagosouthland.com/jrudnydev/phone/");
}
@Override
public boolean onCreateOptionsMenu(Menu menu) {
MenuInflater inflater = getMenuInflater();
inflater.inflate(R.menu.home, menu);
return true;
}
@Override
public boolean onKeyDown(int keyCode, KeyEvent event) {
if ((keyCode == KeyEvent.KEYCODE_BACK) && engine.canGoBack()) {
engine.goBack();
return true;
}
return super.onKeyDown(keyCode, event);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
// Handle item selection
if(item.getItemId() == R.id.home) {
engine.loadUrl("http://www.visitchicagosouthland.com/mobile/");
return true;
}
else if(item.getItemId() == R.id.refresh) {
engine.reload();
return true;
}
else if(item.getItemId() == R.id.stop) {
engine.stopLoading();
return true;
}
else {
return super.onOptionsItemSelected(item);
}
}
}
final class GeoClient extends WebChromeClient {
@Override
public void onProgressChanged(WebView view, int progress) {
// Activities and WebViews measure progress with different scales.
// The progress meter will automatically disappear when we reach 100%
//Activity.setProgress(progress * 100);
}
@Override
public boolean onJsAlert(WebView view, String url, String message, JsResult result) {
//Log.d(LOG_TAG, message);
// This shows the dialog box. This can be commented out for dev
AlertDialog.Builder alertBldr = new AlertDialog.Builder(null);
alertBldr.setMessage(message);
alertBldr.setTitle("Alert");
alertBldr.show();
result.confirm();
return true;
}
@Override
public void onGeolocationPermissionsShowPrompt(String origin, Callback callback) {
// TODO Auto-generated method stub
super.onGeolocationPermissionsShowPrompt(origin, callback);
callback.invoke(origin, true, false);
}
}
my android-manifest.xml:
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.visitchicagosouthland"
android:versionCode="1"
android:versionName="1.0">
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_FINE_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_COARSE_LOCATION" />
<application android:icon="@drawable/icon" android:label="@string/app_name">
<activity android:name=".site"
android:label="@string/app_name"
android:theme="@android:style/Theme.NoTitleBar">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="4" />
</manifest>
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>
精彩评论