4

I'm just playing with Appcelerator's Titanium platform for developing mobile apps.

My test application just opens a webview pointing to an online web page. This page uses the W3C Geolocation API to get user's location.

This are my tiapp.xml specific android permissions:

<android xmlns:android="http://schemas.android.com/apk/res/android">
    <manifest>
        <uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
        <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
        <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
        <uses-permission android:name="android.permission.INTERNET"/>
        <uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
        <uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
        <uses-permission android:name="android.permission.ACCESS_LOCATION_EXTRA_COMMANDS"/>
    </manifest>
</android>

This is my javascript code for getting coords:

if (navigator.geolocation) {

    navigator.geolocation.getCurrentPosition(function(position){

        $("#results").append('Longitude: ' + position.coords.longitude + '<br/>');
        $("#results").append('Latitude: ' + position.coords.latitude + '<br/>');

    }, function(error){

        $("#results").append('An error ocurred ' + error.message);
    });

} else {

    $("#results").append('Geolocation not supported');
}

It seems that navigator.geolocation and navigator.geolocation.getCurrentPosition are defined but delegate's are not executed anyway.

The question is: how to get this working? :-)

Thanks in advance.

Update: I found that the problem seems that Android 2.x webview has it's own implementation of navigator.geolocation. According to this commit on phonegap's source code.

Update 2: I wrote a very small full-native android application that opens a webclient to same webpage and works fine:

package com.sourcerebels;

import android.app.Activity;
import android.os.Bundle;
import android.webkit.GeolocationPermissions.Callback;
import android.webkit.WebChromeClient;
import android.webkit.WebView;

class MyClient extends WebChromeClient {

    @Override
    public void onGeolocationPermissionsShowPrompt(String origin,
            Callback callback) {
        callback.invoke(origin, true, false);
    }
}

public class TestWebClient extends Activity {

    WebView webView;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        webView = (WebView) findViewById(R.id.webView1);
        webView.getSettings().setJavaScriptEnabled(true);
        webView.getSettings().setGeolocationDatabasePath("/data/data/testWebClient");
        webView.loadUrl("http://www.sourcerebels.com/index2.html");

        webView.setWebChromeClient(new MyClient());
    }
}

Update 3: I found this source from appcelerator's github site: https://github.com/appcelerator/titanium_mobile/blob/master/android/modules/ui/src/ti/modules/titanium/ui/widget/webview/TiWebChromeClient.java

sourcerebels
  • 5,140
  • 1
  • 32
  • 52

3 Answers3

4

Titanium's strongest aspect is that it is Native Code on each platform. By using the webview you are greatly avoiding the Native Code advantage.

http://wiki.appcelerator.org/display/guides/Using+Location+services

http://wiki.appcelerator.org/display/guides/HTML5+vs+Native+UI

In the section titled When To Use HTML it states the following:

"HTML should be avoided as much as possible.Almost everything you need it can be done using native code. The app will load faster and will react faster to the user's actions leading to a better user experience."

Going by those standards I would advise you to get the location and then create or update a webview. As for why the javascript isn't working I don't have an answer because a full DOM is loaded when you create a webview?

rivenate247
  • 2,116
  • 2
  • 16
  • 18
  • Thanks for your response. I agree with you, but we have some legacy webapps working with W3C Geolocation API and there are no plans and $ at the moment for rewrite. We want to develop a native interface to access some existing webapps. – sourcerebels May 09 '11 at 07:40
  • Have you tested you're code in the main Android browser rather then a webview? – rivenate247 May 09 '11 at 07:45
  • Also it seems only 2.* supports this in Android through W3C, else you'll need to use GEARS for 1.6+ http://stackoverflow.com/questions/1349064/which-devices-support-javascript-geolocation-via-navigator-geolocation/2864314#2864314 http://textopiablog.wordpress.com/2010/05/07/cross-platform-locative-media/ – rivenate247 May 09 '11 at 07:53
  • My "server" code is working well in main Android Browser 2.x. The problem seems to be with webview. – sourcerebels May 09 '11 at 08:33
3

Finally I solved this "issue" by modifying TiWebChromeClient.java from Titanium mobile SDK sources, and generating a new titanium-ui.jar file.

Added this code and now I can use geolocation on Android webView:

import android.webkit.GeolocationPermissions.Callback;

...

    @Override
    public void onGeolocationPermissionsShowPrompt(String origin,
            Callback callback) {
        callback.invoke(origin, true, false);
    }
sourcerebels
  • 5,140
  • 1
  • 32
  • 52
  • Impressive! I wonder why they exclude it in the webview... possibly to load the DOM with less elements thus faster? – rivenate247 May 09 '11 at 17:01
1

Our solution is as follows:

import android.webkit.GeolocationPermissions;

    // enable navigator.geolocation 
    mWebView.getSettings().setGeolocationEnabled(true);
    mWebView.getSettings().setGeolocationDatabasePath("/data/data/databases/");


    // START Allow Geolocation prompt
    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
    }
sourcerebels
  • 5,140
  • 1
  • 32
  • 52
Kazuko Ando
  • 207
  • 4
  • 17