Archive
Android – Scheduling an application to start later.
Recently I have been working on a simple application that should have the ability to start itself after a period of time, after the application is closed. Hopefully, it turned out that this is quite simple to implement, and to achieve this, the AlarmManager in conjuction with a BroadcastReceiver can be used.
The basic idea is as follows: the AlarmManger registers an intent, when the alarm goes off, the intent that had been registered automatically will start the target application if it is not already running. The BroadcastReceiver will be listening for that intent, and when the intent is received, it will start the desired activity from the application.
The broadcast receiver implementation looks like this:
public class OnAlarmReceive extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
Log.d(Globals.TAG, "BroadcastReceiver, in onReceive:");
// Start the MainActivity
Intent i = new Intent(context, MainActivity.class);
i.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
context.startActivity(i);
}
}
Register the OnAlarmReceive in the AndroidManifest file:
<application
android:icon="@drawable/ic_launcher"
android:label="@string/app_name" >
// ......
<receiver
android:name=".OnAlarmReceive" />
</application>
And finally, here’s how to setup the alarm:
/**
* Sets up the alarm
*
* @param seconds
* - after how many seconds from now the alarm should go off
*/
private void setupAlarm(int seconds) {
AlarmManager alarmManager = (AlarmManager) getSystemService(ALARM_SERVICE);
Intent intent = new Intent(getBaseContext(), OnAlarmReceive.class);
PendingIntent pendingIntent = PendingIntent.getBroadcast(
MainActivity.this, 0, intent,
PendingIntent.FLAG_UPDATE_CURRENT);
Log.d(Globals.TAG, "Setup the alarm");
// Getting current time and add the seconds in it
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, seconds);
alarmManager.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), pendingIntent);
// Finish the currently running activity
MainActivity.this.finish();
}
The last line from the code – finishing the current activity – is optional of course, but in case you need to finish the activity, here’s how to do.
For a live demo of the code, download the Amazing Cracked Screen application and see how it works. There you have the possibility to set up the delay in seconds when the application should start later and show the “broken” screen.
ITMoldova – My First Android Application.
Although it has passed awhile since I published my first android application on Google Play, and I published already my second Android App meanwhile, I decided to write about it as well, as almost all my posts from this blog till now are findings and experience gained while I was working on ITMoldova app.
ITMoldova.com is a Moldavian site that provides daily IT News for romanian speaking people. The main purpose of Android application is to check the RSS feed of the site if there are any new articles. If it turns out that new articles have been published on the site, then launch a status bar notification and notify the user. And of course, the user is able to see the most recent articles and read them right from his device.
The application settings provides the ability to set up the desired interval of time, when the application should verify the RSS feed, plus the possibility to Turn On or Off this feature.
I have some doubts in regards to how many of my readers and visitors of this blog understand Romanian language, but just in case, here’s the Google Play download link:
Here are the topics that will help you achieve this:
Creating A Simple RSS Application in Android
Understanding AsyncTask – Once and Forever
How to verify an RSS Feed if New Articles have been published.
Working With Services – IntentService
Showing status bar notifications in Android
Writing and Reading from SharedPreferences
Building a Custom Fancy ListView in Android
After reading (and exercising) the above tutorials, you should be able to build your own Cool RSS Application
.
Please visit the Android Tutorials page for more Android tutorials.
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”.
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.
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 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.
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.
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:
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


![get_it_on_play_logo_large[1] Get it on Google Play - ITMoldova](http://androidresearch.files.wordpress.com/2012/04/get_it_on_play_logo_large1.png?w=595)




