使用Cookie整个活动在使用的HttpClientCookie、HttpClient

2023-09-12 22:45:21 作者:梦见你哭却不能拥抱

我想一个简单的应用程序来读取一个网页的HTML,并变换分析它创建于Android的一个易于阅读的界面(这是学习Android的一个exersize,不使一个可用的应用程序)。我遇到的问题是持续整个活动一个用户会话,然后使用会话所用的的HttpClient 曾回忆道。

我想这样做正确,推荐的方法似乎是使用 CookieManager 。我有问题,然而,这 - 我似乎无法找到正确的方式,采取一个饼干 CookieManager 并在一个单独的活动中使用它的HttpClient 的更高实例。

在使用 CookieManager 我可以保存饼干饼干则是在范围上的其他活动(见code段2)。我还没有找到如何使用这个后面(见code段3)请求一个页面时。

够说话,这里是一些code。首先我的登录操作和Cookie存储:

 私人OnClickListener loginActionListener =新OnClickListener()
{
    公共无效的onClick(视图v)
    {
        EditText上usernameTextView =(EditText上)findViewById(R.id.Username);
        EditText上passwordTextView =(EditText上)findViewById(R.id.Password);
        字符串username = usernameTextView.getText()的toString()。
        字符串password = passwordTextView.getText()的toString()。

        尝试 {
            HttpPost的PostMethod =新HttpPost(URI);
            的HttpParams PARAMS =新BasicHttpParams();

            params.setParameter(模式,密码);
            params.setParameter(自动登录,真正的);
            params.setParameter(用户名,用户名);
            params.setParameter(密码,密码);
            postMethod.setParams(PARAMS);

            DefaultHttpClient的HttpClient =新DefaultHttpClient();
            HTT presponse响应= httpClient.execute(后方法);
            名单<饼干>饼干= httpClient.getCookieStore()的getCookies()。

            如果(饼干!= NULL)
            {
                对于(饼干饼干:饼干)
                {
                    串cookieString = cookie.getName()+=+ cookie.getValue()+;域=+ cookie.getDomain();
                    。CookieManager.getInstance()setCookie方法(cookie.getDomain(),cookieString);
                }
            }
            CookieSyncManager.getInstance()同步()。

            意向意图=新的意图(v.getContext(),IndexAction.class);
            startActivity(意向);
    }赶上(例外五){...}
}
 

的启动活动而决定阉使用户登录或进入指数低于。你可以从这个code。该cookie是在范围和可以读见:

 公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    CookieSyncManager.createInstance(本);

    如果(CookieManager.getInstance()的getCookie(URI)== NULL)
    {
        意向意图=新的意图(这一点,LoginAction.class);
        startActivity(意向);
    }
    其他
    {
        意向意图=新的意图(这一点,IndexAction.class);
        startActivity(意向);
    }
}
 
HttpClient4.5.2 使用cookie保持会话 获取cookie 1

但是从我的code读取索引页,我希望你可以认为我缺少的是什么:

  @覆盖
公共无效的onCreate(包savedInstanceState){
    super.onCreate(savedInstanceState);
    CookieSyncManager.createInstance(本);

    尝试
    {
            HTTPGET GetMethod的=新HTTPGET(URI_INDEX);

            的HttpParams PARAMS =新BasicHttpParams();
            HttpConnectionParams.setConnectionTimeout(PARAMS,30000);
            HttpConnectionParams.setSoTimeout(PARAMS,30000);

            //在一个ClassCastException这code结果,我假设我已经找到了一个红色的鲱鱼与此解决方案。
            // HttpContext的localContext =新BasicHttpContext();
            // localContext.setAttribute(ClientContext.COOKIE_STORE,CookieManager.getInstance()的getCookie(URI)。);

            DefaultHttpClient的HttpClient =新DefaultHttpClient(PARAMS);
            HTT presponse响应= httpClient.execute(GetMethod的);

            如果(response.getStatusLine()的getStatus code()> 299&安培;&安培; response.getStatusLine()的getStatus code()< 400)
            {
                //未登录没有给出一个重定向响应。很烦人。
            }

            最后的char []缓冲区=新的char [0x10000的]。
            StringBuilder的出=新的StringBuilder();
            读者在=新的InputStreamReader(response.getEntity()的getContent(),UTF-8);
            INT读= 0;
            而(读> = 0)
            {
              读= in.read(缓冲,0,buffer.length);
              如果(读> 0){
                out.append(缓冲,0,读);
              }
            }

            串returnString = out.toString();
    }赶上(ClientProtocolException E){...}
}
 

的HttpClient 执行(GetMethod的)未使用的Cookie(双重检查这调试),以拉回来的页面。这将是巨大的,如果有人可以填补这个洞,我的知识。

在此先感谢。

修改

在评论code加回(与 httpClient.execute(GetMethod的)方法更改为 httpClient.execute(GetMethod的, localContext))这STRACK跟踪生产 - Assumedly因为我填的属性 ClientContext.COOKIE_STORE 饼干 字符串,而不是的CookieStore

  * org.apache.http.client.protocol.RequestAddCookies.process(RequestAddCookies.java:88),org.apache.http.protocol.BasicHttpProcessor.process(BasicHttpProcessor.java: 290),org.apache.http.protocol.Htt prequestExecutor preProcess(Htt的prequestExecutor.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(本机方法)
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(本机方法)*
 

解决方案

(如所承诺的解决了这一点。我还是不喜欢它,觉得我错过了这样做的正确的方式,但,它的工作原理。)

您可以使用 CookieManager 来注册你的cookies(从而使可用的应用程序之间的这些饼干)具有以下code:

保存的Cookie到 CookieManager

 名单,其中,饼干>饼干= httpClient.getCookieStore()的getCookies()。

如果(饼干!= NULL)
{
    对于(饼干饼干:饼干)
    {
        串cookieString = cookie.getName()+=+ cookie.getValue()+;域=+ cookie.getDomain();
        。CookieManager.getInstance()setCookie方法(cookie.getDomain(),cookieString);
    }
}
CookieSyncManager.getInstance()同步()。
 

检查指定域的Cookie: 如果(CookieManager.getInstance()的getCookie(URI_FOR_DOMAIN)

要重建值HttpClient的:

  DefaultHttpClient的HttpClient =新DefaultHttpClient(PARAMS);
的String [] keyValueSets = CookieManager.getInstance()的getCookie(URI_FOR_DOMAIN).split(;)。
对于(字符串的Cookie:keyValueSets)
{
    串[]的keyValue = cookie.split(=);
    字符串键=的keyValue [0];
    字符串值=;
    如果(keyValue.length→1)值= keyValue的[1];
    。httpClient.getCookieStore()的addCookie(新BasicClientCookie(键,值));
}
 

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.

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.

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.

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

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

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.

Thanks in advance.

EDIT

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

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

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

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

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

 
精彩推荐