Android webview cookie 返回空值 [英] Android webview cookie returns null

查看:19
本文介绍了Android webview cookie 返回空值的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试在 android 的 webview 中简单地设置和检索 cookie.我已经尝试了许多 cookie 管理器脚本来尝试让它工作.我启用了 JavaScript.

I'm trying to simply set and retrieve a cookie inside a webview in android. I have tried numerous cookie manager scripts to try and get this to work. I have JavaScript enabled.

在三星 S3 和三星 Galaxy Tab 10.1 上运行应用程序时,cookie 似乎根本没有设置 (android 4.1).但是,在 Samsung Galaxy ace、HTC Desire Z 和 android 模拟器上运行该软件时,cookie 设置和读取完全正常.

When running the application on a Samsung S3 and a Samsung Galaxy Tab 10.1 cookies don't appear to set at all (android 4.1). However, when running the software on a Samsung Galaxy ace, HTC Desire Z and in the android emulators, the cookies are set and read perfectly fine.

工作时,webview按预期返回字符串,不工作时,输出只是null";cookie 没有值/未设置.

When working, the webview returns the string as expected, when not working, the output is simply "null"; the cookie has not value/is not set.

我的具体案例还使用了滑动导航类,它是Actionbar Sherlock的扩展.

My specific case also uses sliding Navigation class, which is an extension of Actionbar Sherlock.

我真的很感激任何帮助,我已经为此苦苦挣扎了几个星期.谢谢.

I'd really appreciate any help, I've been struggling with this for several weeks now. Thank you.

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 代码:

公共类 MainActivity 扩展了 SherlockActivity 实现了 ISideNavigationCallback {

public class MainActivity extends SherlockActivity implements 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();
}

推荐答案

经过一个多月的研究,我得出结论,在 2.3 以上的 android 版本中设置 cookie 在文件位于本地主机上的 web 视图中是不可能的(直接从assets文件夹中读取).

After over a month of research I've concluded that setting a cookie in android versions greater than 2.3 is not possible in a webview where the file is on the localhost (read directly from the assets folder).

我尝试了许多使用 cookie 存储的替代方法,包括使用 HTML 的本地存储.我相信这里的整个问题是安全性.如果我要在本地主机上创建 cookie 或 localstorage,那么其他应用程序可以访问该存储空间,因此是一个主要的安全威胁.

I went through many alternatives to to using cookie storage, including using HTML's localstorage. The whole issue here, I am led to believe, is security. If I were to create a cookie or localstorage on the localhost, then other apps could access that storage, thus is a major security threat.

我的最终问题是试图通过与 java 的双向通信来桥接 webview,并且在此过程中还有一个地方可以存储数据.我的解决方案是利用 JavascriptInterface

My ultimate problem was trying to bridge the webview with two-way communication with java and also having a place to store data during the process. My solution was to take advantage of the JavascriptInterface

思路如下:

  • 解析数据以在 javascript 中运行
  • Javascript 调用一个特殊的 javascript 函数,例如"setData(myDataName, myData)"
  • Java 有一个函数可以监听这个,并接受由 javscript 设置的参数,也可以将值返回给 javascript.
  • 将数据解析为 Java 后,Java 会将其存储在资产中的一系列文件中.
  • 当javascript函数getData(myDataName)"被调用时,数据通过Java的同类方法返回.

我发现这非常有用:Android JavascriptInterface 文档在 Android 2.3 中处理 JavascriptInterface

I found this very useful: Android JavascriptInterface Documentation, Handling JavascriptInterface in Android 2.3

我发现的唯一主要挂断"是 相当严重的错误 在 Android 2.3(在 3.0 中修复)有效地破坏了 JavascriptInterface.上面的第二个链接描述了我找到的最佳解决方法.

The only major 'hang-ups' come with a what I found was a fairly serious bug in Android 2.3 (fixed in 3.0) which effectively broke the JavascriptInterface. The second link above describes the best workaround I have found.

这是一个如何使双向通信工作的示例(非常混乱,但它有效):

Here is an example of how to get the two-way communication working (it's very messy, but it works):

自定义网络界面类:

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

Main class: 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>

这篇关于Android webview cookie 返回空值的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