GAG Pictures – Have Fun! Spread The Fun!

9gag picturesHello everyone, I would like to introduce you my second Android application published on Google Play  – GAG Pictures. Compared with the first one, this application is intended to bring you much fun.

GAG Pictures is your daily set of funny images! Every time the application is launched it downloads a set of new funny images from the famous site 9gag.com. Every image has a Share button so you can share that hilarious image with your friends. The current version allows you to share only the direct link to image, but in the upcoming releases the ability to send the image itself will be provided.

9gag funny image

Have fun! 🙂

Get it on Google Play - GAG Pictures

How to verify an RSS Feed if New Articles have been published.

Recently I built an rss app for a site that publishes daily IT News – ITMoldova.com. The main feature of application is to launch a service in background (at a given interval of time), and check if new articles have been published on http://itmoldova.com site. If it turns out that new articles have been published, then fire a notification message and notify the user about this, something like this: “4 New Articles Published on ITMoldova.com”.

How to identify how many articles were published?

The mechanism to identify if new articles have been published on the site (and how many) is pretty straightforward: when the application is installed and launched for the first time, it parses the Rss Feed and creates a new entry in the SharedPreferences with the value of <pubDate> element, of the first item from the rss list (pubDate = publication date). Then, everytime the service starts, it parses the RSS Feed and checks the value of first item from the rss list against the value stored in SharedPreferences, if the value stored in SharedPreferences is less than value returned by the service, then it means that there are new articles and it’s time to notify the user! Lastly, update the SharedPreferences with the most recent pubDate.

For the sake of simplicity and keeping things consistent, I will post here only snippets of most relevant code, but this will be good enough to give you an idea about how things works.

How to compare two dates?

To compare the dates we need to convert them to milliseconds. The getTime() method of Date class can help us return the number of milliseconds of a given date:

Date date=new Date();
int timeMilliseconds=date.getTime();

 

Below is the implementation of verifyDates(String, String) method that will be used by the Service. The method takes 2 string parameters, the pubDate of rss item, and the pubDate stored in SharedPreferences.


public class Tools {
  public int newArticles;
  public boolean hasMoreArticles = true;

  public void verifyDates(String rssPubDate, String sharedPrefLastPubDate) {
    if (hasMoreArticles) {
      SimpleDateFormat df = new SimpleDateFormat("dd MMM yyyy HH:mm:ss Z", Locale.ENGLISH);
      Date dLastPubDate = null;
      Date dRssPubDate = null;

      try {
        dLastPubDate = df.parse(sharedPrefLastPubDate.substring(5));
        dRssPubDate = df.parse(rssPubDate.substring(5));
      } catch (ParseException e) {
        Log.d("GREC", "Exception in verifayDates: " + e.getMessage());
        e.printStackTrace();
      }

      //We want to count how many new articles were published.
      if (dRssPubDate.getTime() > dLastPubDate.getTime()) {
        newArticles++;
      } else {
        hasMoreArticles = false;
      }
    }
  }

}
The Service Implementation

The service will parse the Rss Feed and do the comparison. Also, it will launch a status bar notification if it turns out that new articles were published.

public class RssService extends IntentService {

  public RssService() {
    super("ITMoldovaRssService");
  }

  @Override
  protected void onHandleIntent(Intent intent) {

    // Retrieve the date from SharedPreferences
    String lastPubDate = getDateFromSharedPrefs();

    // The AndroidFeedParser class helps us parse the Rss Feed.
    AndroidFeedParser parser;

    try {
      parser = new AndroidFeedParser(new URL("http://itmoldova.com/feed/"));
      List<Message> list = parser.parse();

      if (list != null) {
        for (int i = 0; i < list.size(); i++) {

          // Verify the pubDate of each item, against pubDate stored in SharedPreferences
          tools.verifyDates(list.get(i).getDate(), lastPubDate);
        }

        // Get the last pubDate and save it to SharedPreferences.
        lastPubDate = list.get(0).getDate();
        saveToSharedPreferences(lastPubDate);
      }
    } catch (MalformedURLException e) {
      Log.d("GREC", "Malformed URL Exception: " + e.getMessage());
      e.printStackTrace();
    }

    if (tools.newArticles > 0) {
      displayNotification();
    } else {
      Log.d("GREC", "No new articles ");
    }
  }
}

 

