使用 HttpClient 时跨活动使用 Cookie [英] Using Cookies across Activities when using HttpClient

查看:21
本文介绍了使用 HttpClient 时跨活动使用 Cookie的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试一个简单的应用程序来读取网站的 HTML,并将其转换为在 Android 中创建一个易于阅读的用户界面(这是学习 android 的练习,而不是制作一个可用的应用程序).我遇到的问题是跨活动保持用户会话,然后在调用后在 HttpClient 中使用该会话.

I'm trying a simple app to read in the HTML of a website, and tranform it to create an easily readable UI in Android (This is an exersize in learning android, not to make a useable app). The problem I'm having is persisting a users session across Activities and then using the session in a HttpClient once recalled.

我想正确地"执行此操作,推荐的方法似乎是使用 CookieManager.但是,我遇到了问题 - 我似乎无法找到从 CookieManager 获取 Cookie 并在以后的 HttpClient 在一个单独的活动中.

I would like to do this "Correctly", the recommended approach seem to be to use CookieManager. I've had problems with this however - I cannot seem to find the "Correct" way to take a Cookie from the CookieManager and use it in a later instantiation of HttpClient in a seperate Activities.

当使用 CookieManager 时,我可以保存 Cookie 并且 Cookie 然后在其他活动的范围内(参见代码片段 2).我还没有找到稍后在请求页面时如何使用它(参见代码片段 3).

When using a CookieManager I can save the Cookie and the Cookie is then in scope in other Activities (See code snippet 2). I haven't found how to use this later (See code snippet 3) when requesting a page.

话不多说,这里是一些代码.首先是我的登录操作和 Cookie 存储:

Enough talking, here is some code. First my login action and Cookie storage:

private OnClickListener loginActionListener = new OnClickListener() 
{
    public void onClick(View v) 
    {
        EditText usernameTextView = (EditText) findViewById(R.id.Username);
        EditText passwordTextView = (EditText) findViewById(R.id.Password);
        String username = usernameTextView.getText().toString();
        String password = passwordTextView.getText().toString();

        try {
            HttpPost postMethod = new HttpPost(URI);                
            HttpParams params   = new BasicHttpParams();

            params.setParameter("mode", "login");
            params.setParameter("autologin", true);
            params.setParameter("username", username);
            params.setParameter("password", password);
            postMethod.setParams(params);

            DefaultHttpClient httpClient = new DefaultHttpClient();
            HttpResponse response        = httpClient.execute(postMethod);
            List<Cookie> cookies = httpClient.getCookieStore().getCookies();

            if(cookies != null)
            {
                for(Cookie cookie : cookies)
                {
                    String cookieString = cookie.getName() + "=" + cookie.getValue() + "; domain=" + cookie.getDomain();                        
                    CookieManager.getInstance().setCookie(cookie.getDomain(), cookieString);  
                }
            }
            CookieSyncManager.getInstance().sync();

            Intent intent = new Intent(v.getContext(), IndexAction.class);
            startActivity(intent);
    } catch (Exception e) {...}
}

决定是让用户登录还是进入索引的启动Activity如下.从这段代码可以看出cookie在作用域内,可以读取:

The startup Activity which decides wether to make the user login or go to the index is below. You can see from this code that the cookie is in scope and can be read:

public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    CookieSyncManager.createInstance(this);

    if(CookieManager.getInstance().getCookie(URI) == null)
    {
        Intent intent = new Intent(this, LoginAction.class);
        startActivity(intent);
    }
    else
    {
        Intent intent = new Intent(this, IndexAction.class);
        startActivity(intent);
    }
}

但是从我阅读索引页面的代码中,我希望您能提出我所缺少的内容:

But from my code to read the Index page I'm hoping you can suggest what i'm missing:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    CookieSyncManager.createInstance(this);

    try
    {
            HttpGet getMethod = new HttpGet(URI_INDEX);  

            HttpParams params   = new BasicHttpParams();                        
            HttpConnectionParams.setConnectionTimeout(params, 30000);
            HttpConnectionParams.setSoTimeout(params, 30000);

            // This code results in a ClassCastException, I'm assuming i've found a red herring with this solution.
            // HttpContext localContext = new BasicHttpContext();    
            // localContext.setAttribute(ClientContext.COOKIE_STORE, CookieManager.getInstance().getCookie(URI));

            DefaultHttpClient httpClient = new DefaultHttpClient(params);
            HttpResponse response        = httpClient.execute(getMethod);

            if(response.getStatusLine().getStatusCode() > 299 && response.getStatusLine().getStatusCode() < 400)
            {
                // Not logged in doesn't give a redirect response. Very annoying.
            }

            final char[] buffer = new char[0x10000];
            StringBuilder out = new StringBuilder();
            Reader in = new InputStreamReader(response.getEntity().getContent(), "UTF-8");
            int read = 0;
            while (read>=0)
            {
              read = in.read(buffer, 0, buffer.length);
              if (read>0) {
                out.append(buffer, 0, read);
              }
            }

            String returnString = out.toString();
    } catch (ClientProtocolException e) {...}
}

