在本文中,我们将给您介绍关于如何在android中为HttpsUrlConnection禁用SSLv3?的详细内容,并且为您解答androidurlconnection的相关问题,此外,我们还将为您提
在本文中,我们将给您介绍关于如何在android中为HttpsUrlConnection禁用SSLv3?的详细内容,并且为您解答android urlconnection的相关问题,此外,我们还将为您提供关于Android 9.0/P 版本推荐使用 HttpURLConnection、Android http HttpURLConnection、Android HttpURLConnection、Android HTTPUrlConnection POST的知识。
本文目录一览:- 如何在android中为HttpsUrlConnection禁用SSLv3?(android urlconnection)
- Android 9.0/P 版本推荐使用 HttpURLConnection
- Android http HttpURLConnection
- Android HttpURLConnection
- Android HTTPUrlConnection POST
如何在android中为HttpsUrlConnection禁用SSLv3?(android urlconnection)
我们在android中编写了客户端应用程序,该应用程序使用HttpsUrlConnection API与https服务器连接。由于Poodle漏洞,我们需要在调用任何请求时从启用的协议列表中禁用SSLv3。
我们遵循了oracle捕获的准则
并在调用URL连接之前添加了以下行
java.lang.System.setProperty("https.protocols", "TLSv1");
该解决方案可以在普通的Java程序中正常工作。当尝试连接仅适用于SSLv3协议的服务器时,
我们遇到了问题SSLHandShakeException。
但需要注意的是:相同的修复不适用于android。我是否缺少某些东西,还是应该尝试另一种Android方法?请提出建议。
答案1
小编典典通过使用wireshark分析数据包,我找到了解决方案。我发现,在建立安全连接的同时,android从TLSv1退回到SSLv3。这是Android版本<4.4中的错误,可以通过从“启用的协议”列表中删除SSLv3协议来解决。我制作了一个名为NoSSLv3SocketFactory.java的自定义socketFactory类。使用它来创建一个套接字工厂。
/*Copyright 2015 Bhavit Singh SengarLicensed under the Apache License, Version 2.0 (the "License");you may not use this file except in compliance with the License.You may obtain a copy of the License athttp://www.apache.org/licenses/LICENSE-2.0Unless required by applicable law or agreed to in writing, softwaredistributed under the License is distributed on an "AS IS" BASIS,WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.See the License for the specific language governing permissions andlimitations under the License.*/import java.io.IOException;import java.io.InputStream;import java.io.OutputStream;import java.net.InetAddress;import java.net.Socket;import java.net.SocketAddress;import java.net.SocketException;import java.nio.channels.SocketChannel;import java.util.ArrayList;import java.util.Arrays;import java.util.List;import javax.net.ssl.HandshakeCompletedListener;import javax.net.ssl.HttpsURLConnection;import javax.net.ssl.SSLSession;import javax.net.ssl.SSLSocket;import javax.net.ssl.SSLSocketFactory;public class NoSSLv3SocketFactory extends SSLSocketFactory{ private final SSLSocketFactory delegate;public NoSSLv3SocketFactory() { this.delegate = HttpsURLConnection.getDefaultSSLSocketFactory();}public NoSSLv3SocketFactory(SSLSocketFactory delegate) { this.delegate = delegate;}@Overridepublic String[] getDefaultCipherSuites() { return delegate.getDefaultCipherSuites();}@Overridepublic String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites();}private Socket makeSocketSafe(Socket socket) { if (socket instanceof SSLSocket) { socket = new NoSSLv3SSLSocket((SSLSocket) socket); } return socket;}@Overridepublic Socket createSocket(Socket s, String host, int port, boolean autoClose) throws IOException { return makeSocketSafe(delegate.createSocket(s, host, port, autoClose));}@Overridepublic Socket createSocket(String host, int port) throws IOException { return makeSocketSafe(delegate.createSocket(host, port));}@Overridepublic Socket createSocket(String host, int port, InetAddress localHost, int localPort) throws IOException { return makeSocketSafe(delegate.createSocket(host, port, localHost, localPort));}@Overridepublic Socket createSocket(InetAddress host, int port) throws IOException { return makeSocketSafe(delegate.createSocket(host, port));}@Overridepublic Socket createSocket(InetAddress address, int port, InetAddress localAddress, int localPort) throws IOException { return makeSocketSafe(delegate.createSocket(address, port, localAddress, localPort));}private class NoSSLv3SSLSocket extends DelegateSSLSocket { private NoSSLv3SSLSocket(SSLSocket delegate) { super(delegate); } @Override public void setEnabledProtocols(String[] protocols) { if (protocols != null && protocols.length == 1 && "SSLv3".equals(protocols[0])) { List<String> enabledProtocols = new ArrayList<String>(Arrays.asList(delegate.getEnabledProtocols())); if (enabledProtocols.size() > 1) { enabledProtocols.remove("SSLv3"); System.out.println("Removed SSLv3 from enabled protocols"); } else { System.out.println("SSL stuck with protocol available for " + String.valueOf(enabledProtocols)); } protocols = enabledProtocols.toArray(new String[enabledProtocols.size()]); } super.setEnabledProtocols(protocols); }}public class DelegateSSLSocket extends SSLSocket { protected final SSLSocket delegate; DelegateSSLSocket(SSLSocket delegate) { this.delegate = delegate; } @Override public String[] getSupportedCipherSuites() { return delegate.getSupportedCipherSuites(); } @Override public String[] getEnabledCipherSuites() { return delegate.getEnabledCipherSuites(); } @Override public void setEnabledCipherSuites(String[] suites) { delegate.setEnabledCipherSuites(suites); } @Override public String[] getSupportedProtocols() { return delegate.getSupportedProtocols(); } @Override public String[] getEnabledProtocols() { return delegate.getEnabledProtocols(); } @Override public void setEnabledProtocols(String[] protocols) { delegate.setEnabledProtocols(protocols); } @Override public SSLSession getSession() { return delegate.getSession(); } @Override public void addHandshakeCompletedListener(HandshakeCompletedListener listener) { delegate.addHandshakeCompletedListener(listener); } @Override public void removeHandshakeCompletedListener(HandshakeCompletedListener listener) { delegate.removeHandshakeCompletedListener(listener); } @Override public void startHandshake() throws IOException { delegate.startHandshake(); } @Override public void setUseClientMode(boolean mode) { delegate.setUseClientMode(mode); } @Override public boolean getUseClientMode() { return delegate.getUseClientMode(); } @Override public void setNeedClientAuth(boolean need) { delegate.setNeedClientAuth(need); } @Override public void setWantClientAuth(boolean want) { delegate.setWantClientAuth(want); } @Override public boolean getNeedClientAuth() { return delegate.getNeedClientAuth(); } @Override public boolean getWantClientAuth() { return delegate.getWantClientAuth(); } @Override public void setEnableSessionCreation(boolean flag) { delegate.setEnableSessionCreation(flag); } @Override public boolean getEnableSessionCreation() { return delegate.getEnableSessionCreation(); } @Override public void bind(SocketAddress localAddr) throws IOException { delegate.bind(localAddr); } @Override public synchronized void close() throws IOException { delegate.close(); } @Override public void connect(SocketAddress remoteAddr) throws IOException { delegate.connect(remoteAddr); } @Override public void connect(SocketAddress remoteAddr, int timeout) throws IOException { delegate.connect(remoteAddr, timeout); } @Override public SocketChannel getChannel() { return delegate.getChannel(); } @Override public InetAddress getInetAddress() { return delegate.getInetAddress(); } @Override public InputStream getInputStream() throws IOException { return delegate.getInputStream(); } @Override public boolean getKeepAlive() throws SocketException { return delegate.getKeepAlive(); } @Override public InetAddress getLocalAddress() { return delegate.getLocalAddress(); } @Override public int getLocalPort() { return delegate.getLocalPort(); } @Override public SocketAddress getLocalSocketAddress() { return delegate.getLocalSocketAddress(); } @Override public boolean getOOBInline() throws SocketException { return delegate.getOOBInline(); } @Override public OutputStream getOutputStream() throws IOException { return delegate.getOutputStream(); } @Override public int getPort() { return delegate.getPort(); } @Override public synchronized int getReceiveBufferSize() throws SocketException { return delegate.getReceiveBufferSize(); } @Override public SocketAddress getRemoteSocketAddress() { return delegate.getRemoteSocketAddress(); } @Override public boolean getReuseAddress() throws SocketException { return delegate.getReuseAddress(); } @Override public synchronized int getSendBufferSize() throws SocketException { return delegate.getSendBufferSize(); } @Override public int getSoLinger() throws SocketException { return delegate.getSoLinger(); } @Override public synchronized int getSoTimeout() throws SocketException { return delegate.getSoTimeout(); } @Override public boolean getTcpNoDelay() throws SocketException { return delegate.getTcpNoDelay(); } @Override public int getTrafficClass() throws SocketException { return delegate.getTrafficClass(); } @Override public boolean isBound() { return delegate.isBound(); } @Override public boolean isClosed() { return delegate.isClosed(); } @Override public boolean isConnected() { return delegate.isConnected(); } @Override public boolean isInputShutdown() { return delegate.isInputShutdown(); } @Override public boolean isOutputShutdown() { return delegate.isOutputShutdown(); } @Override public void sendUrgentData(int value) throws IOException { delegate.sendUrgentData(value); } @Override public void setKeepAlive(boolean keepAlive) throws SocketException { delegate.setKeepAlive(keepAlive); } @Override public void setOOBInline(boolean oobinline) throws SocketException { delegate.setOOBInline(oobinline); } @Override public void setPerformancePreferences(int connectionTime, int latency, int bandwidth) { delegate.setPerformancePreferences(connectionTime, latency, bandwidth); } @Override public synchronized void setReceiveBufferSize(int size) throws SocketException { delegate.setReceiveBufferSize(size); } @Override public void setReuseAddress(boolean reuse) throws SocketException { delegate.setReuseAddress(reuse); } @Override public synchronized void setSendBufferSize(int size) throws SocketException { delegate.setSendBufferSize(size); } @Override public void setSoLinger(boolean on, int timeout) throws SocketException { delegate.setSoLinger(on, timeout); } @Override public synchronized void setSoTimeout(int timeout) throws SocketException { delegate.setSoTimeout(timeout); } @Override public void setTcpNoDelay(boolean on) throws SocketException { delegate.setTcpNoDelay(on); } @Override public void setTrafficClass(int value) throws SocketException { delegate.setTrafficClass(value); } @Override public void shutdownInput() throws IOException { delegate.shutdownInput(); } @Override public void shutdownOutput() throws IOException { delegate.shutdownOutput(); } @Override public String toString() { return delegate.toString(); } @Override public boolean equals(Object o) { return delegate.equals(o); }}}
在连接时像这样使用此类:
SSLContext sslcontext = SSLContext.getInstance("TLSv1"); sslcontext.init(null, null, null); SSLSocketFactory NoSSLv3Factory = new NoSSLv3SocketFactory(sslcontext.getSocketFactory()); HttpsURLConnection.setDefaultSSLSocketFactory(NoSSLv3Factory); l_connection = (HttpsURLConnection) l_url.openConnection(); l_connection.connect();
更新:
现在,正确的解决方案是使用Google Play服务安装更新的安全提供程序:
ProviderInstaller.installIfNeeded(getApplicationContext());
这有效地使您的应用程序可以访问较新版本的OpenSSL和Java安全提供程序,其中包括对SSLEngine中的TLSv1.2的支持。一旦安装了新的提供程序,就可以创建SSLEngine,以通常的方式支持SSLv3,TLSv1,TLSv1.1和TLSv1.2:
SSLContext sslContext = SSLContext.getInstance("TLSv1.2"); sslContext.init(null, null, null); SSLEngine engine = sslContext.createSSLEngine();
或者,您可以使用来限制已启用的协议engine.setEnabledProtocols。
不要忘记添加以下依赖项(在此处找到最新版本):
compile ''com.google.android.gms:play-services-auth:11.8.0''
Android 9.0/P 版本推荐使用 HttpURLConnection
早在几年前,谷歌就推荐在 Android2.3 版本以上使用 HttpURLConnection,而在即将正式发布的 Android P 版本中,谷歌彻底取消了对 Apache HTTPClient 的支持,针对此更改,开发者该如何正确适配 Android P ?
一、背景
1. 参考谷歌提供的 Android P 版本变更说明文档:
https://developer.android.com/preview/behavior-changes#apache-nonp
https://developer.android.com/preview/behavior-changes#apache-p
2.Android 6.0 版本已移除对 Apache HTTP 客户端的支持
https://developer.android.com/about/versions/marshmallow/android-6.0-changes
Android 6.0 版本移除了对 Apache HTTP 客户端的支持。如果您的应用使用该客户端,并以 Android 2.3(API 级别为 9)或更高版本为目标平台,请改用 HttpURLConnection 类。此 API 效率更高,能够通过透明压缩和响应缓存减少网络使用,并可最大限度降低耗电量。要继续使用 Apache HTTP API,须先在 build.gradle 文件中声明以下编译时依赖项:
android {
useLibrary ''org.apache.http.legacy''
}
3.P 版本修改
Remove org.apache.http.legacy from bootclasspath
从 Android P 开始,org.apache.http.legacy 库将从 bootclasspath 中删除。
(1). 修改对 TargetSdkVersion<P 的应用的影响
该修改对大多数 TargetSdkVersion<P 的应用都无影响,但是如果应用使用了系统 ClassLoader 加载 org.apache.http.* 中的类时,将在 Android P 上发生 NoClassDefFoundError 失败,因为系统 ClassLoader 不再知道这些类。为了防止将来出现类似的问题,应用应该通过应用 ClassLoader 加载类,而不是直接访问系统 ClassLoader。
(2). 修改对 TargetSdkVersion>=P 的应用的影响
对所有 TargetSdkVersion>=P 的应用,如果还是按照以前一样通过在 build.gradle 文件中声明以下编译时依赖项:\
android {
useLibrary ''org.apache.http.legacy''
}
想继续使用 Apache-http 接口,都会出现 Apache-http 接口找不到的异常:

