机器人的WebView饼干返回null [英] Android webview cookie returns null

查看:160
本文介绍了机器人的WebView饼干返回null的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想简单地设置和检索的android一个web视图里面的cookie。我已经试过无数的cookie管理器脚本来尝试,并得到这个工作。我已经启用JavaScript。

当运行在三星S3和三星Galaxy Tab 10.1饼干的应用程序似乎并没有设置在所有(安卓4.1)。然而,在三星Galaxy ACE,HTC Desire Z的,并在Android模拟器上运行的软件时,会将cookie设置和读取完美的罚款。

在工作,web视图返回预期的字符串,不工作时,输出的是简单的空;该cookie没有价值/未设置。

我的具体情况还采用了滑动导航类,这是动作条福尔摩斯的延伸。

我真的AP preciate任何帮助,我一直在努力奋斗着这个好几个星期了。 谢谢你。

HTML:

 < HTML>
< HEAD>
    <冠军>
    < /标题>
<脚本>
    函数的createCookie(名称,值)
    {
            变种天=(1 * 24 * 60 * 60 * 1000);
            VAR日期=新的日期();
            date.setTime(date.getTime()+(20 * 365 *天));
            变种期满=;期满=+ date.toGMTString();

            的document.cookie =名称+'=;到期=周四,1970年1月1日00:00:01 GMT;';
            的document.cookie =名称+=+值+到期+;路径= /;
    }

    功能readCookie(名)
    {
        VAR nameEQ =名称+=;
        变种CA = document.cookie.split(';');
        对于(VAR I = 0; I< ca.length;我++){
            变种C = CA [I]
            而(c.charAt(0)==''),C = c.substring(1,c.length);
            如果(c.indexOf(nameEQ)== 0)返回c.substring(nameEQ.length,c.length);
        }
        返回null;
    }

< / SCRIPT>
< /头>
<身体GT;
< H1类=>
<脚本类型=文/ JavaScript的>
    createCookie的(测试,如果这是工作,它返回这个字符串。如果这是行不通的,则返回null。);
    文件撰写(测试+ readCookie(测试));
< / SCRIPT>
< /身体GT;
< / HTML>
 

Java的code:

公共类MainActivity扩展SherlockActivity实现ISideNavigationCallback {

 公共静态最后弦乐EXTRA_TITLE =com.devspark.sidenavigation.sample.extra.MTGOBJECT;
公共静态最后弦乐EXTRA_RESOURCE_ID =com.devspark.sidenavigation.sample.extra.RESOURCE_ID;
公共静态最后弦乐EXTRA_MODE =com.devspark.sidenavigation.sample.extra.MODE;
公共静态字符串WebLoaded =0;
公共静态字符串页=signup.php;

私人ImageView的图标;
私人SideNavigationView sideNavigationView;
私人的WebView发动机;

@覆盖
保护无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);

    的setContentView(R.layout.activity_main);

    图标=(ImageView的)findViewById(android.R.id.icon);
    sideNavigationView =(SideNavigationView)findViewById(R.id.side_navigation_view);
    sideNavigationView.setMenuItems(R.menu.side_navigation_menu);
    sideNavigationView.setMenuClickCallback(本);

    如果(getIntent()。hasExtra(EXTRA_TITLE)){
        字符串标题= getIntent()getStringExtra(EXTRA_TITLE)。
        。INT渣油= getIntent()getIntExtra(EXTRA_RESOURCE_ID,0);
        的setTitle(职称);
        icon.setImageResource(渣油);
        sideNavigationView.setMode(getIntent()getIntExtra(EXTRA_MODE,0)== 0 Mode.LEFT:Mode.RIGHT?);
    }

   //测试
    getSupportActionBar()setDisplayHomeAsUpEnabled(真)。

    字符串域=localhost的;

    CookieManager cookieManager = CookieManager.getInstance();
    cookieManager.setAcceptCookie(真正的);
    cookieManager.setCookie(域,名称=值);
    cookieManager.setCookie(域,路径= /);
    cookieManager.setCookie(域,仅Http);

    //启用cookies
    。CookieManager.getInstance()setAcceptCookie(真正的);
    //导航Web引擎,包括导航点击
    发动机=(web视图)findViewById(R.id.web_engine);


    engine.loadUrl(文件:/// android_asset /+页);
    //启用JavaScript的支持 - 对于一些奇怪的原因,默认情况下禁用
    engine.getSettings()setJavaScriptEnabled(真)。
    engine.setWebViewClient(新WebViewClient());






    //禁用文本选择
    engine.setOnLongClickListener(新View.OnLongClickListener(){
        公共布尔onLongClick(视图v){
            返回true;
        }
    });
}

@覆盖
公共无效的onPause()
{
    super.onPause();
    engine.getSettings()setJavaScriptEnabled(假)。
}

@覆盖
公共无效onResume()
{
    super.onResume();
    engine.getSettings()setJavaScriptEnabled(真)。
}

@覆盖
公共布尔onOptionsItemSelected(菜单项项){
    开关(item.getItemId()){
        案例android.R.id.home:
            sideNavigationView.toggleMenu();
            打破;
        案例R.id.mode_left:
            item.setChecked(真正的);
            sideNavigationView.setMode(Mode.LEFT);
            打破;
        案例R.id.mode_right:
            item.setChecked(真正的);
            sideNavigationView.setMode(Mode.RIGHT);
            打破;

        默认:
            返回super.onOptionsItemSelected(项目);
    }
    返回true;
}

