我试图在 android 的 webview 中简单地设置和检索 cookie。我已经尝试了很多 cookie 管理器脚本来尝试让它工作。我启用了 JavaScript。
在 Samsung S3 和 Samsung Galaxy Tab 10.1 上运行应用程序时,cookie 似乎根本没有设置 (android 4.1)。但是,当在 Samsung Galaxy ace、HTC Desire Z 和安卓模拟器上运行该软件时,cookie 设置和读取都非常好。
工作时,webview 返回预期的字符串,不工作时,输出只是“null”; cookie 没有值/未设置。
我的具体案例还使用了滑动导航类,它是 Actionbar Sherlock 的扩展。
我真的很感激任何帮助,我已经为此苦苦挣扎了几个星期。 谢谢。
HTML:
<html>
<head>
<title>
</title>
<script>
function createCookie(name, value)
{
var day = (1 * 24 * 60 * 60 * 1000);
var date = new Date();
date.setTime(date.getTime() + (20 * 365 * day));
var expires = "; expires=" + date.toGMTString();
document.cookie = name + '=; expires=Thu, 01 Jan 1970 00:00:01 GMT;';
document.cookie = name + "=" + value + expires + "; path=/";
}
function readCookie(name)
{
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca[i];
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;
}
</script>
</head>
<body>
<h1 class="">
<script type="text/javascript">
createCookie("test", "If this is working, it returns this string. If this is not working, it returns null.");
document.write("test: " + readCookie("test"));
</script>
</body>
</html>
Java 代码:
公共(public)类 MainActivity 扩展 SherlockActivity 实现 ISideNavigationCallback {
public static final String EXTRA_TITLE = "com.devspark.sidenavigation.sample.extra.MTGOBJECT";
public static final String EXTRA_RESOURCE_ID = "com.devspark.sidenavigation.sample.extra.RESOURCE_ID";
public static final String EXTRA_MODE = "com.devspark.sidenavigation.sample.extra.MODE";
public static String WebLoaded = "0";
public static String page = "signup.php";
private ImageView icon;
private SideNavigationView sideNavigationView;
private WebView engine;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
icon = (ImageView) findViewById(android.R.id.icon);
sideNavigationView = (SideNavigationView) findViewById(R.id.side_navigation_view);
sideNavigationView.setMenuItems(R.menu.side_navigation_menu);
sideNavigationView.setMenuClickCallback(this);
if (getIntent().hasExtra(EXTRA_TITLE)) {
String title = getIntent().getStringExtra(EXTRA_TITLE);
int resId = getIntent().getIntExtra(EXTRA_RESOURCE_ID, 0);
setTitle(title);
icon.setImageResource(resId);
sideNavigationView.setMode(getIntent().getIntExtra(EXTRA_MODE, 0) == 0 ? Mode.LEFT : Mode.RIGHT);
}
//test
getSupportActionBar().setDisplayHomeAsUpEnabled(true);
String domain = "localhost";
CookieManager cookieManager = CookieManager.getInstance();
cookieManager.setAcceptCookie(true);
cookieManager.setCookie(domain, "name=value");
cookieManager.setCookie(domain, "path=/");
cookieManager.setCookie(domain, "HttpOnly");
//enable cookies
CookieManager.getInstance().setAcceptCookie(true);
//navigates web engine, including on nav click
engine = (WebView) findViewById(R.id.web_engine);
engine.loadUrl("file:///android_asset/" + page);
//enable JavaScript support - disabled by default for some weird reason
engine.getSettings().setJavaScriptEnabled(true);
engine.setWebViewClient(new WebViewClient());
//disables text selection
engine.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
return true;
}
});
}
@Override
public void onPause()
{
super.onPause();
engine.getSettings().setJavaScriptEnabled(false);
}
@Override
public void onResume()
{
super.onResume();
engine.getSettings().setJavaScriptEnabled(true);
}
@Override
public boolean onOptionsItemSelected(MenuItem item) {
switch (item.getItemId()) {
case android.R.id.home:
sideNavigationView.toggleMenu();
break;
case R.id.mode_left:
item.setChecked(true);
sideNavigationView.setMode(Mode.LEFT);
break;
case R.id.mode_right:
item.setChecked(true);
sideNavigationView.setMode(Mode.RIGHT);
break;
default:
return super.onOptionsItemSelected(item);
}
return true;
}
@Override
public void onSideNavigationItemClick(int itemId) {
switch (itemId) {
case R.id.side_navigation_menu_item1:
invokeActivity(getString(R.string.title1), R.drawable.ic_android1);
page = "index.html";
break;
case R.id.side_navigation_menu_item2:
invokeActivity(getString(R.string.title2), R.drawable.ic_android2);
page = "test.html";
break;
case R.id.side_navigation_menu_item3:
invokeActivity(getString(R.string.title3), R.drawable.ic_android3);
break;
case R.id.side_navigation_menu_item4:
invokeActivity(getString(R.string.title4), R.drawable.ic_android4);
break;
case R.id.side_navigation_menu_item5:
invokeActivity(getString(R.string.title5), R.drawable.ic_android5);
break;
default:
return;
}
finish();
}
最佳答案
经过一个多月的研究,我得出的结论是,在文件位于本地主机(直接从 Assets 文件夹中读取)的 webview 中,不可能在高于 2.3 的 android 版本中设置 cookie。
除了使用 cookie 存储之外,我还尝试了很多替代方法,包括使用 HTML 的本地存储。我被引导相信,这里的整个问题是安全。如果我要在本地主机上创建一个 cookie 或本地存储,那么其他应用程序就可以访问该存储,因此这是一个主要的安全威胁。
我的最终问题是试图将 webview 与 java 的双向通信桥接起来,并在此过程中有一个存储数据的地方。我的解决方案是利用 JavascriptInterface
思路如下:
- 解析数据以在 javascript 中运行
- Javascript 调用特殊的 javascript 函数,例如“设置数据(我的数据名,我的数据)”
- Java 有一个监听这个的函数,它将接受由 javascript 设置的参数,并且还可以将值返回给 javascript。
- 一旦数据被解析为 Java,java 会将其存储在 Assets 中的一系列文件中。
- 当调用 javascript 函数“getData(myDataName)”时,数据由 Java 的同类方法返回。
我发现这非常有用:Android JavascriptInterface Documentation , Handling JavascriptInterface in Android 2.3
我发现的唯一主要“问题”是 fairly serious bug在 Android 2.3(在 3.0 中修复)有效地破坏了 JavascriptInterface。上面的第二个链接描述了我找到的最佳解决方法。
这是一个如何让双向通信正常工作的例子(它很困惑,但它有效):
自定义网络接口(interface)类:
public class webViewInterface {
//@JavascriptInterface //for SDK 12+
public String showToast(String myText) {
Toast.makeText(context, myText, Toast.LENGTH_LONG).show();
return myText;
}
}
主类: protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
engine = (WebView) findViewById(R.id.web_engine);
context = this;
WebSettings webSettings = engine.getSettings();
webSettings.setJavaScriptEnabled(true);
engine.setWebViewClient(new WebViewClient());
engine.loadUrl("file:///android_asset/" + page);
boolean javascriptInterfaceBroken = false;
try {
if (Build.VERSION.RELEASE.startsWith("2.3")) {
javascriptInterfaceBroken = true;
}
} catch (Exception e) {
// Ignore, and assume user javascript interface is working correctly.
}
// Add javascript interface only if it's not broken
// @TODO: write the workaround for < 2.3 devices
if (!javascriptInterfaceBroken) {
engine.addJavascriptInterface(new webViewInterface(), "MainActivityInterface");
}
//disables text selection
engine.setOnLongClickListener(new View.OnLongClickListener() {
public boolean onLongClick(View v) {
return true;
}
});
}
HTML:
<html>
<head>
</head>
<body>
<input type="button" value="Say hello" onClick="showAndroidToast();" />
<script type="text/javascript">
function showAndroidToast() {
document.write(MainActivityInterface.showToast("eureka!"));
}
</script>
</body>
</html>
关于java - Android webview cookie 返回 null,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/19235489/