You are here

Mobile Offline Map Client with Cordova hybrid HTML5

Mobile Offline Map Client, is it necessary? Yes, if you work outside but there is not network or wifi, but you still need WMS to display the map and WFS to edit the feature, offline functionality will help.

After research and inspired by other ideas, /?q=en/node/72475

Then the mobile offline hybrid HTML5 map client is born, frameworks or plugins it used:

1. OpenLayers: Go
2. Sencha-touch: Go
3. GXM: Go
4. Phonegap, Cordova: Go

According to this research, http://pgiraud.github.io/foss4g2013_mobile/#/24 , File API r/w is more efficent than DB blob r/w.
For storing WMS map tile, instead of save tile as base64 Blob in Database, i decided to use Cordova File API to download the map tile image and save to memory card. Map tile was named as md5 HASH string depends on the WMS map request URL, this is unique.

A openlayers extended Class named OpenLayers.Layer.WMSOffline will do this job instead of OpenLayers.Layer.WMS.

Code snippet to download map tile image to memory card:

var fileTransfer = new FileTransfer();
fileTransfer.download(
url,
that.localDirPath + fileName,
function(file) {
console.log("download complete: " + file.toURI());
callback(file.toURI());
},
function(error) {
console.log("downloadFile error source " + error.source);
console.log("downloadFile error target " + error.target);
console.log("downloadFile error code: " + error.code);
}
);

Code snippet to load map tile as file URI:


loadFile: function(url, callback) {
var that = this;
var hash = CryptoJS.MD5(that.filterUrl(url));
var fileName = hash +'.' + that.getTail(url);

console.log("Ready to load cache:" + that.localDirPath +fileName);
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, gotFS, fail);

function gotFS(fileSystem) {
fileSystem.root.getDirectory(that.localDirName, {create: true}, gotDir, fail);
}

function gotDir(dirEntry) {
dirEntry.getFile(fileName, {create: false, exclusive: false}, gotFileEntry, fail);
}

function gotFileEntry(fileEntry) {
console.log("Ready to load cache done");
callback(that.localDirPath +fileName);
}

function fail(error) {
console.log('Not found in cache, go to donwload:' + url);
callback(null);
}
}

For storing WFS features entry, SQLite Plugin from Cordova was used, because browser WebSQL or IndexDB have compatible problem or size limitation.

A openlayers extended Class named OpenLayers.Layer.VectorOffline will do this job instead of OpenLayers.Layer.Vector.

Code snippet to save WFS feature with data attributes(from JSON object to string) into SQLite:

this.db.transaction(function(tx) {
var geometry = '';
var data = '';
try{
geometry = JSON.stringify(checkin.geometry);
data = JSON.stringify(checkin.data);
if(!data)data='';
}catch(e){console.log("saveWFS error: " + e);}

tx.executeSql("INSERT INTO wfsdata (fid, geometry, data) VALUES (?,?,?)", [checkin.fid, geometry, data], function(tx, res) {
console.log("Schema wfsdata new insertId: " + res.insertId);
handler();
}, function(e) {
console.log("Error in saveWFS insert, reason: " + e.message);
});

});

Code snippet to load WFS feature with data attributes(from string in db to JSON format) from SQLite:

that.db.transaction(function(tx) {
tx.executeSql("select * from wfsdata WHERE id > 0 ", [], function(tx, res) {
console.log("getWFS found features: " + res.rows.length );

for ( var i=0, l=res.rows.length ; i

The extended Openlayers Class was developed based on the following research:

  • https://github.com/openlayers/openlayers/pull/643
  • https://github.com/PierceCountyWA/openlayers/commit/264f27a28d7b38dd0e1d4758639e2ed609452224 (Quellcode: IndexDB-cache ab Zeile 200, WebSQL ab Zeile 346)
  • https://github.com/PierceCountyWA/openlayers/commit/f571043ef9d0d1cc5881b6023c3335083fca1496
  • https://github.com/liip/OpenLayersOfflineDemo/blob/master/js/offline-websql.js
  • http://trac.osgeo.org/openlayers/browser/sandbox/jgrocha/openlayers/examples/localstorageexample.js

Thanks for those guys who did their efforts in this offline map cache direction.

Work result:


Map client works even when Offline, wifi is closed:


Map tiles were stored in memory card: