Android
ボレー
サーチ…
前書き
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には非公式の文書がホストされていますが、将来的にこれをホストするのに適した場所があるはずです。
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
オブジェクト。