Android 网页视图 &本地存储

发布于 2024-11-04 23:53:42 字数 2118 浏览 2 评论 0原文

我的 webview 遇到问题,它可能通过 HTML5 应用程序访问 localStorage。 test.html 文件告诉我本地 我的浏览器(即 webview)不支持存储。如果您有任何建议..

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; 
        } 
    }
}

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; 
        } 
    }
}

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(8

依 靠 2024-11-11 23:53:43

最近当我寻找类似的解决方案时,这篇文章出现了很多。 webview WebSettings 对象具有自 API 19 起已弃用的数据库路径方法现在返回空白值,这意味着我们不能依赖它们来提取网页存储,无论我们在加载 URL 之前是否在设置中启用了它。

为了从网页读取 localStorage 值,我们需要扩展 WebViewClient() 并重写 onPageFinished(),您可以在其中评估 webview 上的 javascript,如下所示如下:

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'
        }
    }
}

只需将 'KEY' 替换为您要访问的存储对象的密钥。这样就无需提供任何可能与您已有的数据库实现发生冲突的数据库实现。请注意,这只会从 webview 刚刚完成加载的域中轮询 localStorage。我希望这对其他人有帮助,因为我花了一些时间才弄清楚。

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.

冷血 2024-11-11 23:53:43

我对此有一个更好的解决方案,它将在第一次打开 WebView 时起作用。

您只需要使用自定义回调即可。像这样

public interface DataSavedCallback {
    void onDataSaved();
}

然后使用此函数从 webview 本地存储中获取键的值

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);
        }
    });
}

您可以使用 webview 在任何地方调用上述函数

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

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
        }
    });
});
停滞 2024-11-11 23:53:43

如果您有多个 webview,本地存储将无法正常工作。
两个建议:

  1. 使用java数据库而不是“@Guillaume Gendre”解释的webview localstorage。(当然它对我不起作用)
  2. 本地存储像json一样工作,因此值存储为“key:value”。您可以添加浏览器唯一id到它的关键并使用普通的 android localstorage

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
柠北森屋 2024-11-11 23:53:42

缺少以下内容:

settings.setDomStorageEnabled(true);

The following was missing:

settings.setDomStorageEnabled(true);
原谅我要高飞 2024-11-11 23:53:42

setDatabasePath() 方法是在 API 级别 19 中已弃用。我建议您使用如下存储区域设置:

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/");
}

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/");
}
爱,才寂寞 2024-11-11 23:53:42

我还遇到过应用程序重新启动后数据丢失的问题。
添加这个有帮助:

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

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/");
呆° 2024-11-11 23:53:42

适用于我的 Android 4.2.2 的解决方案,使用构建目标 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());
}

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());
}
岁吢 2024-11-11 23:53:42

如果您的应用程序使用多个 Web 视图,您仍然会遇到麻烦:localStorage 未在所有 Web 视图中正确共享。

如果你想在多个 webview 中共享相同的数据,唯一的方法是使用 java 数据库和 javascript 接口来修复它。

github 上的此页面展示了如何执行此操作。

希望这有帮助!

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!

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文