Get Image, JSON data from URL by Volley


    In my previous post, I presented an overview of Volley, the official networking library in Android. With it, making networking calls much easier, faster without writing tons of code because we mustn't threading with AsyncTask or Handler,... By this post, I will present the way to request online data (Html String, JSON Object/Array, Image Bitmap) which available in an URL and parsing it after receiving.

Create a Volley Singleton

    Before coding, you must ensure that the importing Volley process has been completed. After creating a new Android project, we should create a Volley singleton. The best way to maintain volley core objects and request queue is, making them global by creating a singleton class which extends Application. Define the RequestQueue object in this:
package info.devexchanges.volley;

import android.app.Application;
import android.text.TextUtils;

import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.Volley;

public class VolleyApplication extends Application {

    private RequestQueue requestQueue;
    private ImageLoader imageLoader;

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

    @Override
    public void onCreate() {
        super.onCreate();
        instance = this;
    }

    public static synchronized VolleyApplication getInstance() {
        return instance;
    }

    public RequestQueue getRequestQueue() {
        if (requestQueue == null) {
            requestQueue = Volley.newRequestQueue(getApplicationContext());
        }

        return requestQueue;
    }

    public ImageLoader getImageLoader() {
        getRequestQueue();
        if (imageLoader == null) {
            imageLoader = new ImageLoader(this.requestQueue, new LRUBitmapCache());
        }
        return this.imageLoader;
    }

    public <T> void addToRequestQueue(Request<T> req, String tag) {
        // set the default tag if tag is empty
        req.setTag(TextUtils.isEmpty(tag) ? TAG : tag);
        getRequestQueue().add(req);
    }

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

    public void cancelPendingRequests(Object tag) {
        if (requestQueue != null) {
            requestQueue.cancelAll(tag);
        }
    }
}
   Later, I will present the way to request Image Bitmap from URL, so we should cached it after loading. It is also one of Volley strengths, caching data to restrict requesting to server or online sources. The Bitmap caching class was define as follow:
package info.devexchanges.volley;

import com.android.volley.toolbox.ImageLoader.ImageCache;

import android.graphics.Bitmap;
import android.support.v4.util.LruCache;

public class LRUBitmapCache extends LruCache<String, Bitmap> implements ImageCache {
    public static int getDefaultLruCacheSize() {
        final int maxMemory = (int) (Runtime.getRuntime().maxMemory() / 1024);
        final int cacheSize = maxMemory / 8;

        return cacheSize;
    }

    public LRUBitmapCache() {
        this(getDefaultLruCacheSize());
    }

    public LRUBitmapCache(int sizeInKiloBytes) {
        super(sizeInKiloBytes);
    }

    @Override
    protected int sizeOf(String key, Bitmap value) {
        return value.getRowBytes() * value.getHeight() / 1024;
    }

    @Override
    public Bitmap getBitmap(String url) {
        return get(url);
    }

    @Override
    public void putBitmap(String url, Bitmap bitmap) {
        put(url, bitmap);
    }
}

Creating String Request

    We will go from simple problems to complex ones. The first is StringRequest, will get data (in Html form) from an URL. By override Response.Listener<String>, we parsing responding Html data in onResponse() method and handling any errors by overriding Response.ErrorListener. Source code for this process:
private void getStringFromURL() {
        showProgressDialog();
        StringRequest strReq = new StringRequest(Request.Method.GET, STRING_URL, new Response.Listener<String>() {

            @SuppressLint("SetTextI18n")
            @Override
            public void onResponse(String response) {
                textView.setText("This text have been get from an URL: " + Html.fromHtml(response));
                textView.setVisibility(View.VISIBLE);
                dismissProgressDialog();
                imageLayout.setVisibility(View.GONE);
                listView.setVisibility(View.GONE);
                textLayout.setVisibility(View.VISIBLE);
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
                dismissProgressDialog();
                textView.setText("Error loading text!");
                dismissProgressDialog();
            }
        });

        // Adding request to request queue
        VolleyApplication.getInstance().addToRequestQueue(strReq, "string_request");
    }
   As you can see above code, always adding request to Queue with a tag name after all, Volley will automatically synchronize all of its mechanisms.
    In this project, output after this process completed:

Create a JSON Request

    Now, we are taking JSON from an URL. This request type is called JsonArrayRequest or JsonObjectRequest depend on your data. Also follow steps like string request above, we have this method:
