JSON Feed Reader in Android

This tutorial series, we will build a JSON feed reader in Android. We will fetch all recent posts from javatechig.com (JSON Feed URL is listed below) and display post title, thumbnail, description on UI.  User can share s well as we can share the article using android share intent or may view the original website URL using android WebView.

http://javatechig.com/api/get_category_posts/?dev=1&slug=android

Here in this example, we can learn about below things
-     Designing User Interface
-     Using AsyncTask to Download Data From Remote Server
-     JSON Parsing In Android
-     Downloading Image Asynchronously and Displaying In Android ListView
-     Using Share Intent to Share Article in Android
-     Loading Original Feed Link on Android WebView

1. Designing User Interface

Here in this example, we are using three Activities. While first Activity is used to list out all feed items on a ListView, Second one is used to show the image preview and the description of each feed. Another Activity is used to view the original feed item on a WebView.

Below are the listed three activity classes
-    com.javatechig.feedreader.FeedDetailsActivity
–    com.javatechig.feedreader.FeedListActivity
–    com.javatechig.feedreader.WebViewActivity

In this tutorial, I assume you already have knowledge of creating basic user interfaces. We will be creating the layouts as shown in the images below.

json-feed-reader-android-featured-715x300

On landing page of my example, It uses a ListView which can dislay thumbnail image, title and date published, so here we need to create a custom ListView.

If you are not proficient on creating such custom ListView, then you may visit my previous post on “Android ListView Tutorial”.

For simplicity sake, our previous ListView Tutorial was using static data for list. But in this example, I am fetching the data from JavatechIG feed server and then displaying on list view. During fetching data from server it will display a loading ProgressBar on screen and disappears once the list items are downloaded. Let’s start getting our the code to build the user interface set up.

activity_post_list.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:orientation="vertical" >
 
    <ProgressBar
        android:id="@+id/progressBar"
        style="?android:attr/progressBarStyleLarge"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center" />
 
    <ListView
        android:id="@+id/custom_list"
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:cacheColorHint="#00000000"
        android:dividerHeight="1dp"
        android:focusable="false"
        android:listSelector="@drawable/list_selector_flatcolor"
        android:visibility="gone" />
 
</FrameLayout>

In the above xml code, we are using FrameLayout. We will be displaying either of the UI widgets. During loading we will display ProgressBar and then we will display ListView after feed data is downloaded.

list_row_layout.xml

This layout will be used for ListView row. Each Row is an RelativeLayout with an ImageView and two TextViews placed adjacent to ImageView.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:minHeight="50dp"
    android:orientation="horizontal" >
 
    <ImageView
        android:id="@+id/thumbImage"
        android:layout_width="70dp"
        android:layout_height="70dp"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:background="@drawable/list_placeholder" />
 
    <TextView
        android:id="@+id/title"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_toRightOf="@id/thumbImage"
        android:lineSpacingExtra="3dp"
        android:paddingLeft="5dp"
        android:paddingTop="5dp"
        android:text=""
        android:textColor="@drawable/list_item_text_selector"
        android:textStyle="bold"
        android:typeface="sans" />
 
    <TextView
        android:id="@+id/date"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/title"
        android:layout_toRightOf="@id/thumbImage"
        android:paddingLeft="5dp"
        android:paddingTop="5dp"
        android:text=""
        android:textColor="@drawable/list_item_text_selector"
        android:textSize="11sp" />
 
</RelativeLayout>

In the above code, I have used “list_item_text_selector” for changing the TextView color while list row is pressed.

list_item_text_selector.xml
1
2
3
4
5
6
7
8
<?xml version="1.0" encoding="UTF-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
    <item android:state_pressed="true" 
        android:color="@color/text_color_inverse" />
    <item android:state_focused="true" 
        android:color="@color/text_color_inverse" />
    <item android:color="@color/text_color_default" />
</selector>

We are ready with the layout for FeedList Screen. Now lets create a custom Adapter.

CustomListAdapter.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
public class CustomListAdapter extends BaseAdapter {
	private ArrayList listData;
	private LayoutInflater layoutInflater;
	private Context mContext;
 
	public CustomListAdapter(Context context, ArrayList listData) {
		this.listData = listData;
		layoutInflater = LayoutInflater.from(context);
		mContext = context;
	}
 
	@Override
	public int getCount() {
		return listData.size();
	}
 
	@Override
	public Object getItem(int position) {
		return listData.get(position);
	}
 
	@Override
	public long getItemId(int position) {
		return position;
	}
 
	public View getView(int position, View convertView, ViewGroup parent) {
		ViewHolder holder;
		if (convertView == null) {
			convertView = layoutInflater.inflate(R.layout.list_row_layout, null);
			holder = new ViewHolder();
			holder.headlineView = (TextView) convertView.findViewById(R.id.title);
			holder.reportedDateView = (TextView) convertView.findViewById(R.id.date);
			holder.imageView = (ImageView) convertView.findViewById(R.id.thumbImage);
			convertView.setTag(holder);
		} else {
			holder = (ViewHolder) convertView.getTag();
		}
 
		FeedItem newsItem = (FeedItem) listData.get(position);
		holder.headlineView.setText(newsItem.getTitle());
		holder.reportedDateView.setText(newsItem.getDate());
 
		if (holder.imageView != null) {
			new ImageDownloaderTask(holder.imageView).execute(newsItem.getAttachmentUrl());
		}
 
		return convertView;
	}
 
	static class ViewHolder {
		TextView headlineView;
		TextView reportedDateView;
		ImageView imageView;
	}
}

Now you must be getting some compilation error for FeedItem. FeedItem is an model class used for reading feeds. It has the following fields with public getter and setter methods.

FeedItem.java
1
2
3
4
5
6
7
8
public class FeedItem implements Serializable {
	private String title;
	private String date;
	private String attachmentUrl;
	private String id;
	private String content;
	private String url;
}

Now, we are ready for the first screen layout. Let’s move on to the FeedDetailsActivity layout. In this screen we have thumbnail image, title and the content to be displayed. Below is the layout code snippet.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#ffffff"
    android:orientation="vertical" >
 
    <RelativeLayout
        android:layout_width="fill_parent"
        android:layout_height="200dp" >
 
        <ImageView
            android:id="@+id/featuredImg"
            android:layout_width="fill_parent"
            android:layout_height="fill_parent" >
        </ImageView>
 
        <TextView
            android:id="@+id/title"
            android:layout_width="fill_parent"
            android:layout_height="100dp"
            android:layout_alignParentBottom="true"
            android:background="@drawable/image_border"
            android:ellipsize="end"
            android:gravity="bottom"
            android:lineSpacingExtra="3dp"
            android:maxLines="2"
            android:padding="5dp"
            android:text=""
            android:textColor="#00000c"
            android:textStyle="bold" />
    </RelativeLayout>
 
    <ScrollView
        android:layout_width="fill_parent"
        android:layout_height="fill_parent"
        android:padding="5dp" >
 
        <TextView
            android:id="@+id/content"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:text=""
            android:textColor="#00000c" />
    </ScrollView>
 
</LinearLayout>

In FeedDetailsActivity, we are using Android ActionBar commands.

menu.xml
1
2
3
4
5
6
7
8
9
10
11
12
13
14
<menu xmlns:android="http://schemas.android.com/apk/res/android" >
 
    <item
        android:id="@+id/menu_share"
        android:icon="@android:drawable/ic_menu_share"
        android:showAsAction="always"
        android:title="Share"/>
    <item
        android:id="@+id/menu_view"
        android:icon="@android:drawable/ic_menu_info_details"
        android:showAsAction="always"
        android:title="View"/>
 
</menu>

Now we are done with all xml layouts. Let us have a look into the Activity components

2. Using AsyncTask to Download Data from Remote Server

AsyncTask enables you to implement MultiThreading without get Hands dirty into threads. AsyncTask enables proper and easy use of the UI thread. It allows performing background operations and passing the results on the UI thread. If we are doing something isolated related to UI, for example downloading data and prepare for a list, it is recemended to use AsyncTask.

http://javatechig.com/android/difference-between-handler-and-asynctask-in-android/

DownloadFeedTask.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
private class DownloadFilesTask extends AsyncTask<String, Integer, Void> {
 
		@Override
		protected void onProgressUpdate(Integer... values) {
		}
 
		@Override
		protected void onPostExecute(Void result) {
			if (null != feedList) {
				updateList();
			}
		}
 
		@Override
		protected Void doInBackground(String... params) {
			String url = params[0];
 
			// getting JSON string from URL
			JSONObject json = getJSONFromUrl(url);
 
			//parsing json data
			parseJson(json);
			return null;
		}
	}
Downloading JSON from server

