経緯
研究でAndroidからAzure上のPHPへ画像をPOSTする必要が出てきた
非同期処理等考えずに使えて楽そう!!という短絡的思考でRetrofit2を採用したが意外とハマったのでメモ
前提
- 以下コードは http://example.com/upload/index.php にPOSTする前提で書く
- ネットワークアクセスや内部ストレージへのアクセスなどのPermissionは与えているものとする
ライブラリのインポート
- おなじみの app/build.gradle 下部に以下の一文を追加
app/build.gradle
dependencies {
:
:
compile 'com.squareup.retrofit2:retrofit:2.1.0+'
}
interfaceの実装
- ベースURLは別で指定するのでPathは相対でOK
UploadService.class
public interface UploadService {
@Multipart
// PathはベースURLを抜いたものでOK
@POST("upload/index.php")
Call<ResponseBody> upload(@Part MultipartBody.Part file);
}
ServiceGenerator
- 公式からそのまま引用
- ベースURL部分だけ書き換えが必要
ServiceGenerator.class
public class ServiceGenerator {
// ここでベースURLを指定する
public static final String API_BASE_URL = "http://example.com/";
private static OkHttpClient.Builder httpClient = new OkHttpClient.Builder();
private static Retrofit.Builder builder = new Retrofit.Builder().baseUrl(API_BASE_URL);
public static <S> S createService(Class<S> serviceClass) {
Retrofit retrofit = builder.client(httpClient.build()).build();
return retrofit.create(serviceClass);
}
}
アップロード処理
UploagService service = ServiceGenerator.createService(UploadService.class);
// POSTする画像・音楽・動画等のファイル
String filePath = "path/to/your/file";
File file = new File(filePath);
RequestBody requestFile = RequestBody.create(MediaType.parse("multipart/form-data"), file);
MultipartBody.Part body = MultipartBody.Part.createFormData("POST先フィールド名", file.getName(), requestFile);
Call<ResponseBody> call = service.upload(body);
call.enqueue(new Callback<ResponseBody>() {
// ステータスコードが400等エラーコード以外のとき呼ばれる
@Override
public void onResponse(Call<ResponseBody> call, Response<ResponseBody> response) {
// 成功時の処理
// response.body();でHTMLレスポンスのbodyタグ内が取れる
}
// ステータスコードが400等エラーコードのとき呼ばれる
@Override
public void onFailure(Call<ResponseBody> call, Throwable t) {
// 失敗時の処理
}
});