The service begins with parsing the Rss Feed and return the list of items:

List<Message> list = parser.parse();

then iterate through it comparing the publication date:

for (int i = 0; i < list.size(); i++) {
    // Verify the pubDate of each item, against pubDate stored in SharedPreferences
    tools.verifyDates(list.get(i).getDate(), lastPubDate);
}

and then ends getting the most recent publication date and saving it to SharedPreferences:

// Get the last pubDate and save it to SharedPreferences.
lastPubDate = list.get(0).getDate();
saveToSharedPreferences(lastPubDate);

If it turns out that new articles were published, display a status bar notification.

if (tools.newArticles > 0) {
displayNotification();
}

 

How to parse an XML feed and how to display a status bar notification are some helper topics you may need to take a look in order to fully complete this task.

Drawing Shapes in Android

In this post I would like to share my findings about defining and using shapes.  A shape is an XML file that defines a geometric shape, including strokes, colors and gradients

Android Shapes

To define a shape:

1. Create a new Android XML file in the folder res/drawable

2. Make sure the root element of the file is <shape >. (If it’s not, then change it manually)

3. Inside the <shape> element, press CTRL + Space to reveal all the available elements you can use to define a shape:

android shapes options

As you can see, the elements are pretty self explanatory. To reveal the attributes of an element, put the cursor inside that element and press CTRL + Space:

android shape corner

4. Once the shape is defined, you can specify it as a background resource to any view: android:background=”@drawable/myshape”

Example:

res/drawable/boxbg.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

<stroke
  android:width="2dp"
  android:color="#FFFFFF" />

<corners android:radius="5dp" />

<gradient
  android:angle="270"
  android:centerColor="#6E7FFF"
  android:endColor="#142FFC"
  android:startColor="#BAC2FF" />

</shape>

 

res/drawable/box2bg.xml:

<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android" >

<solid android:color="#4D9611" />

<stroke
  android:width="4dp"
  android:color="#FFFB00" />

</shape>

 

res/layout/main.xml:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<!-- First box, boxbg.xml -->
<LinearLayout
  android:layout_width="match_parent"
  android:layout_height="80dp"
  android:layout_margin="20dp"
  android:background="@drawable/boxbg"
  android:orientation="vertical"
  android:padding="5dp" >

  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    android:textColor="#000"
    android:textSize="20dp" />
</LinearLayout>

<!-- Second box, box2bg.xml -->
<LinearLayout
  android:layout_width="match_parent"
  android:layout_height="80dp"
  android:layout_margin="20dp"
  android:background="@drawable/box2bg"
  android:orientation="vertical"
  android:padding="7dp" >

  <TextView
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:text="@string/hello"
    android:textColor="#FFF"
    android:textSize="20dp" />
</LinearLayout>

</LinearLayout>

 

The final output should look like this:

android shape

Creating A Simple RSS Application in Android

In this tutorial we will build a simple rss application.

Requirements are:
1) parse an rss feed and display the headlines in a ListView
2) when the user clicks on a headline, open the Android browser and redirect to corresponding web page.


Note: this tutorial is outdated. I would suggest you follow the new tutorial. The new tutorial is more extended, but it addresses few issues present in this example. On the other hand, if you are not looking for a very detailed tutorial and are interested only in XML parsing part, feel free to browse this example.

We will parse the PCWorld‘s rss looking for the latest news: http://feeds.pcworld.com/pcworld/latestnews

The final result will look like in the screenshot below:

android rss app

1. Create a new project in Eclipse:
Project: SimpleRssReader
Activity: SimpleRssReaderActivity

2. Add required permissions to AndroidManifest file.
The application will make use of Internet, so this should be specified in the AndroidManifest file, otherwise an exception will be thrown. Just after the <application> tag, (as a child of <manifest> tag), add the following line:

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

3. Open the main.xml layout file, delete the already existing TextView control, and add instead a ListView with the id “list”. This should should look like this:

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical" >

<ListView
android:id="@+android:id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>

</LinearLayout>

4. Lets create the skeleton of our main activity.
Open the SimpleRSSReaderActivity and make it extend ListActivity, instead of Activity as it  comes by default. We need this in order to display the headlines in the ListView by binding to an array which will hold our data, using the list view adapter.
Add 2 instance variables: “headlines” and “links” of type List.

