HttpsUrlConnection Android 与本机 Java

HttpsUrlConnection Android vs Native Java

我写了一些代码试图与网站 "as a browser" 通信(就 cookie 和 headers 而言)。我目前有四个请求(GET、POST、POST、GET)。

代码非常简单:打开连接,添加 headers 和 cookie,解析响应。

获取代码:

conn = (HttpsURLConnection) url.openConnection();
conn.setRequestMethod("GET");
conn.setUseCaches(false);
conn.setRequestProperty("User-Agent", userAgent);
conn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
conn.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
if (cookies != null) {
    for (String cookie : this.cookies) {
        conn.addRequestProperty("Cookie", cookie.split(";", 1)[0]);
    }
}
int responseCode = conn.getResponseCode();
BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
String inputLine;
StringBuilder response = new StringBuilder();

while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();

setCookies(conn.getHeaderFields().get("Set-Cookie"));

return response.toString();

POST代码:

conn = (HttpsURLConnection) url.openConnection();
conn.setUseCaches(false);
conn.setRequestMethod("POST");
conn.setRequestProperty("Host", "...");
conn.setRequestProperty("User-Agent", userAgent);
conn.setRequestProperty("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
conn.setRequestProperty("Accept-Language", "en-US,en;q=0.5");
conn.setRequestProperty("Accept-Encoding","identity");
for (String cookie : this.cookies) {
    conn.addRequestProperty("Cookie", cookie.split(";", 1)[0]);
}
conn.setRequestProperty("Connection", "keep-alive");
conn.setRequestProperty("Referer", "https://...");
conn.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
conn.setRequestProperty("Content-Length", Integer.toString(postParams.length()));

conn.setDoOutput(true);
conn.setDoInput(true);

DataOutputStream wr = new DataOutputStream(conn.getOutputStream());
wr.writeBytes(postParams);
wr.flush();
wr.close();

int responseCode = conn.getResponseCode();
InputStream is = responseCode != 400 ? conn.getInputStream() : conn.getErrorStream();
BufferedReader in = new BufferedReader(new InputStreamReader(is));
String inputLine;
StringBuilder response = new StringBuilder();

while ((inputLine = in.readLine()) != null) {
    response.append(inputLine);
}
in.close();

return response.toString();

该程序在我的电脑上运行良好。但是,当 运行 在 Android 设备上安装它时,我在第二个 POST 上遇到多个问题 ;在一台设备上有 Too many redirections 异常,而在另一台设备(这是我关注的设备)上我只是收到 400 Bad Request 尽管在我的电脑上有完全相同的请求 returns 200。

我注意到实际上有两种不同的实现方式:在 PC 上我使用 sun.net.www.protocol.https.DelegateHttpsURLConnection,而在 Android 上它是 com.android.okhttp.internal.http.HttpURLConnectionImpl。 Object conn 在 运行 期间看起来有点不同。但是,我没能找到有意义的区别(如果需要,我可以post这些objects的全部内容);我发现第一个 GET 中设置的 cookie 有所不同,但手动操作导致相同的 400。

我尝试使用 Wireshark 捕获 Android 输出请求,但结果已加密,我未能成功解密。

我基本上想到了两种可能的场景:

  • 找出这些实现之间的差异并采取相应行动。
  • 想办法在 Android 上使用 sun.net.www.protocol.https.DelegateHttpsURLConnection

到目前为止我还没有弄清楚这些。这些实现是否有任何已知的 difference/issue?有没有办法 运行 Android 上的原生 Java 库?任何帮助将不胜感激,谢谢。

是的,这些 SDK 之间存在一些差异,桌面是 Oracle SDK,Android 上是 Google 发布的。

无论如何,在 Android 上进行 http 请求时,建议使用 Retrofit or Volley