As downloading of feed data from JavatechIG is a long running task, we are doing it inside doInBackground method. Once we have the data downloaded and parsed, then we can update the ListView with appropriate updated data.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
public JSONObject getJSONFromUrl(String url) {
		InputStream is = null;
		JSONObject jObj = null;
		String json = null;
 
		// Making HTTP request
		try {
			// defaultHttpClient
			DefaultHttpClient httpClient = new DefaultHttpClient();
			HttpPost httpPost = new HttpPost(url);
 
			HttpResponse httpResponse = httpClient.execute(httpPost);
			HttpEntity httpEntity = httpResponse.getEntity();
			is = httpEntity.getContent();
 
			BufferedReader reader = new BufferedReader(new InputStreamReader(
					is, "iso-8859-1"), 8);
			StringBuilder sb = new StringBuilder();
			String line = null;
			while ((line = reader.readLine()) != null) {
				sb.append(line + "\n");
			}
			is.close();
			json = sb.toString();
		} catch (UnsupportedEncodingException e) {
			e.printStackTrace();
		} catch (ClientProtocolException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		}
 
		try {
			jObj = new JSONObject(json);
		} catch (JSONException e) {
			Log.e("JSON Parser", "Error parsing data " + e.toString());
		}
 
		// return JSON String
		return jObj;
 
	}

The above method will download the Json feed and returned as a JSONObject. Now its the time to parse the JSON feed data

3. JSON Parsing In Android

The aove Feed link gives the below JSON object structure.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
{
   "status": "ok",
   "count": 10,
   "pages": 3,
   "posts": [
      {
         "id": 2398,
         "type": "post",
         "slug": "asynchronous-image-loader-in-android-listview",
         "url": "http://javatechig.com/android/asynchronous-image-loader-in-android-listview/",
         "status": "publish",
         "title": "Asynchronous Image Loader in Android ListView",
         "date": "2013-06-01 19:31:07",
         "attachments": [
            {
               "id": 2402,
               "url": "http://javatechig.com/wp-content/uploads/2013/06/Async_ListView.png",
               "slug": "async_listview",
               "title": "Async_ListView",
               "description": "",
               "caption": "",
               "parent": 2398,
               "mime_type": "image/png",
               "images": []
            }
         ],
         "comment_count": 3
      }
   ]
}

From this above structure we will be needing the title, date, url and attachment url. check out the code snippet below for json parsing.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
public void parseJson(JSONObject json) {
    try {
 
        // parsing json object
        if (json.getString("status").equalsIgnoreCase("ok")) {
            JSONArray posts = json.getJSONArray("posts");
 
            feedList = new ArrayList();
 
            for (int i = 0; i < posts.length(); i++) {
                JSONObject post = (JSONObject) posts.getJSONObject(i);
                FeedItem item = new FeedItem();
                item.setTitle(post.getString("title"));
                item.setDate(post.getString("date"));
                item.setId(post.getString("id"));
                item.setUrl(post.getString("url"));
                item.setContent(post.getString("content"));
                JSONArray attachments = post.getJSONArray("attachments");
                if (null != attachments && attachments.length() > 0) {
                    JSONObject attachment = attachments.getJSONObject(0);
                    if (attachment != null)
                    item.setAttachmentUrl(attachment.getString("url"));
                }
 
                feedList.add(item);
            }
        }
        } catch (JSONException e) {
        e.printStackTrace();
    }
}

4. Downloading Image Asynchronously

A good practice to bring the best performance for android application is to make sure your main thread does the minimum amount of work. Any long running tasks or heavy operations are usually performed in a different thread. Typical long running tasks could be network operations, reading files form memory, animations, etc.

Check out the below post for detailed implementation

http://javatechig.com/android/asynchronous-image-loader-in-android-listview/

5. Share Article in Android

One of the best and most useful feature is sharing of information across different social networks. Android platform provides handy way of sharing contents across different application using Share Intent. It lists out all of the available application that can handle the share event. Check out the code snippet

1
2
3
4
5
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, feed.getTitle()+"\n"+feed.getUrl());
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, "Share using"));

Note: As sharing intent is taken care by platform, we don’t have control on the way and behavior of each application while sharing. For example, twitter has a limit of maximum of 140 characters for a message.

6. Loading url on Android WebView

We have an excellent post on using WebView in another section on our site. It will gives complete understanding on loading external URL on android WebView and different configurations.

http://javatechig.com/android/android-webview-example/

http://javatechig.com/android/display-html-in-android-textview/

