Archive
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
Receiving a SMS in Android Emulator
1. Start the Android Emulator
2. Open up the windows console by going to Start -> Run (or Windows + R shortcut) and type in “cmd” and press enter.
3. Type in “telnet” and press enter. This should open the Telnet Console.
(If you encounter this error: ‘telnet’ is not recognized as an internal or external command, operable program or batch file, open this link and scroll down to see how to fix it: http://androidresearch.wordpress.com/2012/01/18/how-to-simulate-an-incoming-call-in-android/)
4. Telnet Console being displayed, type in “o localhost 5554″. This will establish a connection with the emulator on port 5554 and open the Android Console. 5554 is the port number and you can see it on the title bar of the emulator window.
5. To send the sms, type in: “sms send 0789456 Hello World″.
As a result, a notification will notify you that a new sms has arrived.
6. Use “exit” to exit the Android Console, and “quit” to quit the Telnet client.
How to simulate an incoming call in Android
1. Start the Android Emulator
2. Open up the windows console by going to Start -> Run (or Windows + R shortcut) and type in “cmd”. Press Enter. This should open the dos console.
3. Type in “telnet” and press enter. This should open the Telnet Console.
(At this stage you may experience some problems, the console may display the error: ‘telnet’ is not recognized as an internal or external command, operable program or batch file. If this is the case, scroll down to see how to fix it, then return and continue the process)
4. Telnet Console being displayed, type in “o localhost 5554″. This will establish a connection with the emulator on port 5554 and open the Android Console. 5554 is the port number and you can see it on the title bar of the emulator window.
5. To simulate the call, type in “gsm call 099062274″
6. To cancel the call, type “gsm cancel 099062274″
7. Use “exit” to exit the Android Console, and “quit” to quit the Telnet client.
That’s it!
*How to fix the: ‘telnet’ is not recognized as an internal or external command, operable program or batch file error.
When trying to invoke the telnet program you may experience the above error. The cause of this could be that the Telnet Client is turned off on your computer.
To turn it on, follow these steps:
1. Go to Control Panel
2. Click on Programs
3. Under Programs and Features section, click on Turn Windows features on or off. This should bring you the Windows Features pop-up.
4. Find the Telnet Client, select it, click OK.
Parsing XML with XmlPullParser
XmlPullParser is an interface that provides parsing functionality. The below code is an example of XmlPullParser usage.
We will parse the Youtube feed that contains the most highly rated YouTube video, looking for “<title>” tag and extracting the text inside.
URL Feed: https://gdata.youtube.com/feeds/api/standardfeeds/top_rated
//We will put the data into a StringBuilder
StringBuilder builder=new StringBuilder();
URL url = new URL("https://gdata.youtube.com/feeds/api/standardfeeds/top_rated");
XmlPullParserFactory factory=XmlPullParserFactory.newInstance();
factory.setNamespaceAware(true);
XmlPullParser xpp=factory.newPullParser();
xpp.setInput(getInputStream(url), "UTF_8");
int eventType=xpp.getEventType();
while(eventType!=XmlPullParser.END_DOCUMENT){
// Looking for a start tag
if(eventType==XmlPullParser.START_TAG){
//We look for "title" tag in XML response
if(xpp.getName().equalsIgnoreCase("title")){
//Once we found the "title" tag, add the text it contains to our builder
builder.append(xpp.nextText()+"\n");
}
}
eventType=xpp.next();
}
And here’s the implementation of getInputStream() method:
public InputStream getInputStream(URL url) {
try {
return url.openConnection().getInputStream();
} catch (IOException e) {
return null;
}
}
Showing status bar notifications in Android
A status bar notification adds an icon to the system’s status bar with an optional ticker-text message and a notification message in the notifications window. When the user selects the notification, usually an Activity is opened. The notification can be configured to alert the user with a sound, a vibration, and flashing lights on the device.
In the example below a notification is fired imediatly and when user clicks on it, the PostNotification activity opens.
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
// Get a reference to the NotificationManager
NotificationManager notificationManager = (NotificationManager) getSystemService(Context.NOTIFICATION_SERVICE);
// Instantiate the Notification with an icon, ticker text, and when to be displayed
int icon = R.drawable.ic_launcher;
CharSequence tickerText = "New notification";
long when = System.currentTimeMillis(); //now
Notification notification = new Notification(icon, tickerText, when);
// Define the notification's message and PendingIntent
Context context = getApplicationContext();
CharSequence title = "Notification title";
CharSequence text = "Notification description";
// The activity PostNotification.class will be fired when notification will be opened.
Intent notificationIntent = new Intent(this, PostNotification.class);
PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, notificationIntent, 0);
// Makes the notification disappear after clicked in the status bar
notification.flags|=Notification.FLAG_AUTO_CANCEL;
// When the notification will be fired, notify the user with default notification phone sound.
notification.defaults|=Notification.DEFAULT_SOUND;
notification.setLatestEventInfo(context, title, text, pendingIntent);
// Pass the Notification object to NotificationManager
notificationManager.notify(1, notification);
}
If you’d like to try the example above, create a new Activity called: PostNotification, create a new layout file, say postnotification.xml and add in the PostNotification activity:
setContentView(R.layout.postnotification);
Ultimately, do not forget to register the PostNotification activity in the AndroidManifest file:
<activity android:name=".PostNotification"></activity>
Keytool throws: The program can’t start because jli.dll is missing from your computer
In order to develop an application that uses the Google Maps, you should obtain first a Maps API key registered via the MD5 fingerprint of the debug certificate. To find the MD5 fingerprint of your debug certificate you should use the keytool to generate it.
When using the keytool you may encounter following error:
The Keytool as well as jli.dll files are part of Java SDK /bin directory, and when you generate the MD5 code, both Keytool and jli.dll files should be in the same directory, if they are not in the same directory, then the above error is thrown.
The simplest way to generate the MD5 fingerprint is to:
1. Copy both keytool and jli.dll into debug keystore location:
- Windows Vista:
C:\Users\<user>\.android\debug.keystore - Windows XP:
C:\Documents and Settings\<user>\.android\debug.keystore - OS X and Linux:
~/.android/debug.keystore
2. Navigate with the command prompt to debug keystore location and run the following command to:
a) generate a Debug certificate:
keytool -list -alias androiddebugkey -keystore debug.keystore -storepass android -keypass android
or
b) generate a Release certificate:
keytool -list -keystore debug.keystore
3. Copy the generated MD5 fingerprint and navigate to http://code.google.com/android/maps-api-signup.html to get the Map key.
Creating a simple Gesture Application in Android
Android supports the Gesture API since version 1.6. The API can be located in the package android.gesture, and lets you store, load, draw and recognize gestures. This tutorial will show you a proof-of-concept application how you can make use of Gesture API.
We will define 2 gestures: “S” and “O”. When a corresponding gesture will be recognized, a toast message will be shown.
The result will look like in the screenshot below:
Create a new project:
Project: AndroidGesture
Activity: AndroidGestureActivity
1. Creating the gestures
Starting with version 1.6 and higher the Android Emulator includes a new application pre-installed, called Gestures Builder.
Start the Android Emulator and use the Gesture Builder application to create the “S” and “O” gestures:
A gesture is always associated with a name, but the name does not necessarily have to be unique. In fact, it’s recommended to have several gestures with the same name to increase the precision of recognition.
2. Importing gesture to your project
Every time we create or edit gestures with Gesture Builder, a file is created on the emulator SD card: /sdcard/gestures. We should import this file into our /res/raw project directory.
In order to do this, open the FileExplorer tab in the DDMS perspective. (If you don’t have the FileExplorer tab available, add it from: Window -> Show View -> File Explorer). Navigate to /sdcard directory and copy the gesture file to your computer, for example on your desktop.
To copy the gesture file from the emulator, select it and click the “Pull a file from the device” button, marked with red in the screenshot below:
Don’t forget to create a new folder called raw in the res directory of your project and copy there the gesture file.
3. Loading the gesture library and recognizing the gesture
To start recognizing gesture in our application we have to add the GestureOverlayView to our XML layout file. There are 2 ways you can use the GestureOverlayView, one of them is to use it as a normal view embedded inside a LinearLayout for example, and another is to use it as an overlay on top of other views. In this tutorial we will use the second option – an overlay on top of other views.
Edit the main.xml layout to look like this:
<?xml version="1.0" encoding="utf-8"?> <android.gesture.GestureOverlayView xmlns:android="http://schemas.android.com/apk/res/android" android:id="@+id/gestures" android:layout_width="fill_parent" android:layout_height="fill_parent" android:eventsInterceptionEnabled="true" android:gestureStrokeType="multiple" android:orientation="vertical" > <TextView android:id="@+id/textView1" android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="TextView" /> </android.gesture.GestureOverlayView>
Make the AndroidGestureActivity to implement the OnGesturePerformedListener interface and add the the mLibrary member variable of type GestureLibrary:
public class AndroidGestureActivity extends Activity implements OnGesturePerformedListener {
GestureLibrary mLibrary;
In the onCreate() method we load the library and add the GestureOverlayView to the listener:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
mLibrary = GestureLibraries.fromRawResource(this, R.raw.gestures);
if (!mLibrary.load()) {
finish();
}
GestureOverlayView gestures = (GestureOverlayView) findViewById(R.id.gestures);
gestures.addOnGesturePerformedListener(this);
}
And below is the implementation of onGesturePerformed(). When the listener is triggered, a list of predictions and a score is returned, each with the name you entered earlier in the Gesture Builder. The list is sorted by descending scores; the higher the score, the more likely the associated gesture is the one the user intended to draw:
public void onGesturePerformed(GestureOverlayView overlay, Gesture gesture) {
ArrayList<Prediction> predictions = mLibrary.recognize(gesture);
if (predictions.size() > 0 && predictions.get(0).score > 1.0) {
String result = predictions.get(0).name;
if ("open".equalsIgnoreCase(result)) {
Toast.makeText(this, "Opening the document", Toast.LENGTH_LONG).show();
} else if ("save".equalsIgnoreCase(result)) {
Toast.makeText(this, "Saving the document", Toast.LENGTH_LONG).show();
}
}
}
By this time the application should compile and run successfully.
Reference: http://developer.android.com/resources/articles/gestures.html
Eclipse always stops at 27% – “Launching delegate”.
This week when I reinstalled both Eclipse and Android SDK on a new computer, I encountered a problem with re-runing the android application. The emulator was starting just fine for the first time, but every time after doing some changes in the project and runing it again, the progress bar was stopping on 27% and showing: “Launching: Launching delegate…” message. It remains in this state for a long time and Eclipse becomes unresponsive.
My first thought was that the computer on which Eclipse was installed is too low in performance to run the Android emulator.
Actually, it appears that this is an issue: #21073.
However, there’s an easy workaround to avoid it if the AVD emulator is launched from the AVD Manager within Eclipse. The issue happens when launching the first emulator from the Run button in Eclipse.
To avoid:
- Start Eclipse
- Window -> AVD Manager
- Start an emulator
- Run the project
How to access the Media Galery in Android
In this tutorial I’ll show how we can access the media galery, pick a picture, and display it in our activity.
The final result will look like this:
1. Create a new project in Eclipse
Project name: MediaGalery
Activity: MediaGaleryActivity.
2. Add a Button and an ImageView control to the main.xml layout file:
<?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" > <Button android:id="@+id/openGalery" android:layout_width="fill_parent" android:layout_height="wrap_content" android:text="Open Media Galery" /> <ImageView android:id="@+id/image" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center" android:src="@drawable/ic_launcher" /> </LinearLayout>
3. Open the MediaGaleryActivity and make it implement the OnClickListener
public class MediaGaleryActivity extends Activity implements OnClickListener {
4. Just after the class declaration, add the following instance variables:
private static final int SELECT_IMAGE = 1; Button openGalery;
5. Add following lines of code in the onCreate() method:
openGalery = (Button) findViewById(R.id.openGalery); openGalery.setOnClickListener(this);
6. Below the onCreate() method, add the onClick() method:
//When the Open Media Gallery button is cliked, open the media galery
@Override
public void onClick(View v) {
switch (v.getId()) {
case R.id.openGalery:
Intent gallery = new Intent(
Intent.ACTION_PICK,
android.provider.MediaStore.Images.Media.INTERNAL_CONTENT_URI);
startActivityForResult(gallery, SELECT_IMAGE);
break;
default:
break;
}
}
7. Below the onClick() method, add following 2 methods.
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
super.onActivityResult(requestCode, resultCode, data);
if(resultCode==RESULT_OK && requestCode==SELECT_IMAGE){
Uri selectedImage=data.getData();
String path=getPath(selectedImage);
Bitmap bitmapImage=BitmapFactory.decodeFile(path);
ImageView image=(ImageView)findViewById(R.id.image);
image.setImageBitmap(bitmapImage);
}
}
public String getPath(Uri uri){
String[] filePathColumn={MediaStore.Images.Media.DATA};
Cursor cursor=getContentResolver().query(uri, filePathColumn, null, null, null);
cursor.moveToFirst();
int columnIndex=cursor.getColumnIndex(filePathColumn[0]);
return cursor.getString(columnIndex);
}
Building a Custom Fancy ListView in Android
In this tutorial we will walk through the process of building a custom ListView with alternate background colors and an image icon set to every row.
The final result will look like in the screenshot below:
1. We will begin by creating a new project in Eclipse.
Project name = FancyList
Activity name = FancyListActivity
2. Put the icon you want to display in the list, in one of the drawable folders, for example I put the arrow icon in the drawable-mdpi folder. Make sure the name of the icon is called arrow_icon.png.
3. Open the main.xml layout file and add a ListView view with the list id:
<ListView
android:id="@+id/list"
android:layout_width="fill_parent"
android:layout_height="wrap_content" >
</ListView>
4. Create a new layout file named row.xml. This layout file will reprezent each row in the list and should contain a TextView and an ImageView.
I used a table layout with 2 columns to arrange the TextView and ImageView both in the same line.
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:layout_width="fill_parent" android:layout_height="wrap_content" > <TableLayout android:id="@+id/tableLayout1" android:layout_width="match_parent" android:layout_height="wrap_content" > <TableRow > <TextView android:id="@+id/headline" android:layout_width="0px" android:layout_height="wrap_content" android:layout_weight="0.8" android:padding="10dp" android:textSize="16dp" android:textColor="#FFF"/> <ImageView android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_vertical|right" android:layout_marginRight="6dp" android:src="@drawable/arrow_icon" /> </TableRow> </TableLayout> </LinearLayout>
5. Open the main activity, in our case FancyListActivity.java, and add a String array instance variable that will contain the text to be displayed in the list:
public class FancyListActivity extends Activity {
String[] items = { "Test text 1", "Test text 2", "Test text 3", "Test text 4", "Test text 5", "Test text 6" };
6. Modify the onCreate() method to look like this:
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
ListView list = (ListView) findViewById(R.id.list);
SpecialAdapter adapter = new SpecialAdapter(this, items);
list.setAdapter(adapter);
}
At this stage you may notice that Eclipse shows you an error saying that the class SpecialAdapter is not defined.
It’s OK for now, because we will define it a bit later.
7. Just after the onCreate() method, add the following static class.
static class ViewHolder {
TextView text;
}
This class will hold a reference to our TextView control defined earlier in the row.xml layout file.
8. In order to customize the list to look like we want, with alternate colors, we should define our own list adapter. Basically, this is achieved by extending the BaseAdapter class and providing our own implementation of methods.
private class SpecialAdapter extends BaseAdapter {
//Defining the background color of rows. The row will alternate between green light and green dark.
private int[] colors = new int[] { 0xAAf6ffc8, 0xAA538d00 };
private LayoutInflater mInflater;
//The variable that will hold our text data to be tied to list.
private String[] data;
public SpecialAdapter(Context context, String[] items) {
mInflater = LayoutInflater.from(context);
this.data = items;
}
@Override
public int getCount() {
return data.length;
}
@Override
public Object getItem(int position) {
return position;
}
@Override
public long getItemId(int position) {
return position;
}
//A view to hold each row in the list
@Override
public View getView(int position, View convertView, ViewGroup parent) {
// A ViewHolder keeps references to children views to avoid unneccessary calls
// to findViewById() on each row.
ViewHolder holder;
if (convertView == null) {
convertView = mInflater.inflate(R.layout.row, null);
holder = new ViewHolder();
holder.text = (TextView) convertView.findViewById(R.id.headline);
convertView.setTag(holder);
} else {
holder = (ViewHolder) convertView.getTag();
}
// Bind the data efficiently with the holder.
holder.text.setText(data[position]);
//Set the background color depending of odd/even colorPos result
int colorPos = position % colors.length;
convertView.setBackgroundColor(colors[colorPos]);
return convertView;
}
}
This is it! By this time you should successfully compile and run the application. If there’re any issues feel free to write them in comments.














