Posts tagged Android

Gmail Logo

Android: Send email with pre-populated fields

1

Within the AppInfoActivity of my current project, I have a button to send an email to the developer (me!). This button creates an Intent and uses Intent.putExtra to pre-populate the Email, subject and body of the email.

Initially my Email “To” field wasn’t populating – if this is happening to you, it’s probably because it’s expecting a String array (to allow for multiple email addresses) and not a single String object, you’ll notice this is different in the onClick handler below:

public void onEmailButtonClick(View v) {
    final Intent emailIntent = new Intent(Intent.ACTION_SEND);
    emailIntent.setType("plain/text");
    emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] { getString(R.string.app_email_address) });
    emailIntent.putExtra(Intent.EXTRA_SUBJECT, getString(R.string.app_info_email_subject));
    emailIntent.putExtra(Intent.EXTRA_TEXT, getString(R.string.app_info_email_body));
    startActivity(emailIntent);
}

and for completeness, here’s the xml for the string resources referenced:

<?xml version="1.0" encoding="utf-8"?>
<resources>
	<string name="app_info_email_subject">Feedback on someOldApp</string>
	<string name="app_info_email_body">Hi someOldApp,</string>
	<string name="app_email_address">someoldapp@samcoles.co.uk</string>
</resources>
Android

Android: Get number of rows in SQLite Database Table

1

Here’s a little function from my Database Adapter class in the app I’m working on. It returns the number of rows in the “Places” table from my database.

It does this using a SQLiteStatement object, much simpler and cleaner than getting a Cursor using SQLiteDatabase.rawQuery().

A SQLiteStatement can be used for database queries that return “1×1 result sets”, that is one row with one column – a single value.

private static final String DB_TABLE_PLACES = "Places";
private SQLiteDatabase mDatabase;

private long fetchPlacesCount() {
    String sql = "SELECT COUNT(*) FROM " + DB_TABLE_PLACES;
    SQLiteStatement statement = mDatabase.compileStatement(sql);
    long count = statement.simpleQueryForLong();
    return count;
}
Passing Data Between Activities

Android: Passing data between Activities

5

With the Android framework, data can be passed between different Activities by adding it to the Intent object before starting the new Activity, and then retrieving it using a Bundle object. We will demonstrate this by creating a small demo with two Activities, the first activity, TextInputActivity will allow the user to type in some text and tap a button. Tapping the button will open ViewTextActivity, taking the inputted text with it in the Intent, this text will be retrieved and displayed in ViewTextActivity.

This demo will cover the method for primitive data types, we’ll cover passing your own data types/objects in another post.

First we will get the layouts out the way, both are very simple.
text_input_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content"
  android:orientation="vertical">
  <EditText
  	android:id="@+id/the_input"
  	android:layout_width="250dp"
  	android:layout_height="wrap_content"
  	android:layout_weight="1"/>
  <Button
  	android:id="@+id/the_button"
  	android:layout_width="wrap_content"
  	android:layout_height="wrap_content"
  	android:text="Go to next Activity"
  	android:onClick="goToNextActivity"/>
</LinearLayout>

text_view_layout.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
  xmlns:android="http://schemas.android.com/apk/res/android"
  android:layout_width="wrap_content"
  android:layout_height="wrap_content">
  <TextView
  	android:id="@+id/the_text"
  	android:layout_width="wrap_content"
  	android:layout_height="wrap_content"
  	android:textSize="10pt"/>
</LinearLayout>

Now we’ll create TextInputActivity, this is declared as the main activity in the AndroidManifest.xml. In here we’ll add the onClick handler, goToNextActivity() that’s referenced in the xml layout. Within this method, first we’ll get a reference to the EditText and extract the text from it to a String. Then we create a new Intent object to ViewTextActivity. We’ll call Intent.putExtra() to add the String to the Intent. the first parameter is the name we’ll use to retrieve it later – this is a constant that we’ll declare in ViewTextActivity so don’t worry about the error for now. We’ll just need to remember to add this constant and give it public access in TextViewActivity. Finally, call startActivity() passing it our Intent to start the new Activity.

TextInputActivity.java

package samcoles.bundleexample;

import android.app.Activity;
import android.content.Intent;
import android.os.Bundle;
import android.view.View;
import android.widget.EditText;

public class TextInputActivity extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.text_input_layout);
    }

    public void goToNextActivity(View v) {
        String theText = null;
        //first get the EditText View and extract the text...
        EditText theInput = (EditText)findViewById(R.id.the_input);
        if(theInput != null) {
            theText = theInput.getText().toString();
        }
        //create a new Intent
        Intent i = new Intent(this, ViewTextActivity.class);
        //add theText to the intent
        i.putExtra(ViewTextActivity.TEXT_DATA, theText);
        //start the activity
        startActivity(i);
    }
}

Next we’ll add our second Activity, ViewTextActivity. Remember to add this to your AndroidManifest.xml or your app will crash!

First we’ll define the public constant TEXT_DATA that we used in TextInputActivity.

public static final String TEXT_DATA = "textData";

Then in the overridden onCreate() method we’ll get a reference to the Bundle object in the Intent by calling getIntent().getExtras(). We’ll then call Bundle.getString(), passing the TEXT_DATA constant to retrieve our value. Finally we’ll get a reference to the TextView in our layout and call TextView.setText() passing our String.

ViewTextActivity.java

package samcoles.bundleexample;

import android.app.Activity;
import android.os.Bundle;
import android.widget.TextView;

public class ViewTextActivity extends Activity {
    public static final String TEXT_DATA = "textData";

    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.text_view_layout);    

        Bundle extras = getIntent().getExtras();
        if(extras != null) {
            String theText = extras.getString(TEXT_DATA);
            if(theText != null) {
                TextView t = (TextView)findViewById(R.id.the_text);
                if(t != null) {
                    t.setText(theText);
                }
            }
        }
    }
}

Here’s a screenshot of each activity in the demo in action:

Passing Data Between Activities

Passing Data Between Activities

android_logo

Android SharedPreferences

8

A quick and easy way to store data that needs to be persistent across different user sessions, and accessible by your whole application and not just one activity, is by using the SharedPreferences class. This can be used for example to store your app’s settings.

To demonstrate we’ll create a small demo with a CheckBox and an EditText box in the layout. The state of these will be saved when the app goes out of focus and restored when resumed.

First up, the very simple layout with the CheckBox and EditText.

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent">
    <CheckBox
    	android:id="@+id/prefsdemo_checkbox"
    	android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
    	android:textSize="6pt"/>
	<EditText
		android:id="@+id/prefsdemo_edittext"
		android:layout_width="250dp"
		android:layout_height="wrap_content"/>
</LinearLayout>

In your activity, you will need objects to reference the EditText and Checkbox. You will also need one for SharedPreferences. Lastly you will need a string constant for the name of the SharedPreferences (your app can have more than one). I’ve called mine “SharedPrefsDemoPreferences” – you can choose something more meaningful. This constant is public so you can access it from elsewhere in your app. Put these in at the top of your activity class.

public static final String PREFS_NAME = "SharedPrefsDemoPreferences";

private SharedPreferences mPrefs;
private EditText mEditText;
private CheckBox mCheckBox;

Override the onCreate() method and assign references to your SharedPreferences, EditText and Checkbox objects. Call getSharedPreferences() with the string constant you just defined. mEditText and mCheckBox are defined in our main.xml layout and we get references to these using findViewById().

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

    mPrefs = getSharedPreferences(PREFS_NAME, 0);

    mEditText = (EditText)findViewById(R.id.prefsdemo_edittext);
    mCheckBox = (CheckBox)findViewById(R.id.prefsdemo_checkbox);
}

Next we will override onResume(). This is called when the activity is resumed after going out of focus, as well as after onCreate() is finished. The code we’ll put here will set the values for our CheckBox and EditText using the values from our SharedPreferences object. Before we do this, add these two new string constants beneath PREFS_NAME. These are the names of the data we’ll be storing.

public static final String PREF_STRING = "PrefString";
public static final String PREF_BOOL = "PrefBool";

The first parameter for SharedPreferences.getString() and SharedPreferences.getBoolean() is the string name of the data we want to get. We pass the constants we just defined. The second represents default values to use if the values do not exist (which as yet, they do not). We take the values from these calls and use them to set the values of our EditText and CheckBox.

@Override
protected void onResume() {
    mEditText.setText(mPrefs.getString(PREF_STRING, "EditText"));
    mCheckBox.setChecked(mPrefs.getBoolean(PREF_BOOL, false));
    super.onResume();
}

Next up we’ll be overriding onPause(). It’s called when the activity goes out of focus or before the activity is about to be destroyed. Here we’ll want to update the SharedPrefences values.

@Override
protected void onPause() {
    Editor e = mPrefs.edit();
    e.putBoolean(PREF_BOOL, mCheckBox.isChecked());
    e.putString(PREF_STRING, mEditText.getText().toString());
    e.commit();

    Toast.makeText(this, "Settings Saved.", Toast.LENGTH_SHORT).show();
    super.onPause();
}

To explain. First we get the Editor object for our SharedPreferences, we use putBoolean() and putString() to put the values from the CheckBox and EditText into the object. Lastly we call commit() to save the new values.

We also give the user a toast notification to let them know it was saved.

Here’s the java class for this demo activity in full.

SharedPrefDemo.java

package samcoles.sharedprefsdemo;

import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.Editor;
import android.os.Bundle;
import android.widget.CheckBox;
import android.widget.EditText;
import android.widget.Toast;

public class SharedPrefsDemo extends Activity {

    public static final String PREFS_NAME = "SharedPrefsDemoPreferences";

    public static final String PREF_STRING = "PrefString";
    public static final String PREF_BOOL = "PrefBool";

    private SharedPreferences mPrefs;
    private EditText mEditText;
    private CheckBox mCheckBox;

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

        mPrefs = getSharedPreferences(PREFS_NAME, 0);

        mEditText = (EditText)findViewById(R.id.prefsdemo_edittext);
        mCheckBox = (CheckBox)findViewById(R.id.prefsdemo_checkbox);
    }

    @Override
    protected void onResume() {
        mEditText.setText(mPrefs.getString(PREF_STRING, "EditText"));
        mCheckBox.setChecked(mPrefs.getBoolean(PREF_BOOL, false));
        super.onResume();
    }

    @Override
    protected void onPause() {
        Editor e = mPrefs.edit();
        e.putBoolean(PREF_BOOL, mCheckBox.isChecked());
        e.putString(PREF_STRING, mEditText.getText().toString());
        e.commit();

        Toast.makeText(this, "Settings Saved.", Toast.LENGTH_SHORT).show();
        super.onPause();
    }

}

Try modifying the EditText and CheckBox, exiting and then coming back to the application later – the values will remain the same.

Custom Toast Notification

Android Custom Toast Notification

2

You may recognise Toast notifications from Android applications you have used, they look like this:

Android Toast Notification

Android Toast Notification

These are very easy to implement, like so:

Toast.makeText(this, "This is toast.", Toast.LENGTH_LONG).show();

This will display the toast notification immediately. You will also need to import android.widget.Toast in your activity, pushing ctrl+shift+o in Eclipse will take care of this for you.

But what about notifications with the same behaviour, but a customised layout? Perhaps with images? To demonstrate I’ve set up an activity with a button and an onClick handler. Here are the layout xml and Activity class.

main.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical"
    android:layout_width="fill_parent"
    android:layout_height="fill_parent"
    android:paddingTop="10px"
    >
	<Button
		android:id="@+id/button"
		android:layout_width="wrap_content"
		android:layout_height="wrap_content"
		android:text="Push For Toast"
		android:onClick="buttonClicked">
	</Button>
</LinearLayout>

CustomToastDemo.java

package samcoles.customtoastdemo;
package samcoles.customtoastdemo;

import android.app.Activity;
import android.os.Bundle;
import android.view.View;

public class CustomToastDemo extends Activity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
    }

    public void buttonClicked(View view) {

    }
}

First things first with your custom toast, you will need to create an xml layout for it. Add this to your /res/layout/ folder. You are practically unlimited in what you can do with this. I’ve put the application’s icon to the left with some text to the right. I’ve also made the background partly transparent so you can see what’s behind.

custom_toast.xml

<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
     android:id="@+id/toast_layout_root"
     android:orientation="horizontal"
     android:layout_width="fill_parent"
     android:layout_height="fill_parent"
     android:paddingLeft="10dp"
     android:paddingRight="10dp"
     android:layout_marginLeft="10dp"
     android:layout_marginRight="10dp">
     <LinearLayout
    	android:orientation="horizontal"
    	android:layout_width="fill_parent"
    	android:layout_height="fill_parent"
    	android:background="#DAAA"
    	android:paddingTop="5dp"
    	android:paddingBottom="5dp">
		    <ImageView
		    	android:id="@+id/toastImage"
		    	android:layout_width="wrap_content"
		        android:layout_height="fill_parent"
		        android:src="@drawable/icon"
		        android:layout_marginRight="10dp"
		        />
		    <TextView
		    	 android:id="@+id/toastText"
		         android:layout_width="wrap_content"
		         android:layout_height="fill_parent"
		         android:textSize="7pt"
		         android:textStyle="bold"
		         android:textColor="#000"
		         android:layout_gravity="center_vertical"
		         android:gravity="center"
		         android:layout_marginRight="10dp"
		         />
    </LinearLayout>
</LinearLayout>

To create and show the custom toast, I’ve modified the onClick handler for the button in the CustomToastDemo activity.

    public void buttonClicked(View view) {
        //get the LayoutInflater and inflate the custom_toast layout
        LayoutInflater inflater = getLayoutInflater();
        View layout = inflater.inflate(R.layout.custom_toast, (ViewGroup) findViewById(R.id.toast_layout_root));

        //get the TextView from the custom_toast layout
        TextView text = (TextView) layout.findViewById(R.id.toastText);
        text.setText("This is my custom toast");

        //create the toast object, set display duration,
        //set the view as layout that's inflated above and then call show()
        Toast t = new Toast(getApplicationContext());
        t.setDuration(Toast.LENGTH_LONG);
        t.setView(layout);
        t.show();
    }

To explain the above, first we instantiate the layout using the application context’s LayoutInflater. We then set the Text to “This is my custom toast”. You could also set the image to something more specific here if wanted. Next up we create the Toast object using the custom layout and finally call show() to display it.

and here’s how that looks:

Custom Toast Notification

Custom Toast Notification

Android ListActivity with a header or footer

8

This post will show you how to go about implementing a ListActivity with a header or footer that does not follow the same layout as the list rows. A well known and obvious example of this is the main screen on the Android Market.

First, create a class that extends ListActivity:

ListWithHeader.java

package samcoles.listwithheader;

import android.app.ListActivity;
import android.os.Bundle;

public class ListWithHeader extends ListActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_main);
    }
}

Remember to ensure you have added this activity to your AndroidManifest.xml.

Next up you’ll need to create the list_main layout that’s set in the above ListActivity within /res/layout. Remember the <ListView> must have id=”@+id/android:list” and you should also have a view with id=”@+id/android:empty” to display when there’s no items in the list. Your ListActivity will go looking for these and your app will crash when loading this activity if you don’t have them. If you’re not aware of this then the debugger can be a bit unhelpful. The TextView uses a string resource, empty_list that you’ll need to remember to add too if you’re using this.

here’s the list_main layout:

list_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="wrap_content"
  android:orientation="vertical">
  <ListView
  	android:id="@+id/android:list"
  	android:layout_width="fill_parent"
  	android:layout_height="wrap_content"
  	android:scrollbars="none"/>
  <TextView
  	android:id="@+id/android:empty"
  	android:layout_width="wrap_content"
  	android:layout_height="wrap_content"
  	android:text="@string/empty_list" />
</LinearLayout>

You’ll also need a layout for the header, note that this below references a couple of string resources and an image resource:

list_header.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="wrap_content"
  android:id="@+id/header_layout_root"
  android:background="#ffffff"
  android:orientation="vertical">
	<TextView
    	android:layout_width="fill_parent"
    	android:layout_height="wrap_content"
	    android:text="@string/app_name"
	    android:background="#000000"
	    android:textColor="#ffffff"
	    android:textSize="28dp"
	    android:gravity="center_horizontal"
	    android:paddingTop="10dp"
	    android:paddingBottom="10dp">
	</TextView>
    <RelativeLayout
	    android:layout_width="fill_parent"
	    android:layout_height="wrap_content">
	  	<ImageView
			android:id="@+id/sample_image"
			android:layout_width="fill_parent"
			android:layout_height="wrap_content"
			android:adjustViewBounds="true"
			android:src="@drawable/sample_image"
			android:scaleType="fitXY">
		</ImageView>
		<TextView
			android:id="@+id/sample_title"
			android:text="@string/sample_text"
			android:layout_width="wrap_content"
			android:layout_height="wrap_content"
			android:textColor="#ffffffff"
			android:textSize="12dp"
			android:background="#AA000000"
			android:padding="5dp"
			android:layout_alignParentLeft="true"
			android:layout_alignBottom="@id/sample_image">
		</TextView>
	</RelativeLayout>
</LinearLayout>

Next go back to your ListActivity class and it’s time to put in the code to add the header to your list, place this just below the call to setContentView():

ListView lv = getListView();
LayoutInflater inflater = getLayoutInflater();
View header = inflater.inflate(R.layout.list_header, (ViewGroup) findViewById(R.id.header_layout_root));
lv.addHeaderView(header, null, false);

To explain the above, first we call getListView() to get the activity’s ListView and assign this to an object. We then call getLayoutInflater() and do the same – this gets the LayoutInflater that’s attached to the current application context. The LayoutInflater is then used to instantiate the layout xml file so that we have a View object that, in line 4, we can attach to the ListView! There is also a method ListView.addFooterView() – you use this in exactly the same way as ListView.addHeaderView().

The full ListActivity class is shown below, it also puts some items in the list.

ListWithHeader.java

package samcoles.listwithheader;

import android.app.ListActivity;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.ListView;

public class ListWithHeader extends ListActivity {
    /** Called when the activity is first created. */
    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.list_main);

        //add header to list
        ListView lv = getListView();
        LayoutInflater inflater = getLayoutInflater();
        View header = inflater.inflate(R.layout.list_header, (ViewGroup) findViewById(R.id.header_layout_root));
        lv.addHeaderView(header, null, false);

        //add some list items
        String listItems[] = {"List Item One", "List Item Two", "List Item Three", "List Item Four", "List Item Five"};
        lv.setAdapter(new ArrayAdapter(this, android.R.layout.simple_list_item_1, listItems));
    }
}

And here’s a look at that in the emulator:

ListWithHeader

ListWithHeader

 

Noisy Neighbour Icon

Android App: ‘Noisy Neighbour’

0

Since I bought my Android phone last year I have been playing about with the Android SDK. I have worked through some App tutorials and also made a number of little demos using AndEngine.

A couple of weekends’ ago I decided to produce and publish a complete application for the market and ended up building a logging tool to record late night disturbances to your sleep.

You can download ‘Noisy Neighbour’ from the market here.

 

Noisy Neighbour Main Screen

Activity for logging disturbance

Noisy Neighbour Custom Toast

Toast notification after logging a disturbance

Frozen Yoghurt

Root and Upgrade your HTC Desire to Stock Froyo

1

Doesn’t look like HTC will be upgrading your relatively new HTC Desire to Android 2.2 Froyo any time soon. But fortunately there are a number of stable ROMs out there that are quite safe to install. I found a number of the tutorials and posts of advice that are out there were often incomplete, so this is my guide to how I went about getting Froyo on my phone.

  1. Firstly, you will need an unlocked phone before you start. You may need to contact your operator to get the code and they are entitled to charge you an admin fee for this, I think it’s somewhere around £10 for the privilege. Fortunately I had an unlocked stock HTC phone to start with.
  2. Push the menu button on your phone, go to Settings > Applications > Development and make sure the box is checked to allow “USB debugging.”
  3. Here, I formatted the SD card to get rid of all the junk. This can be found in Settings > SD Card & Phone Storage Settings, first you’ll need to tap ‘Unmount SD card’ and then ‘Format SD card.’
  4. Plug your phone into your computer, change it to disk drive mode. You will need to copy across two zip files (complete – do not extract them) into the root of your SD card. The first is the radio image and the second is your choice of custom ROM. You can grab the radio image from here and the custom ROM is your choice. I opted for and reccomend, OpenDesire which, so far seems way more stable than the official HTC 2.1 with Sense ever was. I used the latest version, 2.1 and you can download it from the author here.
  5. Download and run unrevoked³ – this will give you root access on your phone, allow you to create a backup as it stands now and to flash your custom ROM. I’ve heard it just works on Mac, on Windows you may need to install an additional driver from the website and on Linux I had to run it in root mode for it to detect the phone – if you don’t know how to do this because you don’t normally use Linux and you’re running a Live CD or something, then you need to Google “sudo” and read what it has to say. This program takes a couple of minutes to flash and will keep you updated on what it’s up to on the screen. After this step your phone should now have root access – if this is all you want so you can run certain apps then leave it here. Once it’s done you’ll see a menu – you can get back to this screen at any time by holding Volume Down as you switch the phone on.
  6. Make a backup! Scroll down on the menu to “Recovery” using the volume buttons and tap the power button. Use the optical track pad from here, go to “nandroid” on the menu and create your backup. After you’ve done this – if you fudge things up, you can simply roll right back to where you started.
  7. “wipe data/factory reset” – I forgot to do this initially, being my point about incomplete guides. Not doing so caused my phone to get stuck in a loop on the boot screen after I’d flashed the new images, a disappointing and mildly unnerving experience.
  8. “install zip from sdcard” – first up you want to flash the radio image, probably called 32.41.00.32U_5.08.00.04.zip if you didn’t change the name.
  9. “install zip from sdcard” – again, but this time you want to flash the OpenDesire ROM.
  10. “reboot system now” – good luck… remember you can roll back to the beginning using your nandroid backup if something went wrong.

Enjoy! : – )

Go to Top