Android volley和webview同步cookies
移动开发免不了要与服务器通信,说白了客户端也就是个升级版的浏览器罢了;其实也不算升级,有些地方升级有些地方降级了,哈哈哈;好吧说正事,通常我们与服务器通信为了数据的安全都会有验证,在浏览器中我们登录之后就可以访问任何一个页面;浏览器会保存用户与服务器的一个会话,那么要保证是同一个链接,浏览器每次请求都会携带这个会话(也就是链接)的标识seeeionid;so 我们就可以用同一链接与服务器通信,这样做的好处是减少并发量,避免了服务器的开销;
好吧,那么问题来了我们做客户端在与服务器交互通常不是通过浏览器,而是通过HttpClient或是HttpURLConnection这两种方式;那么就要求我们自己来管理session(其实开发过web的同学很容易理解);
Cookie格式
上图我是请求某服务器在Chrome浏览器中查看请求的头携带的数据,如上图所示,浏览器会发送给服务器一堆数据,当然这些都是我们不关心的(有兴趣的可以去看看HTTP协议);
我们只关心浏览器发送了什么玩意导致可以复用会话,而不用再起连接;好吧那就是Cookie;
**Cookie:**Cookie,有时也用其复数形式Cookies,指某些网站为了辨别用户身份、进行session跟踪而储存在用户本地终端上的数据(通常经过加密)。 —— [ 百度百科 ]
知道了cookie的格式那么问题就好办了,我们只需要以Cookie为key,后面的一长串为value放到http请求头中发送给服务器就可以了;
获取Cookie并发送到服务器
获取Cookie:用户在第一次登录的时候,服务器响应头会返回Cookie,以Set-Cookie为key,后面的内容就是我们接下来请求服务器要发送的内容;值得注意的是Set-Cookie的存在依赖于服务器,不是每次都会返回Set-Cookie;当我们请求携带Cookie的时候服务器响应也许就不会返回Set-Cookie了;
HttpClient获取Cookie并发送:
参考链接:http://blog.csdn.net/yang_734664103/article/details/22025907
说白了总结就如下:
DefaultHttpClient client = new DefaultHttpClient();
CookieStore store = client.getCookieStore();
List<Cookie> list = store.getCookies();
他可以获取到Cookie中精确的内容,我们要发送的是所有的值,而不只是=号后面的;所以把List列表拼接成字符串一起发送到服务端为好;
HttpURLConnection获取Cookie并发送:
参考链接:http://blog.csdn.net/chindroid/article/details/7556363
发现有时候自己也很懒啊,不自己写出来还得参考别人的文章,哈哈:);
Volley方式获取Cookie并发送:
说实在的如今用原生的Http访问网络的方式以及很少了,Android开源的网络框架层出不穷,而且都十分方便;或许有些框架也已经自带了Cookie的功能,下面我们就以Volley为例自定义Post请求,并获取Cookie;
public class StringPostRequest extends StringRequest {
private static final String TAG = "StringPostRequest";
private Map<String, String> mMap;
private Map<String, String> mHeaders = new HashMap<String, String>();
public StringPostRequest(String url, Listener<String> listener,
ErrorListener errorListener, Map<String, String> map) {
super(Request.Method.POST, url, listener, errorListener);
this.mMap = map;
}
@Override
protected Response<String> parseNetworkResponse(NetworkResponse response) {
try {
Map<String, String> responseHeaders = response.headers;
String rawCookies = responseHeaders.get("Set-Cookie");
String dataString = new String(response.data, "UTF-8");
Log.d(TAG, "Cookies:" + rawCookies);
// 获取Cookie值并保存在SharedPreferences中
if (rawCookies != null) {
CustomUtil.save(CustomUtil.COOKIE, rawCookies);
}
return Response.success(dataString,
HttpHeaderParser.parseCacheHeaders(response));
} catch (UnsupportedEncodingException e) {
return Response.error(new ParseError(e));
}
}
@Override
protected Map<String, String> getParams() throws AuthFailureError {
return mMap;
}
@Override
public Map<String, String> getHeaders() throws AuthFailureError {
Log.i(TAG, "保存在SharedPreferences中:" + mHeaders.get("Cookie"));
return mHeaders;
}
/**
* 设置Cookie
*
* @param cookie
*/
public void setSendCookie(String cookie) {
mHeaders.put("Cookie", cookie);
}
}
该代码中就两处parseNetworkResponse中我们第一次登录获取Cookie,在请求其他链接的时候我们在setSendCookie中设置Cookie这样我们也是可以同一个会话中操作了;
App与WebView共存同步Cookie
如今的app已经是以Native为主打,webView辅助显示页面为主要的模式了;那么问题又来了,Native的Cookie如何同步到webview,或者webview的Cookie同步到Native;
给WebView设置Cookie:
CookieManager mCookieManager;
...
public void synCookies() {
CookieSyncManager.createInstance(this);
mCookieManager = CookieManager.getInstance();
mCookieManager.setAcceptCookie(true);
// 每次移除会有Cookie不一致问题,注释该地方
//mCookieManager.removeSessionCookie();// 移除
// Cookie是通过我们Volley活着HttpClient获取的
mCookieManager.setCookie(url, CustomUtil.get(CustomUtil.COOKIE));
CookieSyncManager.getInstance().sync();
}
该方法什么时候调用?在webview.loadUrl()调用之前设置Cookie,这样我们用Native登录的会话也可以在webview中复用了;
获取WebView中的Cookie:
基于上面的方式我们获取CookieManager的实例并在webviewonPageFinished方法中获取Cookie;
mWebView.setWebViewClient(new WebViewClient() {
@Override
public boolean shouldOverrideUrlLoading(WebView view, String url) {
// TODO Auto-generated method stub
return false;
}
@Override
public void onPageFinished(WebView view, String url) {
super.onPageFinished(view, url);
// 获取Cookie
String cookie = mCookieManager.getCookie(url);
Log.i("WebActivity", "cookie:" + cookie);
}
});
同样获取Cookie也可以设置给用Volley或者HttpClient访问服务器的方式了;
总结
Cookie的存在与否取决于服务端的设置,我们客户端也只是接收或者保存服务器的数据;有些人可能会遇到用了以上方式还是不行,那就得与你的服务端开发人员多交流了,他们的设置可能会对客户端或者浏览器产生一定的影响;也希望大家多尝试,原理其实很简单,剩下的就是运用了;