サーチ…


前書き

VolleyはAndroidのHTTPライブラリで、Googleがネットワーキングコールをもっと簡単にするために導入したものです。デフォルトでは、すべてのVolleyネットワークコールは非同期で行われ、バックグラウンドスレッドのすべてを処理し、コールバックを使用してフォアグラウンドで結果を返します。ネットワーク上のデータを取得することは、どのアプリでも実行される最も一般的なタスクの1つで、VolleyライブラリはAndroidアプリの開発を容易にするために作成されました。

構文

  • RequestQueueキュー= Volley.newRequestQueue(コンテキスト); //キューを設定する
  • リクエストのリクエスト=新しいSomeKindOfRequestClass(Request.Method、String url、Response.Listener、Response.ErrorListener); //何らかの種類のリクエストをセットアップします。各リクエストの種類ごとに正確な型と引数が変更されます
  • queue.add(リクエスト); //要求をキューに追加します。要求が完了した(または何らかの理由で終了した)場合は、適切な応答リスナーが呼び出されます。

備考

インストール

Google正式なソースコードからVolleyを構築することができます 。しばらくの間、それが唯一の選択肢でした。または、サードパーティ製の事前構築版のいずれかを使用します。しかし、Googleはついにjcenterの公式のmavenパッケージをリリースしました。

アプリケーションレベルのbuild.gradleファイルで、これを依存関係リストに追加します。

dependencies {
    ...
    compile 'com.android.volley:volley:1.0.0'
}

アプリのマニフェストにINTERNETアクセス許可が設定されていることを確認します。

<uses-permission android:name="android.permission.INTERNET"/>

公式文書

Googleはこのライブラリについて非常に詳細な文書を提供しておらず、何年も触れていません。しかし、利用可能なものは次の場所にあります:

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

GitHubには非公式の文書がホストされていますが、将来的にこれをホストするのに適した場所があるはずです。

https://pablobaxter.github.io/volley-docs/

GETメソッドを使用した基本StringRequest

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

リクエストをキャンセルする

// assume a Request and RequestQueue have already been initialized somewhere above

public static final String TAG = "SomeTag";

// Set the tag on the request.
request.setTag(TAG);

// Add the request to the RequestQueue.
mRequestQueue.add(request);

// To cancel this specific request
request.cancel();

// ... then, in some future life cycle event, for example in onStop()
// To cancel all requests with the specified tag in RequestQueue
mRequestQueue.cancelAll(TAG);

NetworkImageViewにカスタムのデザインタイム属性を追加する

Volley NetworkImageViewが標準のImageView追加するいくつかの追加の属性があります。ただし、これらの属性はコード内でのみ設定できます。次は、XMLレイアウトファイルから属性を取得してNetworkImageViewインスタンスに適用する拡張クラスを作成する方法の例です。

~/res/xmlディレクトリに、 attrx.xmlという名前のファイルを追加します。

<resources>
    <declare-styleable name="MoreNetworkImageView">
        <attr name="defaultImageResId" format="reference"/>
        <attr name="errorImageResId" format="reference"/>
    </declare-styleable>
</resources>

新しいクラスファイルをプロジェクトに追加します。

package my.namespace;

import android.content.Context;
import android.content.res.TypedArray;
import android.support.annotation.NonNull;
import android.util.AttributeSet;

import com.android.volley.toolbox.NetworkImageView;

public class MoreNetworkImageView extends NetworkImageView {
    public MoreNetworkImageView(@NonNull final Context context) {
        super(context);
    }

    public MoreNetworkImageView(@NonNull final Context context, @NonNull final AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public MoreNetworkImageView(@NonNull final Context context, @NonNull final AttributeSet attrs, final int defStyle) {
        super(context, attrs, defStyle);

        final TypedArray attributes = context.obtainStyledAttributes(attrs, R.styleable.MoreNetworkImageView, defStyle, 0);

        // load defaultImageResId from XML
        int defaultImageResId = attributes.getResourceId(R.styleable.MoreNetworkImageView_defaultImageResId, 0);
        if (defaultImageResId > 0) {
            setDefaultImageResId(defaultImageResId);
        }

        // load errorImageResId from XML
        int errorImageResId = attributes.getResourceId(R.styleable.MoreNetworkImageView_errorImageResId, 0);
        if (errorImageResId > 0) {
            setErrorImageResId(errorImageResId);
        }
    }
}

カスタム属性の使用を示すレイアウトファイルの例:

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
  xmlns:android="http://schemas.android.com/apk/res/android"
  xmlns:app="http://schemas.android.com/apk/res-auto"
  xmlns:tools="http://schemas.android.com/tools"
  android:layout_width="wrap_content"
  android:layout_height="fill_parent">

  <my.namespace.MoreNetworkImageView
    android:layout_width="64dp"
    android:layout_height="64dp"
    app:errorImageResId="@drawable/error_img"
    app:defaultImageResId="@drawable/default_img"
    tools:defaultImageResId="@drawable/editor_only_default_img"/>
    <!-- 
      Note: The "tools:" prefix does NOT work for custom attributes in Android Studio 2.1 and 
      older at least, so in this example the defaultImageResId would show "default_img" in the 
      editor, not the "editor_only_default_img" drawable even though it should if it was 
      supported as an editor-only override correctly like standard Android properties.
    -->

</android.support.v7.widget.CardView>

JSONをリクエストする

final TextView mTxtDisplay = (TextView) findViewById(R.id.txtDisplay);
ImageView mImageView;
String url = "http://ip.jsontest.com/";

final JsonObjectRequest jsObjRequest = new JsonObjectRequest
        (Request.Method.GET, url, null, new Response.Listener<JSONObject>() {    
    @Override
    public void onResponse(JSONObject response) {
        mTxtDisplay.setText("Response: " + response.toString());
    }
}, new Response.ErrorListener() {    
    @Override
    public void onErrorResponse(VolleyError error) {
        // ...
    }
});

requestQueue.add(jsObjRequest);

リクエストにカスタムヘッダーを追加する[例:基本認証]

あなたのボレーリクエストにカスタムヘッダーを追加する必要がある場合は、ヘッダーがプライベート変数に保存されるため、初期化後にこれを行うことはできません。

代わりに、 Request.class getHeaders()メソッドを次のようにオーバーライドする必要があります。

new JsonObjectRequest(REQUEST_METHOD, REQUEST_URL, REQUEST_BODY, RESP_LISTENER, ERR_LISTENER) {
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        HashMap<String, String> customHeaders = new Hashmap<>();

        customHeaders.put("KEY_0", "VALUE_0");
        ...
        customHeaders.put("KEY_N", "VALUE_N");

        return customHeaders;
    }
};

パラメータの説明:

  • REQUEST_METHOD - Request.Method.*定数のいずれか。
  • REQUEST_URL - リクエストを送信する完全なURL。
  • REQUEST_BODY - 送信されるPOST-Bodyを含むJSONObject (またはnull)。
  • RESP_LISTENER - 正常終了時にonResponse(T data)メソッドが呼び出されるResponse.Listener<?>オブジェクトResponse.Listener<?>
  • ERR_LISTENER - 失敗したリクエストに対してonErrorResponse(VolleyError e)メソッドが呼び出されるResponse.ErrorListenerオブジェクト。

カスタムリクエストを作成する場合は、ヘッダーを追加することもできます。

public class MyCustomRequest extends Request {
    ...
    @Override
    public Map<String, String> getHeaders() throws AuthFailureError {
        HashMap<String, String> customHeaders = new Hashmap<>();

        customHeaders.put("KEY_0", "VALUE_0");
        ...
        customHeaders.put("KEY_N", "VALUE_N");

        return customHeaders;
    }
    ...
}

ボレーエラーを処理するためのヘルパークラス

public class VolleyErrorHelper {
        /**
         * Returns appropriate message which is to be displayed to the user
         * against the specified error object.
         *
         * @param error
         * @param context
         * @return
         */

        public static String getMessage (Object error , Context context){
            if(error instanceof TimeoutError){
                return context.getResources().getString(R.string.timeout);
            }else if (isServerProblem(error)){
                return handleServerError(error ,context);

            }else if(isNetworkProblem(error)){
                return context.getResources().getString(R.string.nointernet);
            }
            return context.getResources().getString(R.string.generic_error);

        }

        private static String handleServerError(Object error, Context context) {

            VolleyError er = (VolleyError)error;
            NetworkResponse response = er.networkResponse;
            if(response != null){
                switch (response.statusCode){

                    case 404:
                    case 422:
                    case 401:
                        try {
                            // server might return error like this { "error": "Some error occured" }
                            // Use "Gson" to parse the result
                            HashMap<String, String> result = new Gson().fromJson(new String(response.data),
                                    new TypeToken<Map<String, String>>() {
                                    }.getType());

                            if (result != null && result.containsKey("error")) {
                                return result.get("error");
                            }

                        } catch (Exception e) {
                            e.printStackTrace();
                        }
                        // invalid request
                        return ((VolleyError) error).getMessage();

                    default:
                        return context.getResources().getString(R.string.timeout);
                }
            }

            return context.getResources().getString(R.string.generic_error);
        }

        private static boolean isServerProblem(Object error) {
            return (error instanceof ServerError || error instanceof AuthFailureError);
        }

        private static boolean isNetworkProblem (Object error){
            return (error instanceof NetworkError || error instanceof NoConnectionError);
        }

POSTメソッドによるStringRequestを使用したリモートサーバー認証

この例では、Androidアプリケーションから作成するPOSTリクエストを処理するためのサーバーがあるとします。

// User input data.
String email = "[email protected]";
String password = "123";

// Our server URL for handling POST requests.
String URL = "http://my.server.com/login.php";

// When we create a StringRequest (or a JSONRequest) for sending
// data with Volley, we specify the Request Method as POST, and 
// the URL that will be receiving our data.
StringRequest stringRequest = 
    new StringRequest(Request.Method.POST, URL, 
    new Response.Listener<String>() {
        @Override
        public void onResponse(String response) {
            // At this point, Volley has sent the data to your URL
            // and has a response back from it. I'm going to assume
            // that the server sends an "OK" string.
            if (response.equals("OK")) {
                // Do login stuff.
            } else {
                // So the server didn't return an "OK" response.
                // Depending on what you did to handle errors on your
                // server, you can decide what action to take here.
            }
        }
    },
    new Response.ErrorListener() {
        @Override
        public void onErrorResponse(VolleyError error) {      
            // This is when errors related to Volley happen.
            // It's up to you what to do if that should happen, but
            // it's usually not a good idea to be too clear as to
            // what happened here to your users.
        }
    }) {
        @Override
        protected Map<String, String> getParams() throws AuthFailureError {
            // Here is where we tell Volley what it should send in
            // our POST request. For this example, we want to send
            // both the email and the password. 
            
            // We will need key ids for our data, so our server can know
            // what is what.
            String key_email = "email";
            String key_password = "password";

            Map<String, String> map = new HashMap<String, String>();
            // map.put(key, value);
            map.put(key_email, email);
            map.put(key_password, password);
            return map;
        }
    };

    // This is a policy that we need to specify to tell Volley, what
    // to do if it gets a timeout, how many times to retry, etc.
    stringRequest.setRetryPolicy(new RetryPolicy() {
            @Override
            public int getCurrentTimeout() {
                // Here goes the timeout.
                // The number is in milliseconds, 5000 is usually enough,
                // but you can up or low that number to fit your needs.
                return 50000;
            }
            @Override
            public int getCurrentRetryCount() {
                // The maximum number of attempts.
                // Again, the number can be anything you need.
                return 50000;
            }
            @Override
            public void retry(VolleyError error) throws VolleyError {
                // Here you could check if the retry count has gotten
                // to the maximum number, and if so, send a VolleyError
                // message or similar. For the sake of the example, I'll 
                // show a Toast.  
                Toast.makeText(getContext(), error.toString(), Toast.LENGTH_LONG).show();
            }
    });
    