@覆盖
公共无效onSideNavigationItemClick(INT的itemId){


    开关(的itemId){
        案例R.id.side_navigation_menu_item1:
            invokeActivity(的getString(R.string.title1),R.drawable.ic_android1);
            页=的index.html;
            打破;

        案例R.id.side_navigation_menu_item2:
            invokeActivity(的getString(R.string.title2),R.drawable.ic_android2);
            页=test.html中;
            打破;

        案例R.id.side_navigation_menu_item3:
            invokeActivity(的getString(R.string.title3),R.drawable.ic_android3);
            打破;

        案例R.id.side_navigation_menu_item4:
            invokeActivity(的getString(R.string.title4),R.drawable.ic_android4);
            打破;

        案例R.id.side_navigation_menu_item5:
            invokeActivity(的getString(R.string.title5),R.drawable.ic_android5);
            打破;

        默认:
            返回;
    }
    完();
}
 

解决方案

在一个多月的研究,我得出的结论是设置在Android的版本大于2.3的Cookie是不可能在一个web视图那里的文件在本地主机后, (直接从资产的文件夹中读取)。

我通过很多办法去使用的cookie存储,包括使用HTML的localStorage的。这里的整个问题,导致我相信,是安全的。如果我要创建本地主机上的cookie或localStorage的,那么其他的应用程序可以访问该存储,因此是一个重大的安全威胁。

我的终极问题试图弥合与Java的双向通信的web视图,也有在此过程中存储数据的地方。我的解决办法是充分利用的 JavascriptInterface

的思想如下:

  • 解析数据中的JavaScript功能
  • JavaScript调用一个特殊的JavaScript函数如使用setData(myDataName,myData的)
  • Java有一个功能,听这个,并会采取通过javscript设置参数,也可以返回值的JavaScript。
  • 一旦数据被解析到Java,Java的将其存储在一系列文件的资产。
  • 当JavaScript函数的getData(myDataName)之称,该数据是由Java中的一种方法返回。

我发现这非常有用:<一href="http://developer.android.com/reference/android/webkit/WebView.html#addJavascriptInterface%28java.lang.Object,%20java.lang.String%29"相对=nofollow>安卓的 JavascriptInterface 的文档,的 Android中处理JavascriptInterface 2.3

唯一的主要挂起坐来了什么我发现了一个的中的Andr​​oid 2.3(固定在3.0),从而有效地打破了JavascriptInterface相当严重的错误。上面的第二个链接描述我已经找到了最好的解决方法。

下面是如何获得的双向通信的工作(这是非常凌乱,但它的工作原理)的一个例子:

自定义webinterface类:

 公共类webViewInterface {
    // @ JavascriptInterface //为SDK 12+
    公共字符串showToast(会将myText字符串){
        Toast.makeText(上下文,会将myText,Toast.LENGTH_LONG).show();
        会将myText回报;
    }
    }
 

主要类:     保护无效的onCreate(包savedInstanceState){     super.onCreate(savedInstanceState);

 的setContentView(R.layout.activity_main);

发动机=(web视图)findViewById(R.id.web_engine);

上下文=这一点;
WebSettings webSettings = engine.getSettings();
webSettings.setJavaScriptEnabled(真正的);

engine.setWebViewClient(新WebViewClient());
engine.loadUrl(文件:/// android_asset /+页);

布尔javascriptInterfaceBroken = FALSE;
尝试 {
        如果(Build.VERSION.RELEASE.startsWith(2.3)){
         javascriptInterfaceBroken = TRUE;
        }
    }赶上(例外五){

    //忽略,并且假设用户的JavaScript接口是否正常工作。
    }

//添加JavaScript的接口只有当它不破
    // @TODO:写的解决方法:LT; 2.3设备
如果(!javascriptInterfaceBroken){
        engine.addJavascriptInterface(新webViewInterface(),MainActivityInterface);
}

//禁用文本选择
engine.setOnLongClickListener(新View.OnLongClickListener(){
    公共布尔onLongClick(视图v){
        返回true;
    }
});
}
 

HTML:

 &LT; HTML&GT;
&LT; HEAD&GT;
&LT; /头&GT;
&LT;身体GT;

&LT;输入类型=按钮值=问好的onClick =showAndroidToast(); /&GT;

&LT;脚本类型=文/ JavaScript的&GT;
    功能showAndroidToast(){
        文件撰写(MainActivityInterface.showToast(尤里卡!));
    }
&LT; / SCRIPT&GT;

&LT; /身体GT;
&LT; / HTML&GT;
 

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.

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.

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.

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 Code:

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

解决方案

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

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.

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

The idea is as follows:

  • Parse data to function in javascript
  • Javascript calls a special javascript function e.g. "setData(myDataName, myData)"
  • Java has a function which listens to this, and will take arguments set by javscript, and can also return values to javascript.
  • Once data is parsed to Java, java stores this in a series of files in assets.
  • When javascript function "getData(myDataName)" is called, the data is returned by the same kind of method by Java.

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

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

Custom webinterface class:

public class webViewInterface { 
    //@JavascriptInterface //for SDK 12+
    public String showToast(String myText) {
        Toast.makeText(context, myText, Toast.LENGTH_LONG).show();
        return myText;
    }
    }

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>

这篇关于机器人的WebView饼干返回null的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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