Android webview geoposition database failed to open
Asked Answered
C

3

12

I have website using javascript geolocation api and want it to open in a webview. I set up these permissions in the manifest file:

<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"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

In my activity, I also set webview settings:

webview.getSettings().setDatabaseEnabled(true);
webview.getSettings().setDomStorageEnabled(true);
webview.getSettings().setGeolocationDatabasePath("/data/data/com.my.app/databases");
webview.getSettings().setGeolocationEnabled(true);

And I also handled javascript geolocation dialog:

webview.setWebChromeClient(new WebChromeClient(){
    @Override
    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
    }
});

Geolocation itself is working, but I am not able to cache geoposition into the database. It should be doing it by itself into CachedGeoposition.db, but when I start the webview, i get this strange SQLite error:

E/SQLiteLog(22653): (14) cannot open file at line 30174 of [00bb9c9ce4]
E/SQLiteLog(22653): (14) os_unix.c:30174: (2) open(/CachedGeoposition.db) -
D/WebKit  (22653): ERROR:
D/WebKit  (22653): SQLite database failed to load from /CachedGeoposition.db
D/WebKit  (22653): Cause - unable to open database file
D/WebKit  (22653):
D/WebKit  (22653): external/webkit/Source/WebCore/platform/sql/SQLiteDatabase.cp
p(71) : bool WebCore::SQLiteDatabase::open(const WTF::String&, bool)

When I check existence of CachedGeoposition.db file in File Explorer, it is always there, and permissions of the db are set to -rw-------.

Did I miss something in settings what could cause database not to open correctly? I'm new to Android and trying to find solution for 2 days now. Any help would be greatly appreciated. Thank you.

Cover answered 16/8, 2012 at 9:25 Comment(1)
check this answer #12802190Anu
A
2

I'll post a solution that worked for me in the hope that it might provide some ideas on where the error might be. It would also help if you could provide details about the device(emulator)/os on which you're testing.

I tested on (with no errors):

  • (Emulator) Galaxy Nexus (2.3.3) (data/data/package.name/files/CachedGeoposition.db file created)
  • (Emulator) Galaxy Nexus (3.0) (data/data/package.name/files/CachedGeoposition.db file created)
  • HTC One S (4.1.1) (data/data/package.name/files/CachedGeoposition.db file created)
  • Galaxy S3 (4.3) (couldn't see the file since my phone is not rooted and there are some 'run-as' bugs on 4.3)
  • Nexus 7 (4.4.4) - the webview above KIT KAT has changed a bit and the file is no longer there, but no error was shown (even when providing a wrong 'databases' folder path)
  • (Emulator) Galaxy S4 (5.0) (same as on 4.4.4)

AndroidManifest permissions (pretty much the same):

<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"/>
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>

Web view settings:

WebSettings webSettings = webview.getSettings();
webSettings.setJavaScriptEnabled(true);
webSettings.setDatabaseEnabled(true);
webSettings.setDomStorageEnabled(true);
webSettings.setGeolocationDatabasePath(getFilesDir().getPath());
webSettings.setGeolocationEnabled(true);

Web chrome client (the same):

webview.setWebChromeClient(new WebChromeClient(){
    @Override
    public void onGeolocationPermissionsShowPrompt(String origin, GeolocationPermissions.Callback callback) {
        callback.invoke(origin, true, false);
    }
});

Test html file for getting the geolocation:

<!DOCTYPE html>
<html>
<head>
<script>
var x = document.getElementById("demo");

function getLocation() {
    if (navigator.geolocation) {
        navigator.geolocation.getCurrentPosition(showPosition, showError);
    } else {
        x.innerHTML = "Geolocation is not supported by this browser.";
    }
}

function showPosition(position) {
    var latlon = position.coords.latitude + "," + position.coords.longitude;
    document.getElementById("locationHolder").innerHTML = latlon;
}

function showError(error) {
    switch(error.code) {
        case error.PERMISSION_DENIED:
            x.innerHTML = "User denied the request for Geolocation.";
            break;
        case error.POSITION_UNAVAILABLE:
            x.innerHTML = "Location information is unavailable";
            break;
        case error.TIMEOUT:
            x.innerHTML = "The request to get user location timed out.";
            break;
        case error.UNKNOWN_ERROR:
            x.innerHTML = "An unknown error occurred.";
            break;
    }
}
</script>
</head>

<body>

<p id="demo">Click the button to get your position.</p>

<div id="locationHolder">No location</div>
<button onclick="getLocation()">Get position</button>

</body>
</html>

Also, for a local test, you could created a file containing the html under '/assets/www/index.html' and use the following code to load it into the webview:

try {
    String html = readAssetFile("www/index.html");
    webview.loadDataWithBaseURL(null, html, "text/html", "UTF-8", null);
} catch (IOException e) {
}

Read asset file method:

private String readAssetFile(String filePath) throws IOException {
    StringBuilder buffer = new StringBuilder();
    InputStream fileInputStream = getAssets().open(filePath);
    BufferedReader bufferReader = new BufferedReader(new InputStreamReader(fileInputStream, "UTF-8"));
    String str;

    while ((str=bufferReader.readLine()) != null) {
        buffer.append(str);
    }
    fileInputStream.close();

    return buffer.toString();
}

I couldn't reproduce your error without providing a wrong hardcoded path to the 'databases' folder.

Almena answered 26/2, 2015 at 13:45 Comment(4)
OH MY GODNESSS!!!! THANKSSSSSSSSSSS!!!! The only different line is WebChromeClient callback.invoke(origin, true, false); but it works dude!!!Carmella
It was required for my job and it drived me crazy for 2 weeks!! I knew it must be a silly thing... Do you know exactly what is doing the callback.invoke sentence?Carmella
developer.android.com/reference/android/webkit/…, android.webkit.GeolocationPermissions.Callback) and developer.android.com/reference/android/webkit/…Almena
so you basically allow the web page to access the geolocation apiAlmena
J
0

The line

D/WebKit (22653): SQLite database failed to load from /CachedGeoposition.db

is interesting

Try setting the appropriate DB path in WebSettings.setDatabasePath as well, it could be that this is used as the root for the geo db path

Johannisberger answered 1/11, 2012 at 16:15 Comment(0)
D
0

I know this is an old question but anyone with this issue might find interesting focusing on this function:

mWebView.getSettings().setGeolocationDatabasePath(getFilesDir().getPath());

Geolocation uses databases to persist cached positions and permissions between sessions. This call sets the location of the database.

Instead of setting a fixed path as parameter you should get it dynamically calling:

getFilesDir().getPath()
Dit answered 22/8, 2014 at 9:21 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.