使用 Android Volley 库与 cookies

62

有人知道如何使用com.android.volley库将会话cookie附加到请求中吗? 当我登录网站时,它会给我一个会话cookie。浏览器会将该cookie与任何后续请求一起发送回去。Volley似乎不会自动执行这个操作。

谢谢。


3
这应该是底层的HTTP传输层(例如HttpUrlConnection,HttpClient)的功能,而不是Volley本身。你尝试直接使用它们中的一个了吗? - CommonsWare
CommonsWare,我没有。难道Volley的整个目的不是为了隐藏这种复杂性吗?我已经研究了Volley的选择,但找不到任何访问底层的方法。你有什么建议可以访问底层吗?谢谢。 - Rastio
“难道 Volley 的整个目的不就是为了隐藏这种复杂性吗?”--正如我所写的,据我所知,会话 cookie 是由 HTTP 传输代码处理的。我建议直接尝试其中一个传输方式,以查看您的问题是否仍然存在,如果是,则不是 Volley 的问题,而是 Android 或您的服务器中的某些问题。“你有什么建议如何访问底层?”--暂时将 Volley 放在一边,自己编写“底层”代码。特别是 HttpUrlConnection 已经存在了大约15年,有很多使用示例。 - CommonsWare
6
由于 Cookie 只是一个普通的 HTTP 头,因此您可以使用 NetworkResponse.headers 字段保存此标头,然后通过覆盖 Request.getHeaders 方法将其附加到每个后续请求。 - Vladimir Mironov
对于那些关注这个帖子的人,我有一个后续问题。https://dev59.com/cnbZa4cB1Zd3GeqPBQ15 - TestBest
11个回答

68

Volley本身不会发起HTTP请求,也不会直接管理Cookie。其使用HttpStack的实例来进行这些操作,有两个主要的实现:

  • HurlStack:在后台使用HttpUrlConnection
  • HttpClientStack:在后台使用Apache HttpClient

这些HttpStacks负责管理Cookie,但它们各自处理Cookie的方式不同。

如果您需要支持<2.3版本,则应该使用HttpClientStack:

配置一个HttpClient实例,并将其传递给Volley以在后台使用:

// If you need to directly manipulate cookies later on, hold onto this client
// object as it gives you access to the Cookie Store
DefaultHttpClient httpclient = new DefaultHttpClient();

CookieStore cookieStore = new BasicCookieStore();
httpclient.setCookieStore( cookieStore );

HttpStack httpStack = new HttpClientStack( httpclient );
RequestQueue requestQueue = Volley.newRequestQueue( context, httpStack  );

使用此方法与手动将cookie插入标头相比的优点在于,您可以获得实际的cookie管理。 存储中的cookie将正确响应HTTP控件以使其过期或更新。

我更进一步地对BasicCookieStore进行了子类化,以便我可以自动将我的cookie持久化到磁盘中。

然而! 如果您不需要支持旧版本的Android,请使用此方法:

// CookieStore is just an interface, you can implement it and do things like
// save the cookies to disk or what ever.
CookieStore cookieStore = new MyCookieStore();
CookieManager manager = new CookieManager( cookieStore, CookiePolicy.ACCEPT_ALL );
CookieHandler.setDefault( manager  );

// Optionally, you can just use the default CookieManager
CookieManager manager = new CookieManager();
CookieHandler.setDefault( manager  );

HttpURLConnection会隐式地查询CookieManager。在我的看法中,HttpUrlConnection更高效且实现和使用起来更加简洁。


这对我有用。最终我只使用了默认的CookieManager。需要注意的是,调用CookieHandler.getDefault().put()需要一个Map<String, List<String>>。put()的默认实现从映射中解析出cookie,并要求键为“set-cookie”或“set-cookie2”(不区分大小写)。我不得不查看源代码才发现这一点。 - Jordan
2
@Adam,谢谢,我也使用了默认的CookieManager,现在头部信息是正确的。但是当我重定向到另一个活动时,即使我在活动的onCreate中设置了CookieManager,这些头部信息也不再是请求的一部分了,有没有办法使其在活动之间持久化? - Woppi
1
希望你也与我们分享一下你的MyCookieStore类。 - azerafati

