Edited at

AndroidでHTTP通信したいときの手段まとめ

2019/04/25更新

AndroidでHTTP通信するときの手段についてまとめておきます。

サーバー側の流行やプログラミングのパラダイム変化によって今後もどんどん新しい、便利なライブラリが出てくるでしょう。


HttpUrlConnection(ライブラリ使わずJava標準のURLConnectionを使う方法)

https://developer.android.com/reference/java/net/HttpURLConnection.html


  • Apache系(Apache HttpClient,DefaultHttpClient,AndroidHttpClient)引退にともない、低レベルAPIとしてはこちらが推奨に。
    (以前はバグがあった)


Example

HttpUrlConnectionでGETのサンプルコード


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();
}



GET呼び出し方

        //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する例)


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();
}



POST呼び出し方

        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)

https://developer.android.com/about/versions/marshmallow/android-6.0-changes.html?hl=ja#behavior-apache-http-client


  • 5.1でDeprecatedになり、6.0で削除されました

  • 経過措置はあるものの、もう使用しないほうがいいでしょう


volley

https://developer.android.com/training/volley/index.html


  • 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

http://square.github.io/okhttp/

- 最近人気がある(らしい)

- 現時点で最新は OkHttp 3系


maven/gradle

https://mvnrepository.com/artifact/com.squareup.okhttp3/okhttp

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

http://square.github.io/retrofit/

- OkHttp開発元による「RESTならまかせてよ!」というライブラリ。

- REST操作(GET,POST,PUT,DELETE)を少ない記述で実現できる

- 現時点で最新は Retrofit 2.x系


maven/gralde

https://mvnrepository.com/artifact/com.squareup.retrofit2/retrofit


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に対応したモデルクラスを自動生成してくれる

http://www.jsonschema2pojo.org/


GSON

https://mvnrepository.com/artifact/com.google.code.gson/gson

maven/gradle

https://mvnrepository.com/artifact/com.google.code.gson/gson

設定例


build.gradle

 compile 'com.google.code.gson:gson:2.8.5'



Jackson

https://mvnrepository.com/artifact/com.fasterxml.jackson.core/jackson-databind

(おまけ)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に以下のように書いておくとよいでしょう。


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