2019/04/25更新
AndroidでHTTP通信するときの手段についてまとめておきます。
サーバー側の流行やプログラミングのパラダイム変化によって今後もどんどん新しい、便利なライブラリが出てくるでしょう。
HttpUrlConnection(ライブラリ使わずJava標準のURLConnectionを使う方法)
- Apache系(Apache HttpClient,DefaultHttpClient,AndroidHttpClient)引退にともない、低レベルAPIとしてはこちらが推奨に。
(以前はバグがあった)
Example
■ HttpUrlConnectionでGETのサンプルコード
public static String get(String endpoint, String encoding, Map<String, String> headers) throws IOException {
final int TIMEOUT_MILLIS = 0;// タイムアウトミリ秒:0は無限
final StringBuffer sb = new StringBuffer("");
HttpURLConnection httpConn = null;
BufferedReader br = null;
InputStream is = null;
InputStreamReader isr = null;
try {
URL url = new URL(endpoint);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setConnectTimeout(TIMEOUT_MILLIS);// 接続にかかる時間
httpConn.setReadTimeout(TIMEOUT_MILLIS);// データの読み込みにかかる時間
httpConn.setRequestMethod("GET");// HTTPメソッド
httpConn.setUseCaches(false);// キャッシュ利用
httpConn.setDoOutput(false);// リクエストのボディの送信を許可(GETのときはfalse,POSTのときはtrueにする)
httpConn.setDoInput(true);// レスポンスのボディの受信を許可
// HTTPヘッダをセット
if (headers != null) {
for (String key : headers.keySet()) {
httpConn.setRequestProperty(key, headers.get(key));// HTTPヘッダをセット
}
}
httpConn.connect();
final int responseCode = httpConn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
is = httpConn.getInputStream();
isr = new InputStreamReader(is, encoding);
br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
} else {
// If responseCode is not HTTP_OK
}
} catch (IOException e) {
throw e;
} finally {
// fortify safeかつJava1.6 compliantなclose処理
if (br != null) {
try {
br.close();
} catch (IOException e) {
}
}
if (isr != null) {
try {
isr.close();
} catch (IOException e) {
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
if (httpConn != null) {
httpConn.disconnect();
}
}
return sb.toString();
}
//HTTPヘッダ(指定したければ)
Map<String,String> headers=new HashMap<String,String>();
headers.put("X-Example-Header","Example-Value");
String resultStr = get("http://hogehoge/foofoo", "UTF-8", headers);
■ HttpUrlConnectionでPOST(JSON文字列をPOSTする例)
public static String post(String endpoint, String encoding, Map<String, String> headers, String jsonString) throws IOException {
final int TIMEOUT_MILLIS = 0;// タイムアウトミリ秒:0は無限
final StringBuffer sb = new StringBuffer("");
HttpURLConnection httpConn = null;
BufferedReader br = null;
InputStream is = null;
InputStreamReader isr = null;
try {
URL url = new URL(endpoint);
httpConn = (HttpURLConnection) url.openConnection();
httpConn.setConnectTimeout(TIMEOUT_MILLIS);// 接続にかかる時間
httpConn.setReadTimeout(TIMEOUT_MILLIS);// データの読み込みにかかる時間
httpConn.setRequestMethod("POST");// HTTPメソッド
httpConn.setUseCaches(false);// キャッシュ利用
httpConn.setDoOutput(true);// リクエストのボディの送信を許可(GETのときはfalse,POSTのときはtrueにする)
httpConn.setDoInput(true);// レスポンスのボディの受信を許可
if (headers != null) {
for (String key : headers.keySet()) {
httpConn.setRequestProperty(key, headers.get(key));// HTTPヘッダをセット
}
}
OutputStream os = httpConn.getOutputStream();
final boolean autoFlash = true;
PrintStream ps = new PrintStream(os, autoFlash, encoding);
ps.print(jsonString);
ps.close();
final int responseCode = httpConn.getResponseCode();
if (responseCode == HttpURLConnection.HTTP_OK) {
is = httpConn.getInputStream();
isr = new InputStreamReader(is, encoding);
br = new BufferedReader(isr);
String line = null;
while ((line = br.readLine()) != null) {
sb.append(line);
}
} else {
// If responseCode is not HTTP_OK
}
} catch (IOException e) {
throw e;
} finally {
// fortify safeかつJava1.6 compliantなclose処理
if (br != null) {
try {
br.close();
} catch (IOException e) {
}
}
if (isr != null) {
try {
isr.close();
} catch (IOException e) {
}
}
if (is != null) {
try {
is.close();
} catch (IOException e) {
}
}
if (httpConn != null) {
httpConn.disconnect();
}
}
return sb.toString();
}
String postJson = "[{\"message\":{\"number\":\"1\",\"value\":\"Hello\"}}]";
Map<String, String> headers = new HashMap<String, String>(); // HTTPヘッダ(指定したければ)
headers.put("X-Example-Header", "Example-Value");
String postResult = post("http://hogehoge/foofoo", "UTF-8", headers, postJson);
脱線しますが、Android盤のjava.net.HttpURLConnectionは、本家JDKと同じインタフェースはもっていますが、AndroidのJava実装は本家OracleJDKとは違います(※1)ので、Oracle謹製のJavaランタイムで動作していても、Androidで動作しないことは多々ありました。(※2)
(※1)AndroidのJDKはApache HarmonyベースからOpenJDKベースへと変化しています。
(※2)Pure Java(のみ)でテストされたライブラリをそのままもってくると痛い目をみます。
Apache系(Apache HttpClient,DefaultHttpClient,AndroidHttpClient)
- 5.1でDeprecatedになり、6.0で削除されました
- 経過措置はあるものの、もう使用しないほうがいいでしょう
volley
- Androidでよくあるシーン(非同期とか)に対応したいろいろ便利なvolley
final TextView mTextView = (TextView) findViewById(R.id.text);
...
// Instantiate the RequestQueue.
RequestQueue queue = Volley.newRequestQueue(this);
String url ="http://www.google.com";
// Request a string response from the provided URL.
StringRequest stringRequest = new StringRequest(Request.Method.GET, url,
new Response.Listener<String>() {
@Override
public void onResponse(String response) {
// Display the first 500 characters of the response string.
mTextView.setText("Response is: "+ response.substring(0,500));
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
mTextView.setText("That didn't work!");
}
});
// Add the request to the RequestQueue.
queue.add(stringRequest);
https://developer.android.com/training/volley/simple.html より抜粋
OkHttp3
- 最近人気がある(らしい)
- 現時点で最新は OkHttp 3系
maven/gradle
dependencies {
compile group: 'com.squareup.okhttp3', name: 'okhttp', version: '3.14.1'
}
Example
OkHttp3でのREST操作(Request)のつくりかた
GET
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.Response;
public void doGet(String url) throws IOException {
final Request request = new Request.Builder().url(url).build();
final OkHttpClient client = new OkHttpClient.Builder().build();
//同期呼び出し
Response response = client.newCall(request).execute();
//結果を表示
System.out.println(response.body().string());
}
POST
- Form POSTしたい場合
import okhttp3.FormBody;
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public void doFormPost(String url) throws IOException {
final FormBody.Builder formBodyBuilder = new FormBody.Builder();
formBodyBuilder.add("param_name", "param_value");
final Request request = new Request.Builder()
.url(url)
.header("User-Agent", "Example client")
.post(formBodyBuilder.build())
.build();
OkHttpClient client = new OkHttpClient.Builder()
.build();
//同期呼び出し
Response response = client.newCall(request).execute();
//結果を表示
System.out.println(response.body().string());
}
- JSON をまるっとPOSTしたい場合
import okhttp3.OkHttpClient;
import okhttp3.Request;
import okhttp3.RequestBody;
import okhttp3.Response;
public void doPost(String url, String jsonString) throws IOException {
okhttp3.MediaType mediaTypeJson = okhttp3.MediaType.parse("application/json; charset=utf-8");
RequestBody requestBody = RequestBody.create(mediaTypeJson, jsonString);
final Request request = new Request.Builder()
.url(url)
.post(requestBody)//POST指定
.build();
OkHttpClient client = new OkHttpClient.Builder()
.build();
//同期呼び出し
Response response = client.newCall(request).execute();
//結果を表示
System.out.println(response.body().string());
}
PUT
final Builder formBodyBuilder = new FormBody.Builder();
formBodyBuilder.add("param_name","param_value");
final Request request = new Request.Builder()
.url(url)
.put(formBodyBuilder.build())
.build();
OkHttpClient client = new OkHttpClient.Builder()
.build();
Response response = client.newCall(request).execute();//同期呼び出し
DELETE
final Request request = new Request.Builder()
.url(url)
.delete()
.build();
OkHttpClient client = new OkHttpClient.Builder()
.build();
Response response = client.newCall(request).execute();//同期呼び出し
同期呼び出し
OkHttpClient client = new OkHttpClient.Builder()
.build();
Response response = client.newCall(request).execute();
非同期呼び出し
OkHttpClient client = new OkHttpClient.Builder()
.build();
client.newCall(request).enqueue(new okhttp3.Callback() {
@Override
public void onResponse(Call call, Response response) throws IOException {
final String resString = response.body().string();
//view更新のときは handler#post()する
}
@Override
public void onFailure(Call call, IOException arg1) {
}
});
Retrofit2
- OkHttp開発元による「RESTならまかせてよ!」というライブラリ。
- REST操作(GET,POST,PUT,DELETE)を少ない記述で実現できる
- 現時点で最新は Retrofit 2.x系
maven/gralde
Example
@Multipart
@PUT("user/photo")
Call<User> updateUser(@Part("photo") RequestBody photo, @Part("description") RequestBody description);
( http://square.github.io/retrofit/ より抜粋)
HTTP通信と一緒に使う道具たち
JSONパーサー
JSONをモデルクラス(POJO)にマッピングしたい
JSONパーサーを使うときに、GSONやJacksonに対応したモデルクラスを自動生成してくれるサイト
生のJSONやJSON Schemaから、GSONやJacksonに対応したモデルクラスを自動生成してくれる
■ GSON
maven/gradle
https://mvnrepository.com/artifact/com.google.code.gson/gson
設定例
compile 'com.google.code.gson:gson:2.8.5'
■ Jackson
(おまけ)JacksonをJSON ParserとしてAndroidで使う時の注意
compile 'com.fasterxml.jackson.core:jackson-databind:2.8.6'
gradleのビルド時にJACKSONのLICENSEファイルが重複して以下のようなエラーメッセージがでるので、
Error:Execution failed for task ':app:transformResourcesWithMergeJavaResForDebug'.
> com.android.build.api.transform.TransformException: com.android.builder.packaging.DuplicateFileException: Duplicate files copied in APK META-INF/LICENSE
アプリレベルのbuild.gradleに以下のように書いておくとよいでしょう。
android {
中略
packagingOptions {
exclude 'META-INF/LICENSE'
}
}
JSONの操作については、↓に詳しくまとめました
JSONをJavaに、JavaをJSONにする ~GSONとJacksonの使用方法~
リアクティブプログラミング
RxJava/RxAndroid
https://mvnrepository.com/artifact/io.reactivex/rxandroid
https://mvnrepository.com/artifact/io.reactivex/rxjava