    // And finally, we create a Volley Queue. For this example, I'm using
    // getContext(), because I was working with a Fragment. But context could
    // be "this", "getContext()", etc.
    RequestQueue requestQueue = Volley.newRequestQueue(getContext());
    requestQueue.add(stringRequest);

} else { 
    // If, for example, the user inputs an email that is not currently
    // on your remote DB, here's where we can inform the user.
    Toast.makeText(getContext(), "Wrong email", Toast.LENGTH_LONG).show();
}

HTTPリクエストにVolleyを使用する

アプリレベルbuild.gradleにgradle依存関係を追加する

compile 'com.android.volley:volley:1.0.0'

また、アプリのマニフェストにandroid.permission.INTERNET権限を追加します。

**アプリケーションでVolley RequestQueueインスタンスシングルトンを作成する**

public class InitApplication extends Application {

private RequestQueue queue;
private static InitApplication sInstance;

private static final String TAG = InitApplication.class.getSimpleName();


@Override
public void onCreate() {
    super.onCreate();

    sInstance = this;

    Stetho.initializeWithDefaults(this);

}

public static synchronized InitApplication getInstance() {
    return sInstance;
}

public <T> void addToQueue(Request<T> req, String tag) {
    req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
    getQueue().add(req);
}

public <T> void addToQueue(Request<T> req) {
    req.setTag(TAG);
    getQueue().add(req);
}

public void cancelPendingRequests(Object tag) {
    if (queue != null) {
        queue.cancelAll(tag);
    }
}

public RequestQueue getQueue() {
    if (queue == null) {
        queue = Volley.newRequestQueue(getApplicationContext());
        return queue;
    }
    return queue;
}
}

これで、getInstance()メソッドを使用してvolleyインスタンスを使用し、 InitApplication.getInstance().addToQueue(request);を使用してキューに新しいリクエストを追加できInitApplication.getInstance().addToQueue(request);

サーバーからJsonObjectを要求する簡単な例は次のとおりです

JsonObjectRequest myRequest = new JsonObjectRequest(Method.GET,
        url, null,
        new Response.Listener<JSONObject>() {

            @Override
            public void onResponse(JSONObject response) {
                Log.d(TAG, response.toString());
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.d(TAG, "Error: " + error.getMessage());
            }
});

myRequest.setRetryPolicy(new DefaultRetryPolicy(
        MY_SOCKET_TIMEOUT_MS, 
        DefaultRetryPolicy.DEFAULT_MAX_RETRIES, 
        DefaultRetryPolicy.DEFAULT_BACKOFF_MULT));

Volleyのタイムアウトを処理するには、 RetryPolicyを使用する必要があります。再試行ポリシーは、ネットワーク障害などの理由で要求を完了できない場合に使用されます。

Volleyは、リクエストに対してRetryPolicyを実装する簡単な方法を提供します。デフォルトでは、Volleyはすべての要求に対してすべてのソケットと接続タイムアウトを5秒に設定します。 RetryPolicyは、タイムアウトが発生したときに特定の要求を再試行する方法のロジックを実装する必要のあるインターフェイスです。

コンストラクタには、次の3つのパラメータがあります。

  • initialTimeoutMs - 再試行のたびに、ソケットタイムアウトをミリ秒単位で指定します。
  • maxNumRetries - 再試行が試行された回数。
  • backoffMultiplier - 再試行のたびにソケットに設定された指数時間を決定するために使用される乗数。

json request with volleyのサーバからのブール変数応答

あなたはカスタムクラスを1つ下にすることができます