41

vmirinov是正确的!

以下是我解决问题的方法:

请求类:

public class StringRequest extends com.android.volley.toolbox.StringRequest {

    private final Map<String, String> _params;

    /**
     * @param method
     * @param url
     * @param params
     *            A {@link HashMap} to post with the request. Null is allowed
     *            and indicates no parameters will be posted along with request.
     * @param listener
     * @param errorListener
     */
    public StringRequest(int method, String url, Map<String, String> params, Listener<String> listener,
            ErrorListener errorListener) {
        super(method, url, listener, errorListener);

        _params = params;
    }

    @Override
    protected Map<String, String> getParams() {
        return _params;
    }

    /* (non-Javadoc)
     * @see com.android.volley.toolbox.StringRequest#parseNetworkResponse(com.android.volley.NetworkResponse)
     */
    @Override
    protected Response<String> parseNetworkResponse(NetworkResponse response) {
        // since we don't know which of the two underlying network vehicles
        // will Volley use, we have to handle and store session cookies manually
        MyApp.get().checkSessionCookie(response.headers);

        return super.parseNetworkResponse(response);
    }

    /* (non-Javadoc)
     * @see com.android.volley.Request#getHeaders()
     */
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        Map<String, String> headers = super.getHeaders();

        if (headers == null
                || headers.equals(Collections.emptyMap())) {
            headers = new HashMap<String, String>();
        }

        MyApp.get().addSessionCookie(headers);

        return headers;
    }
}

和我的应用程序:

public class MyApp extends Application {
    private static final String SET_COOKIE_KEY = "Set-Cookie";
    private static final String COOKIE_KEY = "Cookie";
    private static final String SESSION_COOKIE = "sessionid";

    private static MyApp _instance;
  private RequestQueue _requestQueue;
  private SharedPreferences _preferences;

    public static MyApp get() {
        return _instance;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        _instance = this;
            _preferences = PreferenceManager.getDefaultSharedPreferences(this);
        _requestQueue = Volley.newRequestQueue(this);
    }

    public RequestQueue getRequestQueue() {
        return _requestQueue;
    }


    /**
     * Checks the response headers for session cookie and saves it
     * if it finds it.
     * @param headers Response Headers.
     */
    public final void checkSessionCookie(Map<String, String> headers) {
        if (headers.containsKey(SET_COOKIE_KEY)
                && headers.get(SET_COOKIE_KEY).startsWith(SESSION_COOKIE)) {
                String cookie = headers.get(SET_COOKIE_KEY);
                if (cookie.length() > 0) {
                    String[] splitCookie = cookie.split(";");
                    String[] splitSessionId = splitCookie[0].split("=");
                    cookie = splitSessionId[1];
                    Editor prefEditor = _preferences.edit();
                    prefEditor.putString(SESSION_COOKIE, cookie);
                    prefEditor.commit();
                }
            }
    }

    /**
     * Adds session cookie to headers if exists.
     * @param headers
     */
    public final void addSessionCookie(Map<String, String> headers) {
        String sessionId = _preferences.getString(SESSION_COOKIE, "");
        if (sessionId.length() > 0) {
            StringBuilder builder = new StringBuilder();
            builder.append(SESSION_COOKIE);
            builder.append("=");
            builder.append(sessionId);
            if (headers.containsKey(COOKIE_KEY)) {
                builder.append("; ");
                builder.append(headers.get(COOKIE_KEY));
            }
            headers.put(COOKIE_KEY, builder.toString());
        }
    }

}