execute(getMethod) 上的 HttpClient 没有使用 Cookie(在调试中仔细检查)来拉回页面.如果有人能填补我知识中的这个漏洞,那就太好了.

The HttpClient on execute(getMethod) isn't using the Cookie (double checked this in debug) to pull back the page. It would be great if someone could fill this hole in my knowledge.

提前致谢.

编辑

当注释代码被添加回(将 httpClient.execute(getMethod) 方法更改为 httpClient.execute(getMethod, localContext))时,会生成此跟踪跟踪- 大概是因为我用 Cookie String 而不是 CookieStore 填充属性 ClientContext.COOKIE_STORE:

When commented code is added back in (with the httpClient.execute(getMethod) method change to httpClient.execute(getMethod, localContext)) this strack trace is produced - Assumedly because i'm filling the attribute ClientContext.COOKIE_STORE with a Cookie String rather than a CookieStore:

*org.apache.http.client.protocol.RequestAddCookies.process(RequestAddCookies.java:88), org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor.java:290), org.apache.http.protocol.HttpRequestExecutor.preProcess(HttpRequestExecutor.java:160), org.apache.http.impl.client.DefaultRequestDirector.execute(DefaultRequestDirector.java:401)
org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:555), org.apache.http.impl.client.AbstractHttpClient.execute(AbstractHttpClient.java:487), 
com.testapp.site.name.IndexAction.onCreate(IndexAction.java:47), 
android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1047), 
android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1611), 
android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1663), 
android.app.ActivityThread.access$1500(ActivityThread.java:117), 
android.app.ActivityThread$H.handleMessage(ActivityThread.java:931), 
android.os.Handler.dispatchMessage(Handler.java:99), 
android.os.Looper.loop(Looper.java:123), 
android.app.ActivityThread.main(ActivityThread.java:3683), 
java.lang.reflect.Method.invokeNative(Native Method), 
java.lang.reflect.Method.invoke(Method.java:507), 
com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:839), 
com.android.internal.os.ZygoteInit.main(ZygoteInit.java:597), 
dalvik.system.NativeStart.main(Native Method)*

推荐答案

(正如承诺的解决方案.我仍然不喜欢它,觉得我错过了正确"的做法,但是,它有效.)

(As promised a solution to this. I still don't like it and feel like I'm missing out on the "Correct" way of doing this but, it works.)

您可以使用 CookieManager 通过以下代码注册您的 cookie(从而使这些 cookie 在应用程序之间可用):

You can use the CookieManager to register your cookies (and therefore make these cookies available between apps) with the following code:

将 cookie 保存到 CookieManager:

Saving cookies into the CookieManager:

List<Cookie> cookies = httpClient.getCookieStore().getCookies();

if(cookies != null)
{
    for(Cookie cookie : cookies)
    {
        String cookieString = cookie.getName() + "=" + cookie.getValue() + "; domain=" + cookie.getDomain();                        
        CookieManager.getInstance().setCookie(cookie.getDomain(), cookieString);  
    }
}
CookieSyncManager.getInstance().sync();

检查指定域上的 cookie:if(CookieManager.getInstance().getCookie(URI_FOR_DOMAIN)

Checking for cookies on specified domain: if(CookieManager.getInstance().getCookie(URI_FOR_DOMAIN)

为 HttpClient 重建值:

To reconstruct values for HttpClient:

DefaultHttpClient httpClient = new DefaultHttpClient(params);
String[] keyValueSets = CookieManager.getInstance().getCookie(URI_FOR_DOMAIN).split(";");
for(String cookie : keyValueSets)
{
    String[] keyValue = cookie.split("=");
    String key = keyValue[0];
    String value = "";
    if(keyValue.length>1) value = keyValue[1];
    httpClient.getCookieStore().addCookie(new BasicClientCookie(key, value));
}

这篇关于使用 HttpClient 时跨活动使用 Cookie的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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