http://javatechig.com/android/progressbar-while-loading-webview/

7. Download Complete Example

dl_github

8. Working Demo

9. References

http://developer.android.com/reference/android/os/AsyncTask.html

About Nilanchala

A blogger, bit of a tech freak and a software developer. Follow him on Twitter, or like our official Facebook page or Google Plus.

  • http://javatechig.com/ javatechig

    Thanks Sophie..
    This example is more intended for tutorial purpose. You can surely extend the functionality.

    I will certainly do this on my time. thanks

  • Suyash

    Hi, how are you downloading the thumbnail image to show it in list view?

  • http://javatechig.com/ javatechig

    Can you come clear with your question??

  • Matt

    Hi,
    How can I open the hole content in a web view instead of open the content in separate ways? I tried to load the hole content in the web view instead of using the more info button on the action bar, but it does not work?

    Thanks the tutorial is great but I wanna see if I can do it that way, please help me

    Thanks! keep up the good work!

  • Noob

    In the “Download Complete Example” section there is no link, could you provide a link to the github source.

  • droid12

    Nice tutorial, but when i try to use some other rss link it doesn’t work, gives a force close error. can u please tell me what should be done to load from any rss link on the web. thank you

    • http://javatechig.com/ javatechig

      Would you mind checking the structure of JSON file? If it is the same then it shouldn’t cause any problem. However, if you still face problem, don’t forget to put your logs here.

      • Mahmut

        “Nice tutorial, but when i try to use some other rss link it doesn’t work, gives a force close error. can u please tell me what should be done to load from any rss link on the web. thank you”
        He tells the truth ,
        because
        me too
        , I can’t connect with a rss
        because
        “http://javatechig.com/api/get_category_posts/?dev=1&slug=android”
        url be problem for me
        but
        If you can write one rss link
        u can help to we
        for example
        http://javatechig.com/feed/rss
        or
        http://javatechig.com/feed/rss.xml
        or
        http://javatechig.com/feed/rss.php
        thanks (:

        • http://javatechig.com/ javatechig

          Please have a look at the structure of the json. Make sure it is same as mu Json feed, otherwise you have to change your parser code.

          • Mahmut

            ok . I will look
            and
            I will trying
            for understand
            thanks for answer

  • avo28

    Reformulating the first question.

    Special characters .. accentuation and letrra “Ñ”

    I have the following:

    newsData.setHeadline(“Maxichicos”);

    newsData.setReporterName(“Este envase de tamaño pequeño es muy útil para almacenar diversidad de alimentos”);

    newsData.setUrl(“http://www………………………com”);

    obvious … the letter “Ñ” and come with accentuation because they are strange characters. java

    and not called from string.xml as it should be ..

    my question is!! and from. called a string.xml java?

    I just want to know that to be clear in the future.

    because as previously asked, need take the picture information from a TXT from the same server ..

    example ..

    private ArrayList getListData() {

    ArrayList results = new ArrayList();

    NewsItem newsData = new NewsItem();

    newsData.setHeadline(“TXT file name from the server”);

    newsData.setReporterName(“TXT destination from the server”);

    newsData.setUrl(“http://www…………….casa.jpg”);

    results.add(newsData);

    Please be annoying too. Can you help me

    • http://javatechig.com/ javatechig

      It should work as long as the characters are utf-8 encoded.

  • Dickson Owuor

    nice job, very helpful

  • Sebastian

    Nice but I would use a library to work with http and json. My personal vote for https://github.com/kodart/Httpzoid

  • Modo

    great tut but when i install the project in eclipse it closing when i try to open it

  • effr22

    First of all, thanks for all the great tutorials. I’m starting to program in Android and I found them pretty useful. Since I’m new, I don’t know why I can’t seem to run this app in my virtual device (version 4.2.2) It always shows a FeedReader has stopped message. I really wanted to try it to see how it works. I was hoping someone could help me figure this out. I check the logcat and there’s a bunch of warnings saying :”Unexpected value from NativeGetEnabledTags: 0″ and here is a picture of the errors I get. Any help is appreciated.

  • http://marki-tos.tumblr.com/ Todo poderoso

    Nice! but pagination?

    • http://javatechig.com/ javatechig

      @markitoz:disqus, We have just implemented a sample example for demonstrations purpose. However, you can still expand it to support pagination features.

      • http://marki-tos.tumblr.com/ Todo poderoso

        You know when you finish the scroll paging?