2
请注意,头部可能会返回为“Set-Cookie”,就像您现在写的一样,或者是“set-cookie” - 在这种情况下,此代码将无法正常运行。 - Sam Dozor
对于那些关注这个问题的人,我有一个后续问题。https://dev59.com/cnbZa4cB1Zd3GeqPBQ15 - TestBest
@TestBest,将cookie存储在首选项中可以使其在应用退出后仍然存在。如果您希望会话cookie持续时间超过一个应用程序运行,则可以自行选择。 - Rastio
1
请注意,如果有多个cookie,则会有多个“Set-Cookie”标头,并且由于响应标头是Map,因此您只会得到第一个!是的,这个Volley库缺少一些东西。在这个问题上进行了讨论:https://dev59.com/NmMk5IYBdhLWcg3wxAhM - georgiecasey
我刚刚将SESSION_COOKIE的内容更改为"PHPSESSID",它可以正常工作。 - FinalDark
显示剩余3条评论

20

7
默认的传输实现实际上取决于特定设备的Android版本(对于Gingerbread及以上版本使用HttpUrlConnection,而对于早期版本使用HttpClient),您不应该依赖它。 - Vladimir Mironov
这就是我的理解。如果Volley选择HttpUrlConnection,那么Commons Ware的回答是正确的。这就是为什么我期望Volley会处理它。我将离开电脑几天,等回来后看看是否有一些继承可以帮助解决。 - Rastio
请注意,如果您没有显式地向newRequestQueue传递HttpStack,则默认的传输方式在Volley助手类中指定,https://android.googlesource.com/platform/frameworks/volley/+/master/src/com/android/volley/toolbox/Volley.java。编写自己版本的newRequestQueue助手方法很简单,无论使用HurlStack还是HttpClientStack,都可以正确执行。 - adevine
好的。那么有没有一种方法可以选择会话cookie,适用于HttpURLConnection和HttpClient两种类型的客户端?请查看我的后续问题:https://dev59.com/cnbZa4cB1Zd3GeqPBQ15 - TestBest
4
目前运行Gingerbread以下版本的Android用户所占比例为2.2%。我个人并不关心他们。因此,我同意CommonsWare的观点,并在HurlStack构造函数中添加了CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));。效果很好。 - georgiecasey
显示剩余2条评论

16

大家在你们的 AppController.javaonCreate 方法中尝试这个。

  CookieHandler.setDefault(new CookieManager());

希望这能为开发人员节省时间。我已经浪费了四个小时来调试和寻找合适的解决方案。


10

@Rastio的解决方案无法处理存在多个'Set-Cookie'头的情况。我包装了默认的CookieManager cookie存储器,在添加cookie之前,我使用Gson将其序列化并保存在SharedPreferences中。

这是一个cookie存储器包装器的示例:

import android.content.Context;
import android.net.Uri;
import android.util.Log;

import com.google.gson.Gson;

import java.net.CookieManager;
import java.net.CookieStore;
import java.net.HttpCookie;
import java.net.URI;
import java.util.List;

/**
 * Class that implements CookieStore interface. This class saves to SharedPreferences the session
 * cookie.
 *
 * Created by lukas.
 */
public class PersistentCookieStore implements CookieStore {

    private CookieStore mStore;
    private Context mContext;
    private Gson mGson;

    public PersistentCookieStore(Context context) {
        // prevent context leaking by getting the application context
        mContext = context.getApplicationContext();
        mGson = new Gson();

        // get the default in memory store and if there is a cookie stored in shared preferences,
        // we added it to the cookie store
        mStore = new CookieManager().getCookieStore();
        String jsonSessionCookie = Prefs.getJsonSessionCookie(mContext);
        if (!jsonSessionCookie.equals(Prefs.DEFAULT_STRING)) {
            HttpCookie cookie = mGson.fromJson(jsonSessionCookie, HttpCookie.class);
            mStore.add(URI.create(cookie.getDomain()), cookie);
        }
    }

    @Override
    public void add(URI uri, HttpCookie cookie) {
        if (cookie.getName().equals("sessionid")) {
            // if the cookie that the cookie store attempt to add is a session cookie,
            // we remove the older cookie and save the new one in shared preferences
            remove(URI.create(cookie.getDomain()), cookie);
            Prefs.saveJsonSessionCookie(mContext, mGson.toJson(cookie));
        }

        mStore.add(URI.create(cookie.getDomain()), cookie);
    }

