html

android

local-storage

webview

android-webview

I have a problem with a webview which may access to the localStorage by an HTML5 app. The test.html file informs me that local storage is'nt supported by my browser (ie. the webview). If you have any suggestion..

package com.test.HelloWebView; 
import android.app.Activity; 
import android.content.Context; 
import android.os.Bundle; 
import android.util.Log; 
import android.view.KeyEvent; 
import android.webkit.WebChromeClient; 
import android.webkit.WebSettings; 
import android.webkit.WebStorage; 
import android.webkit.WebView; 
import android.webkit.WebViewClient; 

public class HelloWebView extends Activity { 

    WebView webview;

    public void onCreate(Bundle savedInstanceState) { 
        super.onCreate(savedInstanceState); 
        setContentView(R.layout.main); 
        webview = (WebView) findViewById(R.id.webview); 
        webview.getSettings().setJavaScriptEnabled(true); 
        webview.setWebViewClient(new HelloWebViewClient()); 
        webview.loadUrl("file:///android_asset/test.html"); 
        WebSettings settings = webview.getSettings(); 
        settings.setJavaScriptEnabled(true); 
        settings.setDatabaseEnabled(true); 
        String databasePath = this.getApplicationContext().getDir("database", Context.MODE_PRIVATE).getPath(); 
        settings.setDatabasePath(databasePath);
        webview.setWebChromeClient(new WebChromeClient() { 
        public void onExceededDatabaseQuota(String url, String databaseIdentifier, long currentQuota, long estimatedSize, long totalUsedQuota, WebStorage.QuotaUpdater quotaUpdater) { 
                quotaUpdater.updateQuota(5 * 1024 * 1024); 
            } 
        }); 
    }

    public boolean onKeyDown(int keyCode, KeyEvent event) { 
        if ((keyCode == KeyEvent.KEYCODE_BACK) && webview.canGoBack()) { 
            webview.goBack(); 
            return true; 
        } 
        return super.onKeyDown(keyCode, event); 
    }

    private class HelloWebViewClient extends WebViewClient { 
        public boolean shouldOverrideUrlLoading(WebView view, String url) { 
            view.loadUrl(url); 
            return true; 
        } 
    }
}

Solution 1

The following was missing:

settings.setDomStorageEnabled(true);

Solution 2

setDatabasePath() method was deprecated in API level 19. I advise you to use storage locale like this:

webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setDatabaseEnabled(true);
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
    webView.getSettings().setDatabasePath("/data/data/" + webView.getContext().getPackageName() + "/databases/");
}

Solution 3

I've also had problem with data being lost after application is restarted. Adding this helped:

webView.getSettings().setDatabasePath("/data/data/" + webView.getContext().getPackageName() + "/databases/");

Solution 4

A solution that works on my Android 4.2.2, compiled with build target Android 4.4W:

WebSettings settings = webView.getSettings();
settings.setDomStorageEnabled(true);
settings.setDatabaseEnabled(true);

if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) {
    File databasePath = getDatabasePath("yourDbName");
    settings.setDatabasePath(databasePath.getPath());
}

Solution 5

If your app use multiple webview you will still have troubles : localStorage is not correctly shared accross all webviews.

If you want to share the same data in multiple webviews the only way is to repair it with a java database and a javascript interface.

This page on github shows how to do this.

hope this help!

Solution 6

This post came up a lot recently when I was looking for a similar solution. The webview WebSettings object has deprecated database path methods since API 19 which now return blank values, meaning we can't rely on them to pull the web page storage regardless of whether we enabled it on the settings prior to loading an URL.

In order to read localStorage values from a web page, we needed to extend the WebViewClient() and override onPageFinished(), in which you can evaluate javascript on the webview as demonstrated below:

const val JAVASCRIPT_LOCAL_STORAGE_LOOKUP = "javascript:window.localStorage.getItem('KEY');"

...

override fun onPageFinished(view: WebView?, url: String?) {
    super.onPageFinished(view, url)
    view?.let { webView ->
        webView.evaluateJavascript(JAVASCRIPT_LOCAL_STORAGE_LOOKUP) { result ->
            // returns value from 'KEY'
        }
    }
}

Simply replace 'KEY' with the key of the stored object you want to access. This removes the need to provide any database implementation that may conflict with what you already have. Note that this will only poll the localStorage from the domain that the webview just finished loading. I hope this helps anyone else as it took me a bit of time to figure out.

Solution 7

I have a better solution for this it will work for the first time opening WebView.

you just have to use a custom callback. like this

public interface DataSavedCallback {
  void onDataSaved();
}

then use this function to get the value of the key from the webview local storage

    public static void getLocalStorageAndSaveOnAndroidPref(String[] keys,
WebView view,dataSavedCallback savedCallback) {
  
    String JAVASCRIPT_LOCAL_STORAGE_LOOKUP = "javascript:window";
     view.evaluateJavascript(JAVASCRIPT_LOCAL_STORAGE_LOOKUP.concat(".localStorage.getItem('" + keys[i] + "')"), new ValueCallback<String>() {
                @Override
                public void onReceiveValue(String value) {
                    Log.d(TAG, "getLocalStorageAndSaveOnAndroidPref: " + value);
                }
            });

    }


you can call the above function anywhere using your webview

myWebView.post(() -> {
            String[] keys = {"androidDeliveryAppStickyNotificationTitle","androidDeliveryAppStickyNotificationSubtitle","androidAppNewSoundAlertTitle"};
            getLocalStorageAndSaveOnAndroidPref(keys, myWebView, new dataSavedCallback() {
                @Override
                public void onDataSaved() {
                //do whatever you want
                }
            });

        });

Solution 8

if you have multiple webview, localstorage does not work correctly.
two suggestion:

  1. using java database instead webview localstorage that " @Guillaume Gendre " explained.(of course it does not work for me)
  2. local storage work like json,so values store as "key:value" .you can add your browser unique id to it's key and using normal android localstorage