Android的HttpClient调用,冲突的解决办法
只适用部分情况
题外话
攻关百度自动发贴作推广失败,但登录已拿下。全扔有点浪费。
在登录的基础上写了个百度的自动签到系统,功能已实现([java,android,nodejs,.net]+nodejs)
用nodejs是我没摸清楚百度的RSA加密算法,试了很多都失败,索性就直接把百度的RSA加密过程提取出来,移到nodejs了(都是JS)。
成功后又想了想,可以把.net实现迁移到JAVA,写个安卓百度签到的APP的应用,练练手复习安卓。
迁到JAVA的过程非常顺利,但是到Android就进了几个坑。
.NET 获取token代码 ,用微软给的HttpWebRequest和 Newtonsoft.Json DLL
1 public string GetToken(CookieContainer cookies) { 2 string token = ""; 3 DateTime dt = DateTime.Now; 4 string tt = TimeUtils.ConvertDateTimeInt(dt).ToString() + "000"; 5 //这一步获取必定失败,更主要是为了获取百度的一些其他信息。 6 token = NetHelper.HttpGet("https://passport.baidu.com/v2/api/?getapi&tpl=tb&apiver=v3&tt=" + tt + "&class=login&logintype=dialogLogin", ref cookies); 7 //这一步会获取成功。 8 token = NetHelper.HttpGet("https://passport.baidu.com/v2/api/?getapi&tpl=tb&apiver=v3&tt=" + tt + "&class=login&logintype=dialogLogin", ref cookies); 9 JObject jo1 = (JObject)JsonConvert.DeserializeObject(token); 10 string tokenstring = jo1["data"]["token"].ToString(); 11 return tokenstring; 12 }
封装的Http API
public static string HttpGet(string Url, ref CookieContainer cookie) { string strResult =string.Empty; try { HttpWebRequest request = (HttpWebRequest)WebRequest.Create(Url); //request.Referer = "http://www.wangpiao.com/movie/25149/?showulcinfo=1"; request.Headers.Set("Pragma", "no-cache"); request.CookieContainer = cookie; HttpWebResponse response = (HttpWebResponse)request.GetResponse(); Stream streamReceive = response.GetResponseStream(); Encoding encoding = Encoding.GetEncoding("UTF-8"); StreamReader streamReader = new StreamReader(streamReceive, encoding); strResult = streamReader.ReadToEnd(); cookie.Add(response.Cookies); } catch (Exception ex) { //MessageBox.Show(ex.ToString()+"出错"); } return strResult; }
迁到JAVA引用Apache httpclient4.3.5,和GSON JSON解析包。
private static String GetTimeString(){ Date now = new Date(); return now.getTime()+""; } public void GetToken()throws Exception { CloseableHttpClient httpclient = HttpClients.custom() .setDefaultCookieStore(cookies) .build(); String tt=GetTimeString(); try { HttpGet httpget = new HttpGet("https://passport.baidu.com/v2/api/?getapi&tpl=tb&apiver=v3&tt=" + tt + "&class=login&logintype=dialogLogin"); CloseableHttpResponse response1 = httpclient.execute(httpget); try { response1 = httpclient.execute(httpget); ByteArrayInputStream bis = new ByteArrayInputStream(EntityUtils.toByteArray(response1.getEntity())); String ss=convertStreamToString(bis).replace("/n", ""); JsonParser jsonparer = new JsonParser();//初始化解析json格式的对象 token = jsonparer.parse(ss).getAsJsonObject().get("data").getAsJsonObject().get("token").getAsString(); } finally { response1.close(); } }finally { httpclient.close(); } } public static String convertStreamToString(InputStream is) { BufferedReader reader = new BufferedReader(new InputStreamReader(is)); StringBuilder sb = new StringBuilder(); String line = null; try { while ((line = reader.readLine()) != null) { sb.append(line + "/n"); } } catch (IOException e) { e.printStackTrace(); } finally { try { is.close(); } catch (IOException e) { e.printStackTrace(); } } return sb.toString(); }
OK,JAVA+NODEJS也已实现。
就差一步了,JAVA到android不是很容易嘛,结果这一步坑了我两个小时
首先 编译不过
之后 运行出错
根本原因都是因为android自带了个httpclient的包。和引用的httpclient4.3.5冲突。
询问得知几种方法
一:有就让用anroid的(这不是费话么,用android的能解决我干嘛要引,android(版本 19)的自带的包不支持cookie,开发要用的)
二:有说拿httpclient4.3.5源码改包名重打包编译的,折腾
三:有说扒个开源实现的(开源中国已扒),自已实现的一个精简的request包,自实现cookie,代码差距太太,几乎要重写,也折腾。
四:这是自已无意翻来的,搜了一个回答说4.3.3不冲突,顺道看了看http://hc.apache.org/downloads.cgi,冲突不冲突,我还不知道,不过眼前一亮,发现了这个
HttpClient for Android 4.3.5 (GA)
这就是主角了,满心欢喜的引了,几翻处理完,OK,编译过了,执行,还是报错
不过这包是直接给的源码,追下去,找到办法了,异常堆栈的大概印象。
Args.NotNull:item may not be null
RegisterBuilder.register Arg.notNull
HttpClientBuilder register("https",sslSocketFactory)
sslSocketFactory 这玩意为null了。
builder里有sslSocketFactory 的新建实例操作,追下去,发现不进。
原因是systemProperties默认的值为false。
搜systemProperties 发现一个方法会设置该值,调用,这下总算是OK了。
对比下
JAVA调用
CloseableHttpClient httpclient = HttpClients.custom()
.setDefaultCookieStore(cookies)
.build();
Android修改为
CloseableHttpClient httpclient = HttpClients.custom().useSystemProperties()
.setDefaultCookieStore(cookies)
.build();
这下一切OK了
对了,Android还要记得设INTERNET权限
android app百度贴吧签到核心功能已实现。