    @Override
    public List<HttpCookie> get(URI uri) {
        return mStore.get(uri);
    }

    @Override
    public List<HttpCookie> getCookies() {
        return mStore.getCookies();
    }

    @Override
    public List<URI> getURIs() {
        return mStore.getURIs();
    }

    @Override
    public boolean remove(URI uri, HttpCookie cookie) {
        return mStore.remove(uri, cookie);
    }

    @Override
    public boolean removeAll() {
        return mStore.removeAll();
    }
}

然后,要使用cookie存储,只需在CookieManager中设置即可!

CookieManager cookieManager = new CookieManager(new PersistentCookieStore(mContext),
    CookiePolicy.ACCEPT_ORIGINAL_SERVER);
CookieHandler.setDefault(cookieManager);

在PersistentCookieStore的构造函数中,我认为我们需要从SharedPreferences获取存储的cookie列表(不仅仅是一个cookie)。你觉得呢?此外,每次更新mStore时,我们也需要更新SharedPreferences。 - Mr Cold
@Lukas,你能详细说明一下你的例子吗?我的意思是,你是如何将这些多个Cookie保存在共享首选项中的? - aB9

5
我知道这篇文章有些旧了,但我们最近遇到了一个问题,需要在服务器之间共享已登录用户的会话,而服务器端的解决方案开始要求客户端通过cookie提供一个值。 我们找到的一个解决方案是向RequestQueue对象添加一个参数,在下面链接中的getRequestQueue方法中的代码片段中实例化RequestQueue之前解决了这个问题,不确定是如何解决的,但它开始工作了。
请访问http://woxiangbo.iteye.com/blog/1769122
public class App extends Application {

    public static final String TAG = App.class.getSimpleName();

    private static App         mInstance;

    public static synchronized App getInstance() {
        return App.mInstance;
    }

    private RequestQueue mRequestQueue;

    public <T> void addToRequestQueue( final Request<T> req ) {
        req.setTag( App.TAG );
        this.getRequestQueue().add( req );
    }

    public <T> void addToRequestQueue( final Request<T> req, final String tag ) {
        req.setTag( TextUtils.isEmpty( tag ) ? App.TAG : tag );
        this.getRequestQueue().add( req );
    }

    public void cancelPendingRequests( final Object tag ) {
        if ( this.mRequestQueue != null ) {
            this.mRequestQueue.cancelAll( tag );
        }
    }

    public RequestQueue getRequestQueue() {

        if ( this.mRequestQueue == null ) {


            DefaultHttpClient mDefaultHttpClient = new DefaultHttpClient();

            final ClientConnectionManager mClientConnectionManager = mDefaultHttpClient.getConnectionManager();
            final HttpParams mHttpParams = mDefaultHttpClient.getParams();
            final ThreadSafeClientConnManager mThreadSafeClientConnManager = new ThreadSafeClientConnManager( mHttpParams, mClientConnectionManager.getSchemeRegistry() );

            mDefaultHttpClient = new DefaultHttpClient( mThreadSafeClientConnManager, mHttpParams );

            final HttpStack httpStack = new HttpClientStack( mDefaultHttpClient );

            this.mRequestQueue = Volley.newRequestQueue( this.getApplicationContext(), httpStack );
        }

        return this.mRequestQueue;
    }

    @Override
    public void onCreate() {
        super.onCreate();
        App.mInstance = this;
    }
}

//设置令牌值

ObjectRequest.setHeader( "Cookie", "JSESSIONID=" + tokenValueHere );

你在哪里添加 cookies? - AZ_
非常感谢 ObjectRequest.setHeader("Cookie", "JSESSIONID=" + tokenValueHere); 这行代码救了我的一天。@AndersonK - naresh vadlakonda

2
使用这种方法使用带有cookie的Volley,以便于:
  1. 仅使用经过充分测试的Apache 2许可证下的代码
  2. 同时发出尽可能多的请求
  3. 确保cookie在设备上持久存在
  4. 不必重复发明轮子

