How to Create an Imgur Client for Android

  Programming

Introduction

Imgur has a very powerful and easy-to-use API that allows you to programmatically access all its photos, albums, and galleries. In this tutorial, I’m going to show you how to use it to create a simple Imgur client for Android. Because it will be a native application, we’ll be working with the Android SDK and a few third-party Android libraries.

To keep this tutorial short, the Imgur client we’ll be creating now will be capable of only fetching and displaying photos from the usersub. In my opinion, that should give you a good idea of the kind of effort you’ll have to put in.

Here’s what we will be creating:

imgur app preview

Prerequisites

To be able to follow this tutorial, you’ll need the following:

  • The latest version of Android Studio
  • An Imgur account
  • An Android device or emulator running Android 4.4 or higher

1. Register Your App With Imgur

All Imgur clients must be registered. Therefore, before you do anything else, I suggest you log in to your Imgur account and register a new app for yourself. The registration process is quick and easy. For now, just make sure that the Authorization type field is set to Anonymous usage.

app registration

Once the registration is successful, you’ll be provided with a Client ID and Client Secret. Make a note of the Client ID because we’ll be using it soon.

app registration complete

2. Create an Android Studio Project

Launch Android Studio and create a new project that has one Empty Activity called MainActivity. Once the project has been generated, go to the manifest file and request for the INTERNET permission.

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

Next, go to the app module’s build.gradle file and add compile dependencies for Picasso and OkHttp.

compile 'com.squareup.picasso:picasso:2.5.2'
compile 'com.squareup.okhttp3:okhttp:3.4.1'

We’ll, of course, use Picasso to fetch and display the Imgur images. And, we’ll use OkHttp to fetch JSON information from the Imgur API servers.

Also add dependencies for the RecyclerView and CardView widgets.

compile 'com.android.support:recyclerview-v7:23.4.0'
compile 'com.android.support:cardview-v7:23.4.0'

3. Create the Layout

The layout of our app is going to be very simple. It will have just one RecyclerView that fills the screen completely. Therefore, add the following to the activity_main.xml file:

<android.support.v7.widget.RecyclerView
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:id="@+id/rv_of_photos">
    
</android.support.v7.widget.RecyclerView>

Let us now create a new layout XML file for the layout of the individual list items, which are going to be cards. So, create a file called item.xml, whose root element is a CardView. Inside the CardView, for now, just add an ImageView for the actual photo, and a TextView for the title associated with the photo. If you want to, you can always add more TextView widgets to display more information later.

<?xml version="1.0" encoding="utf-8"?>
<android.support.v7.widget.CardView
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="wrap_content"
    android:background="@android:color/white">
    <LinearLayout
        android:orientation="vertical" android:layout_width="match_parent"
        android:layout_height="match_parent">
        <ImageView
            android:layout_width="match_parent"
            android:layout_height="180dp"
            android:scaleType="centerCrop"
            android:id="@+id/photo"/>
        <TextView
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:id="@+id/title"
            android:textAppearance="@android:style/TextAppearance.Large"
            android:layout_margin="8dp"
            android:textAlignment="center"/>
    </LinearLayout>
</android.support.v7.widget.CardView>

The layouts are now ready, and we can move on to writing some Java code.

4. Fetch JSON Data From Imgur Servers

We’ll be using the OkHttp library now to fetch JSON data from Imgur’s API servers. So, add a new member variable to MainActivity, and initialize it inside a new method called fetchData(). Also, make sure that you add a call to fetchData() inside the onCreate() method.

private OkHttpClient httpClient;

private void fetchData() {
    httpClient = new OkHttpClient.Builder().build();
}

We can now build a Request object to connect to the API servers. This is the URL we’ll be using, which fetches the rising submissions from Imgur’s usersub gallery.:

https://api.imgur.com/3/gallery/user/rising/0.json

We must also remember to include the Client-ID as an authorization header. Here’s how you would create the request:

Request request = new Request.Builder()
                    .url("https://api.imgur.com/3/gallery/user/rising/0.json")
                    .header("Authorization","Client-ID abcdef1234561")
                    .header("User-Agent","My Little App")
                    .build();

To execute the request in a background thread, you must use the enqueue() method and pass a Callback object to it.

httpClient.newCall(request).enqueue(new Callback() {
    @Override
    public void onFailure(Call call, IOException e) {
        Log.e(TAG, "An error has occurred " + e);
    }

    @Override
    public void onResponse(Call call, Response response) throws IOException {
        // More code goes here
    }
});

Inside the onResponse() method, we must parse the response, which will be a JSON string. Before we do that, however, let us create a new class to represent each photo. So, add the following code to the MainActivity class:

private static class Photo {
    String id;
    String title;
}

The response of the Imgur API looks like this:

{
    "data": [
        {
            "account_id": 38891714, "account_url": "Idkwimh4",
            "comment_count": 10, "cover": "kYoThz7",
            "cover_height": 360, "cover_width": 540,
            "datetime": 1478970806, "description": null,
            "downs": 3, "favorite": false,
            "id": "ahJyF", "images_count": 22,
            "in_gallery": true, "is_ad": false,
            "is_album": true, "layout": "blog",
            "link": "http://imgur.com/a/ahJyF",
            "nsfw": false, "points": 75, "privacy": "public",
            "score": 75, "section": "",
            "title": "Fun doodle gif dump to dump to.",
            "topic": "No Topic",
            "topic_id": 29, "ups": 78, "views": 679,
            "vote": null
        },
        {
            "account_id": 44162823,
            "account_url": "qwqq",
            "comment_count": 5, "cover": "Y6YTQi7",
            "cover_height": 483, "cover_width": 484,
            "datetime": 1478970027, "description": null,
            "downs": 4,
            ...
            ...

As you can see, it contains a key called data whose value is a large array. That’s the array we’re interested in. Now, you must understand that the array contains both albums and photos. In this tutorial, we’ll be displaying only the photos, and the cover photos of the albums.

Add the following JSON parsing code to the onResponse() method:

JSONObject data = new JSONObject(response.body().string());
JSONArray items = data.getJSONArray("data");
final List<Photo> photos = new ArrayList<Photo>();

for(int i=0; i<items.length();i++) {
    JSONObject item = items.getJSONObject(i);
    Photo photo = new Photo();
    if(item.getBoolean("is_album")) {
        photo.id = item.getString("cover");
    } else {
        photo.id = item.getString("id");
    }
    photo.title = item.getString("title");
    
    photos.add(photo); // Add photo to list
}

The above code must be fairly intuitive. All we are doing is fetching the title and the id/cover id of each photo and adding it to an ArrayList of Photo objects.

Now that we have the photos, let us pass the list to a new method called render(). Make sure that the method is run on the UI thread.

runOnUiThread(new Runnable() {
    @Override
    public void run() {
        render(photos);
    }
});

Before we create the render() method, let us now create a RecyclerView.ViewHolder class for our RecyclerView. As you might expect, the view holder will have two fields, one for the ImageView and one for the TextView.

private static class PhotoVH extends RecyclerView.ViewHolder {
    ImageView photo;
    TextView title;

    public PhotoVH(View itemView) {
        super(itemView);
    }
}

And now, inside the render() method, initialize the RecyclerView using findViewById() and assign a layout manager to it.

private void render(final List<Photo> photos) {
    RecyclerView rv = (RecyclerView)findViewById(R.id.rv_of_photos);
    rv.setLayoutManager(new LinearLayoutManager(this));
}

It’s time to create a RecyclerView.Adapter. When you create it, Android Studio should automatically generate stubs for its three methods.

Inside the onCreateViewHolder() method, you must inflate the item.xml layout file and initialize the two views of the PhotoVH view holder using the findViewById() method.

Inside the getItemCount() method, you must simply return the size of the photos list.

Finally, inside the onBindViewHolder() method, you must use the position parameter to set the source of the ImageView. Similarly, set the text of the TextView. You must, of course, use the load() and into() methods of the Picasso class to load the photo into the ImageView asynchronously and on demand.

RecyclerView.Adapter<PhotoVH> adapter = new RecyclerView.Adapter<PhotoVH>() {
    @Override
    public PhotoVH onCreateViewHolder(ViewGroup parent, int viewType) {
        PhotoVH vh = new PhotoVH(getLayoutInflater().inflate(R.layout.item, null));
        vh.photo = (ImageView) vh.itemView.findViewById(R.id.photo);
        vh.title = (TextView) vh.itemView.findViewById(R.id.title);
        return vh;
    }

    @Override
    public void onBindViewHolder(PhotoVH holder, int position) {
        Picasso.with(MainActivity.this).load("https://i.imgur.com/" +
            photos.get(position).id + ".jpg").into(holder.photo);
        holder.title.setText(photos.get(position).title);
    }

    @Override
    public int getItemCount() {
        return photos.size();
    }
};

Finally, call the setAdapter() method to assign the adapter to the RecyclerView.

rv.setAdapter(adapter);

Furthermore, to add a little space between the cards, create and add an ItemDecoration to the RecyclerView.

rv.addItemDecoration(new RecyclerView.ItemDecoration() {
    @Override
    public void getItemOffsets(Rect outRect, View view, RecyclerView parent, RecyclerView.State state) {
        outRect.bottom = 16; // Gap of 16px
    }
});

You can now run the app to see your Imgur client in action.

imgur app running

Conclusion

You now know how to use the Imgur API to create an Android app for Imgur. There is, of course, more to the API than just fetching photos. You can read about it here.

If you found this article useful, please share it with your friends and colleagues!