private void getJSONFromURL() {
        showProgressDialog();

        JsonArrayRequest jsonObjReq = new JsonArrayRequest(Request.Method.GET, JSON_URL, null,
                new Response.Listener<JSONArray>() {

                    @Override
                    public void onResponse(JSONArray response) {
                        List<String> allNames = new ArrayList<>();
                        ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_dropdown_item_1line,
                                allNames);
                        listView.setAdapter(adapter);

                        try {
                            for (int i = 0; i < response.length(); i++) {
                                JSONObject friend = response.getJSONObject(i);
                                String name = friend.getString("name");
                                allNames.add(name);
                            }
                            //update adapter
                            adapter.notifyDataSetChanged();
                            listView.setVisibility(View.VISIBLE);
                            imageLayout.setVisibility(View.GONE);
                            textLayout.setVisibility(View.GONE);

                            dismissProgressDialog();
                        } catch (JSONException e) {
                            e.printStackTrace();
                            dismissProgressDialog();
                        }

                    }
                }, new Response.ErrorListener() {

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

        VolleyApplication.getInstance().addToRequestQueue(jsonObjReq, "json_request");
    }
    Output for this process (after parsing data, I have a strings List and display it to a ListView):


Create a Image Request

    In terms of mechanism of action, Image request is with string, json request on the same. But with this request type, data (Bitmap) will be cached after the first successful loading and this cached data used in the next times without having to request several times to online source. Moreover, we can direct use NetWorkImageView object in Volley framework to handle this loading progress. In follow code, I present both 2 ways,  ImageView and NetWorkImageView:
private void getImageFromURL() {
        showProgressDialog();
        ImageLoader imageLoader = VolleyApplication.getInstance().getImageLoader();
        // Using NetworkImageView
        networkImageView.setImageUrl(IMAGE_URL, imageLoader);
        networkImageView.setDefaultImageResId(R.mipmap.ic_launcher);

        // If you are using normal ImageView
        imageLoader.get(IMAGE_URL, new ImageLoader.ImageListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Image Load Error: " + error.getMessage());
                imageView.setImageResource(R.mipmap.ic_launcher);
                dismissProgressDialog();
            }

            @Override
            public void onResponse(ImageLoader.ImageContainer response, boolean arg1) {
                if (response.getBitmap() != null) {
                    imageView.setImageBitmap(response.getBitmap());
                    imageLayout.setVisibility(View.VISIBLE);
                    listView.setVisibility(View.GONE);
                    textLayout.setVisibility(View.GONE);
                }
                dismissProgressDialog();
            }
        });
    }
    And this process invoked by ImageLoader, not include in an any request queue!
    Output:

Final Activity code

    Including all 3 above methods in an Activity, we have this full code:
package info.devexchanges.volley;

import android.annotation.SuppressLint;
import android.app.ProgressDialog;
import android.support.v7.app.AppCompatActivity;
import android.os.Bundle;
import android.text.Html;
import android.util.Log;
import android.view.View;
import android.widget.ArrayAdapter;
import android.widget.ImageView;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.ScrollView;
import android.widget.Spinner;
import android.widget.TextView;

import com.android.volley.Cache;
import com.android.volley.Request;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.VolleyLog;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.JsonArrayRequest;
import com.android.volley.toolbox.JsonObjectRequest;
import com.android.volley.toolbox.NetworkImageView;
import com.android.volley.toolbox.StringRequest;

import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;

import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.List;

public class MainActivity extends AppCompatActivity {

    private LinearLayout imageLayout;
    private ListView listView;
    private ScrollView textLayout;
    private TextView textView;
    private Spinner spinner;
    private View btnRequest;
    private ImageView imageView;
    private NetworkImageView networkImageView;
    private ArrayList<String> stringArrayList;
    private ProgressDialog progressDialog;

    private final static String IMAGE_URL = "http://i.imgur.com/cReBvDB.png";
    private final static String STRING_URL = "http://httpbin.org/html";
    private final static String JSON_URL = "http://www.json-generator.com/api/json/get/cfgOSImXUy?indent=2";
    private final static String TAG = MainActivity.class.getSimpleName();

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
        spinner = (Spinner) findViewById(R.id.spinner);
        btnRequest = findViewById(R.id.btn_request);
        textLayout = (ScrollView) findViewById(R.id.ll_text);
        imageLayout = (LinearLayout) findViewById(R.id.ll_image);
        listView = (ListView) findViewById(R.id.list_item);
        imageView = (ImageView) findViewById(R.id.image);
        textView = (TextView) findViewById(R.id.text);
        networkImageView = (NetworkImageView) findViewById(R.id.img_network);