private final String PROTOCOL_CONTENT_TYPE = String.format("application/json; charset=%s", PROTOCOL_CHARSET);

    public BooleanRequest(int method, String url, String requestBody, Response.Listener<Boolean> listener, Response.ErrorListener errorListener) {
        super(method, url, errorListener);
        this.mListener = listener;
        this.mErrorListener = errorListener;
        this.mRequestBody = requestBody;
    }

    @Override
    protected Response<Boolean> parseNetworkResponse(NetworkResponse response) {
        Boolean parsed;
        try {
            parsed = Boolean.valueOf(new String(response.data, HttpHeaderParser.parseCharset(response.headers)));
        } catch (UnsupportedEncodingException e) {
            parsed = Boolean.valueOf(new String(response.data));
        }
        return Response.success(parsed, HttpHeaderParser.parseCacheHeaders(response));
    }

    @Override
    protected VolleyError parseNetworkError(VolleyError volleyError) {
        return super.parseNetworkError(volleyError);
    }

    @Override
    protected void deliverResponse(Boolean response) {
        mListener.onResponse(response);
    }

    @Override
    public void deliverError(VolleyError error) {
        mErrorListener.onErrorResponse(error);
    }

    @Override
    public String getBodyContentType() {
        return PROTOCOL_CONTENT_TYPE;
    }

    @Override
    public byte[] getBody() throws AuthFailureError {
        try {
            return mRequestBody == null ? null : mRequestBody.getBytes(PROTOCOL_CHARSET);
        } catch (UnsupportedEncodingException uee) {
            VolleyLog.wtf("Unsupported Encoding while trying to get the bytes of %s using %s",
                    mRequestBody, PROTOCOL_CHARSET);
            return null;
        }
    }
}

あなたの活動でこれを使用してください

try {
        JSONObject jsonBody;
        jsonBody = new JSONObject();
        jsonBody.put("Title", "Android Demo");
        jsonBody.put("Author", "BNK");
        jsonBody.put("Date", "2015/08/28");
        String requestBody = jsonBody.toString();
        BooleanRequest booleanRequest = new BooleanRequest(0, url, requestBody, new Response.Listener<Boolean>() {
            @Override
            public void onResponse(Boolean response) {
                Toast.makeText(mContext, String.valueOf(response), Toast.LENGTH_SHORT).show();
            }
        }, new Response.ErrorListener() {
            @Override
            public void onErrorResponse(VolleyError error) {
                Toast.makeText(mContext, error.toString(), Toast.LENGTH_SHORT).show();
            }
        });
        // Add the request to the RequestQueue.
        queue.add(booleanRequest);
    } catch (JSONException e) {
        e.printStackTrace();
    }

リクエスト本体としてJSONArrayを使用する

volleyに組み込まれているデフォルトのリクエストでは、 POSTリクエストでリクエスト本体としてJSONArrayを渡すことはできません。代わりに、 JSONオブジェクトをパラメータとして渡すことしかできません。

ただし、リクエストコンストラクタにパラメータとしてJSONオブジェクトを渡す代わりに、 Request.class getBody()メソッドをオーバーライドする必要があります。 3番目のパラメータとしてnullも渡す必要がありnull

JSONArray requestBody = new JSONArray();

new JsonObjectRequest(Request.Method.POST, REQUEST_URL, null, RESP_LISTENER, ERR_LISTENER) {
    @Override
    public byte[] getBody() {
        try {
            return requestBody.toString().getBytes(PROTOCOL_CHARSET);
        } catch (UnsupportedEncodingException uee) {
            // error handling
            return null;
        }
    }
};

パラメータの説明:

  • REQUEST_URL - リクエストを送信する完全なURL。
  • RESP_LISTENER - 正常終了時にonResponse(T data)メソッドが呼び出されるResponse.Listener<?>オブジェクトResponse.Listener<?>
  • ERR_LISTENER - 失敗したリクエストに対してonErrorResponse(VolleyError e)メソッドが呼び出されるResponse.ErrorListenerオブジェクト。


Modified text is an extract of the original Stack Overflow Documentation
ライセンスを受けた CC BY-SA 3.0
所属していない Stack Overflow