我的服务器使用cookie进行身份验证,我想确保cookie在设备上持久存在。因此,我的解决方案是使用PersistentCookieStoreSerializableCookie类来自Android异步Http客户端

首先,为了实现并发请求,需要一个适用于Android的Apache HttpClient v4.3端口——系统自带的已过时。更多信息请见此处。我使用Gradle导入它的方式如下:
dependencies {
    compile group: 'org.apache.httpcomponents' , name: 'httpclient-android' , version: '4.3.3'
}

获取 RequestQueue 的函数(在我的继承 Application 的类中):
private RequestQueue mRequestQueue;
private CloseableHttpClient httpClient;

...

public RequestQueue getRequestQueue() {
    if (mRequestQueue == null) {
        httpClient = HttpClients.custom()
            .setConnectionManager(new PoolingHttpClientConnectionManager())
            .setDefaultCookieStore(new PersistentCookieStore(getApplicationContext()))
            .build();
        mRequestQueue = Volley.newRequestQueue(getApplicationContext(), new HttpClientStack(httpClient));
    }
    return mRequestQueue;
}

这是我如何排队请求。
public <T> void addToRequestQueue(Request<T> req, String tag) {
    req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
    getRequestQueue().add(req);
}

这就是了!

setDefaultCookieStore不能将PersistentCookieStore作为参数。 - josh123a123
不确定您的意思 - 那正是我运行的代码。它一直很好用。但这个答案可能与早期版本的Volley有关。 - C0D3LIC1OU5

2

姜饼+Android版本:

还有一种简单的方法来维护Cookie会话,那就是在扩展APPLICATION类的类中添加以下行:

CookieHandler.setDefault(new CookieManager(null, CookiePolicy.ACCEPT_ALL));

1
如果您已经开始使用Loopj库来实现应用程序,您会注意到在Volley.newRequestQueue()中无法使用new HttpClient实例,因为您会收到关于未关闭先前连接等各种错误。
例如:

诸如以下错误:

java.lang.IllegalStateException: No wrapped connection

Invalid use of SingleClientConnManager: connection still allocated.

现在有时候需要时间来重构所有旧的API调用并使用volley进行重写,但是您可以同时使用volley和loopj,并在这两者之间共享一个cookiestore,直到您将所有内容都写入volley(使用volley代替loopj,它更好:))。
以下是如何使用loopj共享HttpClient和CookieStore与volley。
// For example you initialize loopj first
private static AsyncHttpClient client = new AsyncHttpClient();
sCookieStore = new PersistentCookieStore(getSomeContextHere());
client.setTimeout(DEFAULT_TIMEOUT);
client.setMaxConnections(12);
client.setCookieStore(sCookieStore);
client.setThreadPool(((ThreadPoolExecutor) Executors.newCachedThreadPool()));

public static RequestQueue getRequestQueue(){
    if(mRequestQueue == null){

    HttpClient httpclient = KkstrRestClient.getClient().getHttpClient();

    ((AbstractHttpClient) httpclient).setCookieStore( ApplicationController.getCookieStore() );

    HttpStack httpStack = new HttpClientStack(httpclient);

    mRequestQueue = Volley.newRequestQueue(getContext(), httpStack);
    }

    return mRequestQueue;
}

这件事发生在我身上,我们开始使用loopj。经过50000行代码的编写和发现loopj并不总是按照预期工作后,我们决定转向Volley。


谢谢,你让我找到了解决一个令人恼火的 bug 的正确方法。我的应用程序中同时使用了 Loopj 和 Volley,而且两者都需要(别问为什么!)。虽然你提供的确切答案没有起作用,但这个答案却行得通,思路相同,只是获取了一个线程安全的 DefaultHttpClient 以用于 Volley cookies:https://dev59.com/questions/AW445IYBdhLWcg3w9O0s#6737645 - georgiecasey

0

