LoginSignup
5
5

More than 5 years have passed since last update.

Volleyを無理矢理file schemeに対応してみる

Posted at

NetworkImageView#setImageUrl(String, ImageLoader)はfileスキームに未対応なので扱えるように改造してみました

BasicNetwork#performRequest()メソッドをOverrideしてfile schemeの場合はFileInputStream経由でデータを取得するようにしたらあっさりできました。

CustomNetwork.java
package com.example.volleysample;

import java.io.ByteArrayOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;

import org.apache.http.HttpStatus;

import android.net.Uri;
import android.util.Log;

import com.android.volley.NetworkError;
import com.android.volley.NetworkResponse;
import com.android.volley.Request;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.BasicNetwork;
import com.android.volley.toolbox.ByteArrayPool;
import com.android.volley.toolbox.HttpStack;
import com.example.volleysample.BuildConfig;

public class CustomNetwork extends BasicNetwork {
    private static final String TAG = CustomNetwork.class.getSimpleName();

    public CustomNetwork(HttpStack stack) {
        super(stack);
    }

    public CustomNetwork(HttpStack stack, ByteArrayPool pool) {
        super(stack, pool);
    }

    @Override
    public NetworkResponse performRequest(Request<?> request)
            throws VolleyError {
        // file schemeの場合は自前で処理
        Uri uri = Uri.parse(request.getUrl());
        if (uri != null && "file".equals(uri.getScheme())) {
            return performFileRequest(uri);
        }

        // file scheme以外の処理は親クラスに丸投げ
        return super.performRequest(request);
    }

    private NetworkResponse performFileRequest(Uri uri) throws VolleyError {
        File file = new File(uri.getPath());
        NetworkResponse response;
        if (file.exists()) {
            byte[] data = readBytes(file);
            response = new NetworkResponse(data);
        } else {
            // 404エラーを返す
            if (BuildConfig.DEBUG)
                Log.w(TAG, "performFileRequest: file not found: " + file);
            response = new NetworkResponse(HttpStatus.SC_NOT_FOUND, null,
                    Collections.<String, String> emptyMap(), false);
        }
        return response;
    }

    private byte[] readBytes(File file) throws VolleyError {
        if (BuildConfig.DEBUG) Log.d(TAG, "readBytes: reading data from " + file);
        byte[] data = null;
        try {
            ByteArrayOutputStream out = new ByteArrayOutputStream();
            InputStream in = null;
            try {
                in = new FileInputStream(file);
                byte[] buf = new byte[1024];
                int len = 0;
                while ((len = in.read(buf, 0, buf.length)) >= 0) {
                    out.write(buf, 0, len);
                }
                data = out.toByteArray();
                if (BuildConfig.DEBUG) Log.d(TAG, "readBytes: read " + data.length + " bytes.");
            } finally {
                if (in != null) in.close();
                if (out != null) out.close();
            }
        } catch (IOException e) {
            if (BuildConfig.DEBUG) Log.w(TAG, "readBytes: failed to read data", e);
            throw new NetworkError(e);
        }
        return data;
    }
}

実際に使う場合にはRequestQueueのコンストラクターにCustomNetworkのインスタンスを渡します。

    public static RequestQueue createRequestQueue(Context context, HttpStack stack, int maxCacheSizeInBytes) {
        File cacheDir = new File(context.getCacheDir(), DEFAULT_CACHE_DIR);

        String userAgent = "volley/0";
        try {
            String packageName = context.getPackageName();

            PackageInfo info = context.getPackageManager().getPackageInfo(packageName, 0);
            userAgent = packageName + "/" + info.versionCode;
        } catch (NameNotFoundException e) {
        }

        if (stack == null) {
            if (Build.VERSION.SDK_INT >= 9) {
                stack = new HurlStack();
            } else {
                // Prior to Gingerbread, HttpUrlConnection was unreliable.
                // See: http://android-developers.blogspot.com/2011/09/androids-http-clients.html
                stack = new HttpClientStack(AndroidHttpClient.newInstance(userAgent));
            }
        }

//        Network network = new BasicNetwork(stack);
        Network network = new CustomNetwork(stack); // ここだけ修正

        RequestQueue queue = new RequestQueue(new DiskBasedCache(cacheDir, maxCacheSizeInBytes), network);
        queue.start();

        return queue;
    }

5
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
5