It should look like this:

public class SimpleRSSReaderActivity extends ListActivity {

	List headlines;
	List links;

	@Override
	public void onCreate(Bundle savedInstanceState) {
		super.onCreate(savedInstanceState);
		setContentView(R.layout.main);

	}
}

5. In the onCreate() method, just after the setContentView(….) , add following lines:

// Initializing instance variables
headlines = new ArrayList();
links = new ArrayList();

try {
	URL url = new URL("http://feeds.pcworld.com/pcworld/latestnews");

	XmlPullParserFactory factory = XmlPullParserFactory.newInstance();
	factory.setNamespaceAware(false);
	XmlPullParser xpp = factory.newPullParser();

        // We will get the XML from an input stream
	xpp.setInput(getInputStream(url), "UTF_8");

        /* We will parse the XML content looking for the "<title>" tag which appears inside the "<item>" tag.
         * However, we should take in consideration that the rss feed name also is enclosed in a "<title>" tag.
         * As we know, every feed begins with these lines: "<channel><title>Feed_Name</title>...."
         * so we should skip the "<title>" tag which is a child of "<channel>" tag,
         * and take in consideration only "<title>" tag which is a child of "<item>"
         *
         * In order to achieve this, we will make use of a boolean variable.
         */
	boolean insideItem = false;

        // Returns the type of current event: START_TAG, END_TAG, etc..
	int eventType = xpp.getEventType();
	while (eventType != XmlPullParser.END_DOCUMENT) {
		if (eventType == XmlPullParser.START_TAG) {

			if (xpp.getName().equalsIgnoreCase("item")) {
				insideItem = true;
			} else if (xpp.getName().equalsIgnoreCase("title")) {
				if (insideItem)
					headlines.add(xpp.nextText()); //extract the headline
			} else if (xpp.getName().equalsIgnoreCase("link")) {
				if (insideItem)
					links.add(xpp.nextText()); //extract the link of article
			}
		}else if(eventType==XmlPullParser.END_TAG && xpp.getName().equalsIgnoreCase("item")){
			insideItem=false;
		}

		eventType = xpp.next(); //move to next element
	}

} catch (MalformedURLException e) {
	e.printStackTrace();
} catch (XmlPullParserException e) {
	e.printStackTrace();
} catch (IOException e) {
	e.printStackTrace();
}

// Binding data
ArrayAdapter adapter = new ArrayAdapter(this,
		android.R.layout.simple_list_item_1, headlines);

setListAdapter(adapter);

6. In the onCreate() method we passed an input stream to setInput(): xpp.setInput(getInputStream(url), "UTF_8");
getInputStream() is not a standard Java method, so we should create it. This method should take as an argument the feed url, and return the input stream.


public InputStream getInputStream(URL url) {
   try {
       return url.openConnection().getInputStream();
   } catch (IOException e) {
       return null;
     }
}

7. Finnaly, we want when a title is clicked, the Android browser to be opened and display the corresponding article. This one is simple, we override the onListItemClick() method, get the position of article in the ListView, retrieve the coresponding link, and pass the url of that article to ACTION_VIEW intent which takes care further of displaying the web page.


@Override
protected void onListItemClick(ListView l, View v, int position, long id) {
   Uri uri = Uri.parse(links.get(position));
   Intent intent = new Intent(Intent.ACTION_VIEW, uri);
   startActivity(intent);
}

By this time you should compile and run successfully the application.

Well, if everything went fine and you are done with the simple rss application, the next step to consider is how can you enhance the visual aspect of the application. Adding some style to the ListView, for example alternating between background colors, or displaying an icon next to each headline, can considerably increase the visual aspect, which will make your application look more appealing.
Take a look at this tutorial: Building a Custom Fancy ListView in Android, where I show in details how to achieve this.

This application, however, has one major drawback. Its drawback is that all the parsing and network access is done on the UI thread. As a result, you may notice that when starting the application, it “freezes” for a few seconds and then displays the headlines. To fix this issue, you should put all the parsing functionality in a background thread. In regards how to do that, you definitely should consider this post: Understanding AsyncTask – Once and Forever