読者です 読者をやめる 読者になる 読者になる

【Android】Volley各種設定メモ

ちょっとVolleyを使いたい要件があるんですが、公式のドキュメントを読んでも「いや知りたいのはそこじゃねーよ」と言うものばかりなのでメモしていきます。

JavaDocこれを参考にしています。正直このJavaDocが生成されたのがいつ時点のビルドかわからないのでもっと色々追加されてるのかもしれないんですが、ちょっとそこまで追う気力はないです。

覚えておきたい前知識

重要なオブジェクトはこの辺です。

RequestQueueはその名の通りRequestをキューイングするクラスです。ExecutorServiceみたいなものだと思っておけばいいです。

Request<T>もその名の通りHTTPリクエストに関する諸々を設定するクラスです。URLだとか、GET/POSTメソッドだとかをコンストラクタで指定します。

deliverResponseメソッドは明らかにレスポンスに関わる部分なんですが、まぁここにあったほうが便利ですね。

NetworkはRequestを受け取って実行しNetworkResponseを返す、いわばアダプタです。実装はBasicNetworkが用意されていますし、これで十分です。

と言うか、Volley#newRequestQueue経由でインスタンスを作成するとNetworkの指定すらできません。

HttpStackはBasicNetworkで使用される、実際の通信部分です。実装としてはHttpClientStackとHurlStackが用意されています。Hurlは「HttpURL」の略だと思われます。

HurlStackはperformRequest内でHttpURLConnectionを作成しているんですが、Gingerbread(API Level 9)より前はHttpUrlConnectionにバグがあるので、minSdkVersionによってはちゃんと分岐させないと痛い目を見そうです。

Header / Post paramsの設定はRequest<T>のメソッドをオーバーライドする

HeaderとかPostのparamとか追加したいと思うんですが、その手のものはRequestのgetterをオーバーライドすることで渡せます。まぁ、1リクエスト毎に渡せた方がありがたいので、そうですねって感じ。

使いたいRequestをnewする際にオーバーライドするだけでもいけます。

RequestのJavaDoc眺めてsetterがなかったらそいつ、って認識。具体的にはこの辺のメソッド

エンコード指定が必要ならこの辺も。特にgetParamsEncodingはデフォルトだとUTF-8を返すようになってるので注意したほうが良さそうです。

リトライやタイムアウト設定はRetryPolicyを使う

タイムアウトの設定なんかはRequest#setRetryPolicyRetryPolicyを渡せばOKです。

DefaultRetryPolicyのコンストラクタが便利です。デフォルト値はソース見たほうが早いです。

自己署名証明書によるHTTPS通信設定

HurlStackを使うかHttpClientStackを使うかで微妙に変わってきます。

細かい設定方法なんかは本旨にそぐわないので割愛。(めんどくさいんだよねあれ…。)

HurlStackを使う場合

コンストラクタでSSLSocketFactoryを渡せるので渡してあげましょう。

参考:Android - Volleyで自己署名証明書を使ったHTTPS通信 - Qiita

HttpClientStackを使う場合

どっちにしたってコンストラクタでHttpClientを渡さなきゃいけないのでいつも通りにやればOK。

参考:

Cookieの設定とか取得とか

Cookieを使用する場合はRequestQueueのthreadPoolSizeを1にする必要があるらしいので、気をつけましょう。クソ面倒ですね。

設定も取得もCookieManagerを使うのがベストでしょう。リクエストを飛ばした後のHttpClientが手に入るならCookieStoreも併用したいところですが、残念ながらこれは手に入りません。レスポンスヘッダからちまちま取得します。

具体的にはこんなコードをRequest内で書けばOK。

public abstract class CookieRequest<T> extends Request<T> {
    
    // コンストラクタの実装とかは省略
    
    // Cookieの設定
    @Override
    public Map<String,String> getHeaders() throws AuthFailureError {
        Map<String,String> header = null;
        
        CookieManager cm = CookieManager.getInstance();
        // 設定されたURLからCookieが取得できないか試行する
        String cookie = cm.getCookie(getUrl());
        
        if(cookie != null) {
            header = new HashMap<String, String>();
            String[] cookies = cookie.split(";");
            for(String c : cookies) {
                c = c.trim();
                String[] cs = c.split("=");
                // ヘッダにCookieを詰め込む
                header.put(cs[0], cs[1]);
            }
        }
        
        return header != null : header ? Collections.emptyMap();
    }
    
    // Cookieの取得
    @Override
    protected Response<T> parseNetworkResponse(NetworkResponse response) {
        Map<String, String> headers = response.headers;
        if(headers != null) {
            CookieManager cm = null;
            for(Entry<String, String> e : headers.entrySet()) {
                if(!"Set-Cookie".equars(e.getKey()))
                    continue;
                
                if(cm == null) cm = CookieManager.getInstance();
                
                cm.setCookie(getUrl(), e.getValue());
            }
        }
        
        return super.parseNetworkResponse(response);
    }
}

OKと言ったもののまだ動かしてないので本当にこれでいいのか微妙です。そのうち試します。

まとめ

HttpClient / HttpURLConnectionを後から変更できるようにしてくれ頼む。

参考