@CommonsWare的回答是我会使用的。然而,看起来KitKat在这样做时存在一些错误(当您创建具有自定义CookieStoreCookieManager时,如果您想要持久的Cookies,则需要它)。 鉴于无论使用的CookieStore的实现如何,Volley都会抛出NullpointerException,因此我不得不创建自己的CookieHandler……如果您觉得有用,请使用它。

public class MyCookieHandler extends CookieHandler {

private static final String VERSION_ZERO_HEADER = "Set-cookie";

private static final String VERSION_ONE_HEADER = "Set-cookie2";
private static final String COOKIE_HEADER = "Cookie";

private static final String COOKIE_FILE = "Cookies";
private Map<String, Map<String, HttpCookie>> urisMap;

private Context context;

public MyCookieHandler(Context context) {

    this.context = context;
    loadCookies();

}

@SuppressWarnings("unchecked")
private void loadCookies() {
    File file = context.getFileStreamPath(COOKIE_FILE);
    if (file.exists())
        try {

            FileInputStream fis = context.openFileInput(COOKIE_FILE);
            BufferedReader br = new BufferedReader(new InputStreamReader(
                    fis));
            String line = br.readLine();
            StringBuilder sb = new StringBuilder();
            while (line != null) {
                sb.append(line);
                line = br.readLine();
            }
            Log.d("MyCookieHandler.loadCookies", sb.toString());
            JSONObject jsonuris = new JSONObject(sb.toString());
            urisMap = new HashMap<String, Map<String, HttpCookie>>();
            Iterator<String> jsonurisiter = jsonuris.keys();

            while (jsonurisiter.hasNext()) {
                String prop = jsonurisiter.next();
                HashMap<String, HttpCookie> cookiesMap = new HashMap<String, HttpCookie>();
                JSONObject jsoncookies = jsonuris.getJSONObject(prop);
                Iterator<String> jsoncookiesiter = jsoncookies.keys();
                while (jsoncookiesiter.hasNext()) {
                    String pprop = jsoncookiesiter.next();
                    cookiesMap.put(pprop,
                            jsonToCookie(jsoncookies.getJSONObject(pprop)));
                }
                urisMap.put(prop, cookiesMap);

            }

        } catch (Exception e) {

            e.printStackTrace();
        }
    else {
        urisMap = new HashMap<String, Map<String, HttpCookie>>();
    }
}

@Override
public Map<String, List<String>> get(URI arg0,
        Map<String, List<String>> arg1) throws IOException {
    Log.d("MyCookieHandler.get",
            "getting Cookies for domain: " + arg0.getHost());
    Map<String, HttpCookie> cookies = urisMap.get(arg0.getHost());
    if (cookies != null)
        for (Entry<String, HttpCookie> cookie : cookies.entrySet()) {
            if (cookie.getValue().hasExpired()) {
                cookies.remove(cookie.getKey());
            }
        }

    if (cookies == null || cookies.isEmpty()) {
        Log.d("MyCookieHandler.get", "======");
        return Collections.emptyMap();
    }
    Log.d("MyCookieHandler.get",
            "Cookie : " + TextUtils.join("; ", cookies.values()));
    Log.d("MyCookieHandler.get", "======");
    return Collections.singletonMap(COOKIE_HEADER, Collections
            .singletonList(TextUtils.join("; ", cookies.values())));
}

@Override
public void put(URI uri, Map<String, List<String>> arg1) throws IOException {
    Map<String, HttpCookie> cookies = parseCookies(arg1);
    Log.d("MyCookieHandler.put",
            "saving Cookies for domain: " + uri.getHost());

    addCookies(uri, cookies);
    Log.d("MyCookieHandler.put",
            "Cookie : " + TextUtils.join("; ", cookies.values()));
    Log.d("MyCookieHandler.put", "======");

}

private void addCookies(URI uri, Map<String, HttpCookie> cookies) {
    if (!cookies.isEmpty()) {
        if (urisMap.get(uri.getHost()) == null) {
            urisMap.put(uri.getHost(), cookies);
        } else {
            urisMap.get(uri.getHost()).putAll(cookies);
        }
        saveCookies();
    }
}

private void saveCookies() {
    try {
        FileOutputStream fos = context.openFileOutput(COOKIE_FILE,
                Context.MODE_PRIVATE);

        JSONObject jsonuris = new JSONObject();
        for (Entry<String, Map<String, HttpCookie>> uris : urisMap
                .entrySet()) {
            JSONObject jsoncookies = new JSONObject();
            for (Entry<String, HttpCookie> savedCookies : uris.getValue()
                    .entrySet()) {
                jsoncookies.put(savedCookies.getKey(),
                        cookieToJson(savedCookies.getValue()));
            }
            jsonuris.put(uris.getKey(), jsoncookies);
        }
        fos.write(jsonuris.toString().getBytes());
        fos.close();
        Log.d("MyCookieHandler.addCookies", jsonuris.toString());
    } catch (Exception e) {
        e.printStackTrace();
    }
}

private static JSONObject cookieToJson(HttpCookie cookie) {
    JSONObject jsoncookie = new JSONObject();
    try {
        jsoncookie.put("discard", cookie.getDiscard());
        jsoncookie.put("maxAge", cookie.getMaxAge());
        jsoncookie.put("secure", cookie.getSecure());
        jsoncookie.put("version", cookie.getVersion());
        jsoncookie.put("comment", cookie.getComment());
        jsoncookie.put("commentURL", cookie.getCommentURL());
        jsoncookie.put("domain", cookie.getDomain());
        jsoncookie.put("name", cookie.getName());
        jsoncookie.put("path", cookie.getPath());
        jsoncookie.put("portlist", cookie.getPortlist());
        jsoncookie.put("value", cookie.getValue());

    } catch (JSONException e) {

        e.printStackTrace();
    }

    return jsoncookie;
}

private static HttpCookie jsonToCookie(JSONObject jsonObject) {
    HttpCookie httpCookie;
    try {
        httpCookie = new HttpCookie(jsonObject.getString("name"),
                jsonObject.getString("value"));
        if (jsonObject.has("comment"))
            httpCookie.setComment(jsonObject.getString("comment"));
        if (jsonObject.has("commentURL"))
            httpCookie.setCommentURL(jsonObject.getString("commentURL"));
        if (jsonObject.has("discard"))
            httpCookie.setDiscard(jsonObject.getBoolean("discard"));
        if (jsonObject.has("domain"))
            httpCookie.setDomain(jsonObject.getString("domain"));
        if (jsonObject.has("maxAge"))
            httpCookie.setMaxAge(jsonObject.getLong("maxAge"));
        if (jsonObject.has("path"))
            httpCookie.setPath(jsonObject.getString("path"));
        if (jsonObject.has("portlist"))
            httpCookie.setPortlist(jsonObject.getString("portlist"));
        if (jsonObject.has("secure"))
            httpCookie.setSecure(jsonObject.getBoolean("secure"));
        if (jsonObject.has("version"))
            httpCookie.setVersion(jsonObject.getInt("version"));
        return httpCookie;
    } catch (JSONException e) {

        e.printStackTrace();
    }
    return null;

}

private Map<String, HttpCookie> parseCookies(Map<String, List<String>> map) {
    Map<String, HttpCookie> response = new HashMap<String, HttpCookie>();

    for (Entry<String, List<String>> e : map.entrySet()) {
        String key = e.getKey();
        if (key != null
                && (key.equalsIgnoreCase(VERSION_ONE_HEADER) || key
                        .equalsIgnoreCase(VERSION_ZERO_HEADER))) {
            for (String cookie : e.getValue()) {
                try {
                    for (HttpCookie htpc : HttpCookie.parse(cookie)) {
                        response.put(htpc.getName(), htpc);
                    }
                } catch (Exception e1) {

                    Log.e("MyCookieHandler.parseCookies",
                            "Error parsing cookies", e1);
                }
            }

        }
    }
    return response;

}
}

这个答案并没有经过彻底的测试。我使用JSON来序列化Cookies,因为这个类没有实现Serializable接口,而且是final类型。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接