2017/02/08
POSTが動かなかったので修正しました
はじめに
最近Androidエンジニアしてるぼく。
アプリ作ってるとHTTPリクエストしたくなるよね。
GETとかPOSTとかPUTとかDELETEとか。
基礎は「HttpURLConnection Android」でググってもらって。
HttpURLConnection使いにくいやんなー
ずっと自作のラッパー使ってたんやけどなー
使い古しすぎ&他クラスとの結合度高すぎやなー
なので、いい加減作り直した。
*残念ながらmultipart/form-dataのPOST未対応。そのうちやる。
*残念ながら動作確認はしていません。
・変更点
最近メソッドチェーンがマイブームやねんってことでメソッドチェーンに
マルチスレッド処理をAsyncTask→Thred+Runnableに
コールバックをinterfaceに
パラメータとかを自作のParamクラスで受け取ってたのやめ
レスポンスの加工までHttpClientでやってたのやめた
IxJava導入した
IOUtils発見した
下準備
・【Java】HTTPステータスコード列挙型 Powered by Wikipediaを実装
・以下、追記
build.gradle
dependencies {
compile 'com.github.akarnokd:ixjava:0.90.0'
compile 'org.apache.directory.studio:org.apache.commons.io:2.4'
}
AndroidManifest.xml
<uses-permission android:name="android.permission.INTERNET" />
実装
Githubに上げるのとかなんかナウくて嫌いなのでここで。
HttpClient
package com.akippa.akippacore.http;
import android.net.Uri;
import android.text.TextUtils;
import org.apache.commons.io.IOUtils;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.HttpURLConnection;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.URL;
import java.net.URLDecoder;
import java.net.URLEncoder;
import java.util.HashMap;
import java.util.Map;
import ix.Ix;
import rx.functions.Action1;
import rx.functions.Func1;
// TODO:クッキーとかセッションとか。schooのソースにあるな。
/**
* HTTPクライアント
*/
public final class HttpClient {
public enum HttpMethod {
GET("GET"),
POST("POST"),
DELETE("DELETE"),
PUT("PUT");
private final String mValue;
HttpMethod(String value) {
mValue = value;
}
@Override
public String toString() {
return mValue;
}
}
private final Uri.Builder mBuilder;
private Map<String, String> mRequestParameter = new HashMap<>();
private String mEncode = "UTF-8";
private HttpMethod mMethod = HttpMethod.GET;
private int mConnectTimeout = 5000;
private int mReadTimeout = 5000;
private Map<String, String> mRequestProperty = new HashMap<>();
private Proxy.Type mProxyType;
private String mProxyServerAddress;
private int mProxyServerPort;
private HttpClient() {
super();
mBuilder = new Uri.Builder();
}
public static HttpClient create() {
return new HttpClient();
}
public HttpClient setScheme(String scheme) {
mBuilder.scheme(scheme);
return this;
}
public HttpClient setEncodedAuthority(String authority) {
mBuilder.encodedAuthority(authority);
return this;
}
public HttpClient setPath(String path) {
mBuilder.path(path);
return this;
}
public HttpClient appendRequestParameter(String key, String value) {
mRequestParameter.put(key, value);
return this;
}
public HttpClient appendRequestParamter(final Map<String, String> param) {
Ix.from(param.keySet()).forEach(new Action1<String>() {
@Override
public void call(String s) {
mRequestParameter.put(s, param.get(s));
}
});
return this;
}
public HttpClient setEncode(String encode) {
mEncode = encode;
return this;
}
public HttpClient setMethod(HttpMethod method) {
mMethod = method;
return this;
}
public HttpClient setConnectTimeout(int connectTimeout) {
mConnectTimeout = connectTimeout;
return this;
}
public HttpClient setReadTimeout(int readTimeout) {
mReadTimeout = readTimeout;
return this;
}
public HttpClient setRequestProperty(String key, String value) {
mRequestProperty.put(key, value);
return this;
}
public HttpClient setRequestProperty(Map<String, String> requestProperty) {
mRequestProperty = requestProperty;
return this;
}
public HttpClient setProxy(Proxy.Type proxyType, String serverAddress, int serverPort) {
mProxyType = proxyType;
mProxyServerAddress = serverAddress;
mProxyServerPort = serverPort;
return this;
}
private HttpURLConnection createConnection() throws IOException {
switch (mMethod) {
case GET:
case DELETE:
Ix.from(mRequestParameter.keySet()).forEach(new Action1<String>() {
@Override
public void call(String s) {
mBuilder.appendQueryParameter(s, mRequestParameter.get(s));
}
});
break;
}
final HttpURLConnection httpURLConnection = mProxyServerAddress == null
? (HttpURLConnection) new URL(URLDecoder.decode(mBuilder.build().toString(), mEncode)).openConnection()
: (HttpURLConnection) new URL(URLDecoder.decode(mBuilder.build().toString(), mEncode)).openConnection(new Proxy(mProxyType, new InetSocketAddress(mProxyServerAddress, mProxyServerPort)));
httpURLConnection.setRequestMethod(mMethod.toString());
httpURLConnection.setConnectTimeout(mConnectTimeout);
httpURLConnection.setReadTimeout(mReadTimeout);
Ix.from(mRequestProperty.keySet()).forEach(new Action1<String>() {
@Override
public void call(String s) {
httpURLConnection.setRequestProperty(s, mRequestProperty.get(s));
}
});
switch (mMethod) {
case POST:
case PUT:
httpURLConnection.setDoOutput(true);
httpURLConnection.setDoInput(true);
httpURLConnection.setUseCaches(false);
final String requestBody = TextUtils.join("&",
Ix.from(mRequestParameter.keySet()).map(new Func1<String, String>() {
@Override
public String call(String s) {
try {
return String.format("%s=%s",
URLEncoder.encode(s, "UTF-8"),
URLEncoder.encode(mRequestParameter.get(s), "UTF-8"));
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
return "";
}
}).toArray(new String[]{}));
if (requestBody.length() > 0) {
final OutputStream outputStream = httpURLConnection.getOutputStream();
final BufferedWriter bufferedWriter = new BufferedWriter(new OutputStreamWriter(outputStream, mEncode));
bufferedWriter.write(requestBody);
bufferedWriter.flush();
bufferedWriter.close();
outputStream.flush();
outputStream.close();
}
break;
}
return httpURLConnection;
}
public void sendRequest(final SendRequestCallBack callBack) {
new Thread(
new Runnable() {
@Override
public void run() {
final HttpURLConnection httpURLConnection;
try {
httpURLConnection = createConnection();
} catch (IOException e) {
e.printStackTrace();
return;
}
HttpStatusCode httpStatusCode;
try {
httpURLConnection.connect();
httpStatusCode = HttpStatusCode.getByStatusCode(httpURLConnection.getResponseCode());
} catch (IOException e) {
e.printStackTrace();
callBack.onFailure(HttpStatusCode.DEFAULT);
return;
}
try {
callBack.onSuccess(httpStatusCode, IOUtils.toString(httpURLConnection.getInputStream()));
} catch (IOException e) {
e.printStackTrace();
callBack.onFailure(httpStatusCode);
}
}
}
).start();
}
public interface SendRequestCallBack {
void onFailure(HttpStatusCode code);
void onSuccess(HttpStatusCode code, String responseText);
}
}
使い方
sample
HttpClient.create()
.setScheme("https")
.setEncodedAuthority("www.google.co.jp")
.setPath("search")
.appendRequestParameter("q", "akippa")
.appendRequestParameter("rct", "j")
.setMethod(HttpClient.HttpMethod.GET)
.sendRequest(new HttpClient.SendRequestCallBack() {
@Override
public void onFailure(HttpStatusCode code) {
Log.d("log", String.format("HttpStatusCode:%s", code.toString()));
}
@Override
public void onSuccess(HttpStatusCode code, String responseText) {
Log.d("log", String.format("HttpStatusCode:%s : Response:%s", code.toString(), responseText));
}
});