在Android WebView中使用本地存储时出现访问被拒绝的问题

17

我有一个 Android webview,我相信它具备访问和使用本地存储所需的一切条件,但是当我尝试使用本地存储时,在控制台中看到了一个“Access denied”的错误。

Uncaught SecurityError: Failed to read the 'localStorage' property from 'Window': Access is denied for this document.

有人能发现问题吗?

JavaScript 代码:

function localStorageTest() {
  // Check browser support
  if (typeof(Storage) != "undefined") {
    // Store
    localStorage.setItem("lastname", "Smith");
    // Retrieve
    document.getElementById("console").innerHTML = localStorage.getItem("lastname");
  } else {
    document.getElementById("console").innerHTML = "Sorry, your browser does not support Web Storage...";
  }
}

以下是 Android 代码:

    // Enable javascript
    WebSettings settings = getSettings();
    settings.setJavaScriptEnabled(true);
    settings.setDomStorageEnabled(true);
    settings.setDatabaseEnabled(true);

    // Create database folder
    String databasePath = getContext().getDir("databases", Context.MODE_PRIVATE).getPath();
    getSettings().setDatabasePath(databasePath);

    getContext().getPackageName() + "/databases/");

    settings.setAppCacheEnabled(true);
    settings.setSaveFormData(true);;
    settings.setLoadWithOverviewMode(true);
    settings.setSaveFormData(true);

你在使用第三方cookie吗? - Rayon
你在这里留下了一个错别字 getContext().getPackageName() + "/databases/"); - Cory Robinson
6个回答

17

localStorage 的访问仅允许在特定的“Web安全”协议下,如 http:https:file:。它不能用于诸如 about:data: 等自定义协议中。Chrome 的行为方式相同,在桌面端可以检查。


嗯...所以如果我只是加载自己的HTML内容而不是从服务器提供它,它就无法工作了吗? - bugfixr
3
尝试使用WebView.loadDataWithBaseUrl方法,并指定以http:协议为开头的基本URL。或者您可以在应用程序内部运行一个简单的Web服务器。 - Mikhail Naganov
1
为什么我在“file://”协议中本地访问被拒绝了呢? - oldboy

5
为了在JS中操作全局对象,我们需要一个技巧。正如 @Mikhail Naganov 所说的那样,chromium 抱怨安全问题,在Android WebView中使用本地存储时访问被拒绝 我将JS作为基础url加载,并在JS中重定向到真实的url。下面的代码在Android 7上适用。
    String mimeType = "text/html";
    String encoding = "utf-8";
    String injection = "<script type='text/javascript'>localStorage.setItem('key', 'val');window.location.replace('REAL_URL_HERE');</script>";
    webview.loadDataWithBaseURL("REAL_URL_HERE", injection, mimeType, encoding, null);

1
我在iOS和WKWebView中使用了相同的代码,它也可以正常工作。 - canbax
在我的情况下,它解决了错误“Uncaught SecurityError:无法从'Window'读取'localStorage'属性:在'data:'URL中禁用了存储。”谢谢。 - kosiara - Bartosz Kosarzycki
也许安卓中的WebView已经改变了。我已经8个月没有运行安卓了。@Ryan,这一行代码 "window.location.replace('REAL_URL_HERE')" 应该会重定向到你想要的URL。 - canbax
对于某些原因,它不会重定向,或者加载一个空页面。我最终通过在评估脚本之前和之后分别加载URL两次来以不同的方式解决了这个问题,虽然并不理想但也能起作用……如果有人遇到这个问题,我可以分享解决方案,只需提及我的名字即可。 - Ryhan
嗨@Ryhan,我也遇到了同样的问题。你能分享一下你的代码吗? - Vivek

3

这对我有用

webview.getSettings().setAllowFileAccess(true);

1

你在manifest.xml中请求了访问存储和网络的权限吗?

就像这样:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />

嗯...我发现人们在使用Google Chrome时会遇到这个问题,但是对于仅限于ViewPager的情况我找不到相关信息,但谁知道呢,也许这个链接可以帮到你: https://dev59.com/iGAf5IYBdhLWcg3wnDwI - Damien

1

尝试使用以下方法调用来在Webview中启用本地存储。

webView.getSettings().setDomStorageEnabled(true);
webView.getSettings().setJavaScriptEnabled(true);
webView.getSettings().setDatabaseEnabled(true);

1
我遇到了一个相关的错误。除了最后一部分访问数据被拒绝:之外,其他都一样。
在我的情况下,我正在加载与指定src交互的html内容的脚本。为了使webView渲染此src,我必须从<script>部分提取url,并将其作为baseUrl调用loadDataWithBaseURL方法,并将html作为数据放入其中。
web.loadDataWithBaseURL(urlSrc, data, "text/html", "utf-8")

1
我也有同样的需求。我需要展示一个嵌入式的TikTok视频,使用HTML字符串作为内容。在WebView的loaddatawithbaseurl中使用TikTok脚本所需的基础URL,可以渲染出嵌入式视频。 - Xaren

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接