        btnRequest.setOnClickListener(onClickListener());
        setSpinnerData();
    }

    private View.OnClickListener onClickListener() {
        return new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                int position = spinner.getSelectedItemPosition();
                if (position == 0) {
                    getStringFromURL();
                } else if (position == 1) {
                    getJSONFromURL();
                } else {
                    getImageFromURL();
                }
            }
        };
    }

    private void setSpinnerData() {
        stringArrayList = new ArrayList<>();
        stringArrayList.add("String request");
        stringArrayList.add("JSON request");
        stringArrayList.add("Image request");

        ArrayAdapter<String> adapter = new ArrayAdapter<>(this, android.R.layout.simple_dropdown_item_1line, stringArrayList);
        spinner.setAdapter(adapter);
    }

    public void getImageFromURL() {
        showProgressDialog();
        ImageLoader imageLoader = VolleyApplication.getInstance().getImageLoader();
        // Using NetworkImageView
        networkImageView.setImageUrl(IMAGE_URL, imageLoader);
        networkImageView.setDefaultImageResId(R.mipmap.ic_launcher);

        // If you are using normal ImageView
        imageLoader.get(IMAGE_URL, new ImageLoader.ImageListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                Log.e(TAG, "Image Load Error: " + error.getMessage());
                imageView.setImageResource(R.mipmap.ic_launcher);
                dismissProgressDialog();
            }

            @Override
            public void onResponse(ImageLoader.ImageContainer response, boolean arg1) {
                if (response.getBitmap() != null) {
                    imageView.setImageBitmap(response.getBitmap());
                    imageLayout.setVisibility(View.VISIBLE);
                    listView.setVisibility(View.GONE);
                    textLayout.setVisibility(View.GONE);
                }
                dismissProgressDialog();
            }
        });
    }

    /**
     * Making String request from URL
     */
    private void getStringFromURL() {
        showProgressDialog();
        StringRequest strReq = new StringRequest(Request.Method.GET, STRING_URL, new Response.Listener<String>() {

            @SuppressLint("SetTextI18n")
            @Override
            public void onResponse(String response) {
                textView.setText("This text have been get from an URL: " + Html.fromHtml(response));
                textView.setVisibility(View.VISIBLE);
                dismissProgressDialog();
                imageLayout.setVisibility(View.GONE);
                listView.setVisibility(View.GONE);
                textLayout.setVisibility(View.VISIBLE);
            }
        }, new Response.ErrorListener() {

            @Override
            public void onErrorResponse(VolleyError error) {
                VolleyLog.d(TAG, "Error: " + error.getMessage());
                dismissProgressDialog();
                textView.setText("Error loading text!");
                dismissProgressDialog();
            }
        });

        // Adding request to request queue
        VolleyApplication.getInstance().addToRequestQueue(strReq, "string_request");
    }

    private void getJSONFromURL() {
        showProgressDialog();

        JsonArrayRequest jsonObjReq = new JsonArrayRequest(Request.Method.GET, JSON_URL, null,
                new Response.Listener<JSONArray>() {

                    @Override
                    public void onResponse(JSONArray response) {
                        List<String> allNames = new ArrayList<>();
                        ArrayAdapter<String> adapter = new ArrayAdapter<>(MainActivity.this, android.R.layout.simple_dropdown_item_1line,
                                allNames);
                        listView.setAdapter(adapter);

                        try {
                            for (int i = 0; i < response.length(); i++) {
                                JSONObject friend = response.getJSONObject(i);
                                String name = friend.getString("name");
                                allNames.add(name);
                            }
                            //update adapter
                            adapter.notifyDataSetChanged();
                            listView.setVisibility(View.VISIBLE);
                            imageLayout.setVisibility(View.GONE);
                            textLayout.setVisibility(View.GONE);

                            dismissProgressDialog();
                        } catch (JSONException e) {
                            e.printStackTrace();
                            dismissProgressDialog();
                        }

                    }
                }, new Response.ErrorListener() {

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

        VolleyApplication.getInstance().addToRequestQueue(jsonObjReq, "json_request");
    }

    private void showProgressDialog() {
        progressDialog = new ProgressDialog(this);
        progressDialog.setMessage("Loading...");
        progressDialog.setCancelable(false);
        progressDialog.show();
    }

    private void dismissProgressDialog() {
        if (progressDialog != null && progressDialog.isShowing()) {
            progressDialog.dismiss();
        }
    }
}
    And it's layout:

Important note: XML Request is missing

    As of now, Volley doesn’t provided any native classes to make XML requests and user must customize it. So, it's not suitable for request to SOAP Web Service, only support well for Restful ones, you can use java.net.URLConnection instead!

Conclusions

    Through this post, I've presented 3 simple/basic ways to get data from Internet, the tutorial post about request to REST web service is will available soon in next tutorials. Finally, thanks for reading and please subscribes my blog to see the newest tuts!

Share


Previous post
« Prev Post
Next post
Next Post »