当前位置: 首页 > 面试题库 >

Android Webview Cookie返回null

鲜于煜祺
2023-03-14
问题内容

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

在Samsung S3和Samsung Galaxy Tab 10.1上运行该应用程序时,cookie似乎根本没有设置(android
4.1)。但是,在Samsung Galaxy ace,HTC Desire Z和android模拟器中运行该软件时,将设置cookie并使其完全正常阅读。

当工作时,webview返回预期的字符串,当工作时,输出只是“ null”;cookie没有值/未设置。

我的特定情况还使用了滑动式Navigation类,它是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代码:

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

问题答案:

经过一个多月的研究,我得出结论,在文件位于localhost(直接从assets文件夹中读取)的webview中,无法在高于2.3的android版本中设置cookie。

我经历了使用cookie存储的多种选择,包括使用HTML的localstorage。我被认为可以相信,这里的整个问题都是安全性。如果要在本地主机上创建cookie或localstorage,则其他应用程序可以访问该存储,因此是主要的安全威胁。

我的最终问题是尝试通过Java与Java的双向通信来桥接Webview,并且在此过程中还需要存储数据。我的解决方案是利用
JavascriptInterface

这个想法如下:

  • 解析数据以在javascript中起作用
  • Javascript调用特殊的JavaScript函数,例如“ setData(myDataName,myData)”
  • Java有一个侦听此函数的函数,它将接受javscript设置的参数,并且还可以将值返回给javascript。
  • 将数据解析为Java之后,java会将其存储在资产中的一系列文件中。
  • 当调用javascript函数“ getData(myDataName)”时,Java用相同的方法返回数据

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

我发现的唯一主要“问题”是Android
2.3(已在3.0中修复)中一个相当严重的错误,该错误有效地破坏了JavascriptInterface。上面的第二个链接描述了我发现的最佳解决方法。

这是一个如何使双向通信正常工作的示例(虽然很杂乱,但是可以工作):

自定义网络界面类:

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

主类:受保护的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>


 类似资料:
  • 问题内容: 例如我有一个功能: 我怎样才能返回AJAX后得到的? 问题答案: 因为请求是异步的,所以您无法返回ajax请求的结果(而同步ajax请求是一个 糟糕的 主意)。 最好的选择是将自己的回调传递给f1 然后,您将像这样致电:

  • 我有两个活动和两个布局。当我在第一个活动中显示列表时,一切都正常,并在单击时给出列表中项目的编号,但当我尝试在第二个活动中重复相同的内容时,它会告诉我RecycleServiceClickListener侦听器为空。 适配器: 第一项活动: 第二项活动: 错误: 我不明白为什么在第一种情况下,它正常处理单击,而在第二种情况下,它说RecyclerViewClickListener为null

  • 问题内容: 我在使用Ajax时遇到问题。 问题是,在获得ajax响应之前,它会返回cnt。因此它总是返回NULL。 有没有办法使正确的返回响应值? 谢谢! 问题答案: 由于AJAX请求是异步的,因此您的cnt变量将在请求返回并调用成功处理程序之前返回。 我建议重构您的代码以解决此问题。 一种方法是从AJAX请求的成功处理程序中调用调用了GetGrantAmazonItemCnt()的任何函数,此方

  • 我想在下面返回JSON。 {“名字”:“杰基”} 新来的春靴在这里。1天大。有没有合适的方法可以做到这一点?

  • 加载样式表,并在用户单击按钮时将其应用于场景 调用getScene()返回null。 函数所在的类是场景的控制器和根节点,我使用SceneBuilder 2.0,并将类设置为加载fxml的控制器,它是一个。 问题代码是类中的一个成员函数,标记是这样的,我可以通过设置按钮来调用它。 完整的代码可以在https://github.com/SebastianTroy/FactorioManufactur

  • 问题内容: 我创建了一个自定义错误类型来包装错误,以便更轻松地在Golang中进行调试。当有打印错误时它可以工作,但是现在引起了恐慌。 演示版 当我调用一个函数时,它不会返回错误,我仍然应该能够包装该错误。 预期的行为是,如果错误为nil,则应该简单地忽略它,不幸的是,它会做相反的事情。 我希望它能打印出来。而是即使错误为nil也会打印。 问题答案: 正在将err变量与nil进行比较,但实际上它是

  • 问题内容: 我正在使用Servlets&Struts2的混合情况下工作。 我正在调用HTTPServlet,并且正在处理数据。 然后,我需要调用struts API在DB中插入数据。 在那我也使用HTTPSession。 所以我打电话 要获取HttpRequest,然后在该struts动作类中进行会话。 Servlet正在调用Struts Action类。 但 始终返回NULL。 是因为它没有被网

  • 问题内容: 我使用osgi + cdi,并且有以下代码: 而且我有以下tasklist.fxml 但是parent.lookup(“#testComboBox”)返回null。怎么解释呢?我已经多次检查ID的名称。 问题答案: 您可以将所需的逻辑放入控制器类中,而不必使用仅在渲染场景之后才能使用的查找。您可以通过注释将元素从FXML文件注入到控制器类中。 查询通常不可靠,我建议避免使用它们。如果您