二、适配指导
1. 继续使用 Apache-http
(1). TargetSdkVersion<P 的应用适配指导
方案一:不要使用非标准的 ClassLoader 。
方案二:应用可以自己添加依赖的 apache jar 包到工程 libs 目录规避该兼容性问题。


注意:对于最低 SDK 为 23 或更低的应用程序,android:required=“false” 属性是必需的,因为在 API 等级低于 24 的设备上,org.apache.http.legacy 库不可用。(在这些设备上,Apache HTTP 类在 bootclasspath 上可用。)
(2). TargetSdkVersion>=P 的应用适配指导
对于 TargetSdkVersion>=P 的应用如果想继续使用 Apache-http 客户端,需要在应用的 AndroidManifest.xml 文件中添加:
<uses-libraryandroid:name="org.apache.http.legacy"android:required="false"/>
2. 不再使用 Apache-http 客户端
使用 HttpURLConnection 替代 Apache-http。
Android http HttpURLConnection
/**
* Http get 请求
*
* @param urlPath
*
*
*/
private static String httpConnByGet(RequestUrl ru,Params params){
String token = (String) params.getMap().get("token") ;
String et = (String) params.getMap().get("et") ;
params.getMap().remove("et");
if(token != null ){
params.getMap().put("token",Md5.md5(token + et + params.getMap().get("uid") + ru.getKeywords()));
}
String urlPath = ru.getUrl() + HttpURLConstant.QMARK + HttpURLConstant.COMMON_PARAMS + et + params.toString() ; //通用参数的设置
Log.w("NETURL","geturl:"+urlPath);
URL url = null;
HttpURLConnection urlConnection = null;
try {
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] data = new byte[2048]; //应该不会小吧!
int len = 0;
url = new URL(urlPath);
urlConnection = (HttpURLConnection) url.openConnection();
// Class<?> clazz=url.openConnection().getClass(); //看看返回什么鬼类型
// Class<?> clazzSuper=clazz.getSuperclass(); //父类又是什么鬼啊!
//getInputStream暗中执行了连接,不需要urlConnection.connect();
urlConnection.setReadTimeout(readTimeout); // 设置请求的超时时间
urlConnection.setConnectTimeout(connectTimeout);
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream inStream = urlConnection.getInputStream(); //获取输入流,此时才真正建立链接
while ((len = inStream.read(data)) != -1) {
outStream.write(data, 0, len);
}
inStream.close();
if(isDebug){Log.e(TAG,"get 返回数据"+new String(outStream.toByteArray()));}
return new String(outStream.toByteArray());
}else{ //返回的是HTTP的错误码,不是我们自己定义的错误码!
//处理一下http的错误返回码
Log.e(TAG,"get 网络连接失败"+urlConnection.getResponseCode());
return "HTTP_ERROR-"+urlConnection.getResponseCode();
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e(TAG,"MalformedURLException e");
} catch (IOException e) {
e.printStackTrace();
Log.e(TAG,"IOException e");
} finally{
if(urlConnection!=null){
urlConnection.disconnect(); //总是需要关闭的吧!
}
}
return null;
}
/**
* Http Post 请求
*
* @param urlpath
* @param paramsDatas
*/
private static String httpConnByPost(RequestUrl ru,Params params) {
String token = (String) params.getMap().get("token") ;
String et = (String) params.getMap().get("et") ;
params.getMap().remove("et");
if(token != null ){
params.getMap().put("token", Md5.md5(token + et + params.getMap().get("uid") + ru.getKeywords()));
}
URL url = null; // 根据地址创建URL对象
HttpURLConnection urlConnection = null; // 根据URL对象打开链接
try {
url = new URL(ru.getUrl()); // 根据地址创建URL对象
urlConnection = (HttpURLConnection) url.openConnection(); // 根据URL对象打开链接
urlConnection.setRequestMethod("POST"); // 设置请求的方式
urlConnection.setReadTimeout(readTimeout); // 设置请求的超时时间
urlConnection.setConnectTimeout(connectTimeout);
String paramsData = HttpURLConstant.COMMON_PARAMS + et + params.toString(); //通用参数的使用要注意
Log.w("NETURL",url+"?"+paramsData);
urlConnection.setRequestProperty("Connection", "keep-alive"); // 设置维持长连接
urlConnection.setRequestProperty("Content-Type","application/x-www-form-urlencoded"); // 设置文件的类型
urlConnection.setRequestProperty("Content-Length",String.valueOf(paramsData.getBytes().length)); // 设置数据的长度
urlConnection.setRequestProperty("User-Agent","Devond_Watch,Android-device."); // ???
urlConnection.setDoOutput(true); // 发送POST请求必须设置允许输出
urlConnection.setDoInput(true); // 发送POST请求必须设置允许输入,setDoInput的默认值就是true
urlConnection.setUseCaches(false); // 为安全,不允许使用缓存
urlConnection.connect(); //urlConnection.getInputStream()的时候会自动的打开连接的
OutputStream os = urlConnection.getOutputStream(); //获取输出流developer
os.write(paramsData.getBytes());
os.flush();
if (urlConnection.getResponseCode() == HttpURLConnection.HTTP_OK) {
InputStream is = urlConnection.getInputStream(); // 获取响应的输入流对象
ByteArrayOutputStream baos = new ByteArrayOutputStream(); // 创建字节输出流对象
int len = 0; // 定义读取的长度
byte buffer[] = new byte[2048]; // 定义缓冲区
while ((len = is.read(buffer)) != -1) { // 按照缓冲区的大小,循环读取
baos.write(buffer, 0, len); // 根据读取的长度写入到os对象中
}
is.close();// 释放资源
baos.close();
final String result = new String(baos.toByteArray());
if(isDebug){
Log.e(TAG,"Post返回的数据:"+result);
}
return new String(baos.toByteArray());
}else{ //返回的是HTTP的错误码,不是我们自己定义的错误码!
//处理一下http的错误返回码
Log.e(TAG,urlConnection.getResponseCode()+"#Post 网络连接失败#"+urlConnection.getErrorStream());
return "HTTP_ERROR-"+urlConnection.getResponseCode();
}
} catch (MalformedURLException e) {
e.printStackTrace();
Log.e(TAG,"MalformedURLException e");
}catch (Exception e) {
e.printStackTrace();
}finally{
if(urlConnection!=null){
urlConnection.disconnect();
}
}
Log.e(TAG,"Post 请求返回为空");
return null;
}
Android HttpURLConnection
谷歌推荐用HttpUrlConnection
HttpURLConnection默认使用GET方式 :
URL url = new URL("www.baidu.com");
//使用HttpURLConnection打开连接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//得到读取的内容(流)
InputStreamReader in = new InputStreamReader(urlConn.getInputStream());
// 为输出创建BufferedReader
BufferedReader buffer = new BufferedReader(in);
String inputLine = null;
//使用循环来读取获得的数据
while (((inputLine = buffer.readLine()) != null)){
//我们在每一行后面加上一个"\n"来换行
resultData += inputLine + "\n";
}
//关闭InputStreamReader
in.close();
//关闭http连接
urlConn.disconnect();
使用POST方式,则需要setRequestMethod设置 :
String httpUrl = "http://192.168.1.110:8080/httpget.jsp";
//获得的数据
String resultData = "";
URL url = null;
try {
//构造一个URL对象
url = new URL(httpUrl);
}
catch (MalformedURLException e){
Log.e(DEBUG_TAG, "MalformedURLException");
}
if (url != null){
try{
// 使用HttpURLConnection打开连接
HttpURLConnection urlConn = (HttpURLConnection) url.openConnection();
//因为这个是post请求,设立需要设置为true
urlConn.setDoOutput(true);
urlConn.setDoInput(true);
// 设置以POST方式
urlConn.setRequestMethod("POST");
// Post 请求不能使用缓存
urlConn.setUseCaches(false);
urlConn.setInstanceFollowRedirects(true);
// 配置本次连接的Content-type,配置为application/x-www-form-urlencoded的
urlConn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
// 连接,从postUrl.openConnection()至此的配置必须要在connect之前完成,
// 要注意的是connection.getOutputStream会隐含的进行connect。
urlConn.connect();
//DataOutputStream流
DataOutputStream out = new DataOutputStream(urlConn.getOutputStream());
//要上传的参数
String content = "par=" + URLEncoder.encode("ABCDEFG", "gb2312");
//将要上传的内容写入流中
out.writeBytes(content);
//刷新、关闭
out.flush();
out.close();
//返回响应结果
BufferedReader br = new BufferedReader(new InputStreamReader(urlConn.getinputstream()))
string line = br.readline();
while(line != null){
system.out.printli(line);
line = br.readline();
}
Android HTTPUrlConnection POST
我正在使用HttpURLConnection通过POST将数据发送到服务器.我设置头,然后获取输出流并写入5个字节的数据(“ M = 005”),然后关闭输出流.
在服务器上,我收到了所有标头,正确的内容长度,但是随后得到的长度为零,并且服务器挂在readLine上.
似乎发生的事情是客户端关闭实际上从未发生,因此不会写入整个数据,因此服务器永远不会获得它.
我已经阅读了许多示例,并尝试了各种更改,以查看我是否可以以任何方式实现此目标,而效果均不理想.例如,关闭保持活动状态,然后在数据末尾强制执行CRLF(这会迫使我的数据在服务器端发出,但连接仍无法关闭.(仅用于测试),尝试使用打印写程序.
由于很多示例都在执行我的操作,因此我认为这很简单,但是我看不到它.任何帮助,将不胜感激.
StringBuilder postDataBuilder.append("M=").append(URLEncoder.encode("005", UTF8));
byte[] postData = null;
postData = postDataBuilder.toString().getBytes();
url = new URL("http://" + serverAddress + ":" + String.valueOf(serverPort));
conn = (HttpURLConnection) url.openConnection();
conn.setDoOutput(true);
conn.setRequestMethod("POST");
conn.setRequestProperty("Content-Length", Integer.toString(postData.length));
conn.setUseCaches(false);
OutputStream out = conn.getoutputStream();
out.write(postData);
out.close();
int responseCode = conn.getResponseCode();
// After executing the above line the server starts to successfully readLines
// until it gets to the post data when the server hangs. If I restart the
// client side then the data finally gets through but the connection on the
// server side never ends.
解决方法:
哎呀我们服务器端的错误是执行readLine而不是字符读取.由于没有CRLF,它将挂起.
关于如何在android中为HttpsUrlConnection禁用SSLv3?和android urlconnection的问题就给大家分享到这里,感谢你花时间阅读本站内容,更多关于Android 9.0/P 版本推荐使用 HttpURLConnection、Android http HttpURLConnection、Android HttpURLConnection、Android HTTPUrlConnection POST等相关知识的信息别忘了在本站进行查找喔。
本文标签: