Taste of Android :: Part-6


Bhaskar S 05/24/2013


Android Application Development - V

We will now explore the concept of passing and receiving data between Activities using the Android framework Bundle class. A Bundle holds information as name-value pairs and can be passed between Activities.

Let us create a new Android application named DroidActivityData to illustrate the concept of passing and receiving data using a Bundle. The application will contain two Activities - Email Activity and Zip Activity. The Email Activity shows an EditView and a Submit button. One would type an email id in the EditView and click on the Submit button. The email id is passed in a Bundle to the next Zip Activity. The Zip Activity shows an EditView, a Done button and displays the email id. One would type a zipcode in the EditView and click on the Done button. The zipcode is returned in a Bundle to the main Email Activity.

Without further ado, lets get started. We will not go step-by-step to show the various screens since we already did that in Part-2 for the DroidTipCalculator application.

The contents of the dimens.xml file to look like the one shown in the listing 6.1 below:

Listing-6.1
<?xml version="1.0" encoding="utf-8"?>
<resources>

<dimen name="margin_size">20dp</dimen>
<dimen name="result_size">16sp</dimen>

</resources>

The contents of the strings.xml file to look like the one shown in the listing 6.2 below:

Listing-6.2
<?xml version="1.0" encoding="utf-8"?>
<resources>

<!-- id references -->

<string name="button1">button1</string>
<string name="button2">button2</string>
<string name="edittext1">edittext1</string>
<string name="edittext2">edittext2</string>
<string name="textview1">textview1</string>
<string name="textview2">textview2</string>

<!-- text references -->

<string name="app_name">DroidActivityData</string>
<string name="action_settings">Settings</string>
<string name="action_name">com.polarsparc.android.ACTIVITY_TWO</string>
<string name="email_key">EMAIL_KEY</string>
<string name="email">Enter Your Email</string>
<string name="zip_key">ZIP_KEY</string>
<string name="zip">Enter Your Zip</string>
<string name="submit">Submit</string>
<string name="done">Done</string>

</resources>

We will have two Activity files - the main is named activity_one.xml and the other is named activity_two.xml.

The contents of the activity_one.xml layout file will look like the one shown in the listing 6.3 below:

Listing-6.3
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<EditText
android:id="@+id/edittext1"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/email"
android:inputType="textEmailAddress" />

<Button
android:id="@+id/button1"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/submit" />

<TextView
android:id="@+id/textview1"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/margin_size"
android:paddingBottom="@dimen/margin_size"
android:paddingLeft="@dimen/margin_size"
android:paddingRight="@dimen/margin_size"
android:text=""
android:textColor="#cc3300"
android:textSize="@dimen/result_size"
android:textStyle="bold"
android:typeface="sans" />
</LinearLayout>

From the listing 6.3 above, the thing of interest would be the attribute android:inputType. It is set with the value of textEmailAddress, which indicates that the EditView will take an email address as the input.

Previewing the activity_one.xml layout file in the Graphical Mode in Eclipse will look like the one shown in the figure 6.1 below:

Activity One Preview Image
Figure-6.1

The contents of the activity_two.xml layout file will look like the one shown in the listing 6.4 below:

Listing-6.4
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:gravity="center"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical">

<EditText
android:id="@+id/edittext2"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:hint="@string/zip"
android:inputType="number" />

<Button
android:id="@+id/button2"
android:layout_height="wrap_content"
android:layout_width="wrap_content"
android:text="@string/done" />

<TextView
android:id="@+id/textview2"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:paddingTop="@dimen/margin_size"
android:paddingBottom="@dimen/margin_size"
android:paddingLeft="@dimen/margin_size"
android:paddingRight="@dimen/margin_size"
android:text=""
android:textColor="#cc3300"
android:textSize="@dimen/result_size"
android:textStyle="bold"
android:typeface="sans" />
</LinearLayout>

From the listing 6.4 above, once again the thing of interest would be the attribute android:inputType. It is set with the value of number, which indicates that the EditView will take onlu numbers as the input.

Previewing the activity_two.xml layout file in the Graphical Mode in Eclipse will look like the one shown in the figure 6.2 below:

Activity Two Preview Image
Figure-6.2

Next, modify the contents of the AndroidManifest.xml file to look like the one shown in the listing 6.5 below:

Listing-6.5
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.polarsparc.android.droidactivitydata"
android:versionCode="1"
android:versionName="1.0" >

<uses-sdk
android:minSdkVersion="14"
android:targetSdkVersion="14" />

<application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.polarsparc.android.droidactivitydata.ActivityOne"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity
android:name="com.polarsparc.android.droidactivitydata.ActivityTwo"
android:label="ActivityTwo" >
<intent-filter>
<action android:name="com.polarsparc.android.ACTIVITY_TWO" />

<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>

</manifest>

Finally, we will have two java source files corresponding to the two Activity files - the main is named ActivityOne.java and the other is named ActivityTwo.java.

The contents of the java source file ActivityOne.java will look like the one shown in the listing 6.6 below:

Listing-6.6
package com.polarsparc.android.droidactivitydata;

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

public class ActivityOne extends Activity {
final int ZIP = 1;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_one);

// Email EditText
final EditText emailFld = (EditText) findViewById(R.id.edittext1);

/* Set the OnKeyListener on the Email EditText field so that the
* TextView that displays the zip result display is blanked out
*/
emailFld.setOnKeyListener(new View.OnKeyListener() {
@Override
public boolean onKey(View v, int keyCode, KeyEvent event) {
final TextView zipTxt = (TextView) findViewById(R.id.textview1);
zipTxt.setText("");
return false;
}
});

// Submit button
Button submitBtn = (Button) findViewById(R.id.button1);

/*
* When we click the Submit button, we will check if there is some
* value in the Email EditText and then launch the other Activity
*/
submitBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
String emailStr = emailFld.getText().toString();
if (emailStr != null && emailStr.isEmpty() == false) {
String action = getResources().getString(R.string.action_name);
String email_key = getResources().getString(R.string.email_key);

Intent in = new Intent(action);

// Put the email in the bundle
Bundle extras = new Bundle();
extras.putString(email_key, emailStr);

in.putExtras(extras);

startActivityForResult(in, ZIP);
}
}
});
}

/*
* Callback method when another activity returns a result
*/
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) {
if (requestCode == ZIP && resultCode == Activity.RESULT_OK) {
String zip_key = getResources().getString(R.string.zip_key);
String zip = "";

Bundle extras = data.getExtras();
if (extras != null) {
zip = extras.getString(zip_key);
}

// Clear the contents of the Email EditText
final EditText emailFld = (EditText) findViewById(R.id.edittext1);
emailFld.setText("");

// Display the zip returned from the other activity
final TextView zipTxt = (TextView) findViewById(R.id.textview1);
zipTxt.setText(String.format("Returned Zip :: %s", zip));
}
}
}

From the code Listing 6.6 above, we see that when one clicks on the Submit button, we perform the following steps:

The interesting part is the method onActivityResult(). This callback method will be invoked when an Activity started by the method startActivityForResult() completes and returns some result. How do we correlate a result from a particular startActivityForResult() call ? This is where the request code comes into play. When the startActivityForResult() method is invoked, we will pass a request code as the second argument. When a result is returned through the onActivityResult() callback, we will be able to correlate it with the returned request code in the first parameter.

In the onActivityResult() callback method, we extract the zipcode from the returned Intent data (the third argument) and update the TextView to display the zip.

The contents of the java source file ActivityTwo.java will look like the one shown in the listing 6.7 below:

Listing-6.7
package com.polarsparc.android.droidactivitydata;

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

public class ActivityTwo extends Activity {
final Activity act = this;

@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_two);

String email_key = getResources().getString(R.string.email_key);
String emailStr = "";

// Extract the email from the bundle in the intent
Bundle extras = getIntent().getExtras();
if (extras != null) {
emailStr = extras.getString(email_key);
}

// Display the email in the Email TextView
final TextView emailTxt = (TextView) findViewById(R.id.textview2);
emailTxt.setText(String.format("Passed Email :: %s", emailStr));

// Done button
final Button doneBtn = (Button) findViewById(R.id.button2);

/*
* When we click the Done button, we will check if there is zip code
* in the Zip EditText. If there is text, we will send that out as
* the result and exit this activity
*/
doneBtn.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
final EditText zipFld = (EditText) findViewById(R.id.edittext2);
String zipStr = zipFld.getText().toString();
if (zipStr != null && zipStr.length() == 5) {
String zip_key = getResources().getString(R.string.zip_key);

Intent in = getIntent();

// Put the zip in the bundle
Bundle extras = in.getExtras();
if (extras != null) {
in.putExtra(zip_key, zipStr);
}

setResult(Activity.RESULT_OK, in);

// Close this activty
act.finish();
}
}
});
}

}

From the code Listing 6.7 above, we see that when one clicks on the Done button, we perform the following steps:

The act of setting the result by invoking setResult() and calling finish() on the Activity is what triggers the Android system to invoke the callback method onActivityResult() on the main Email Activity.

We are now ready to test our DroidActivityData application on the virtual Android device we created in Part-1. We will create a Run Configuration for DroidActivityData as we did in Part-2 for DroidTipCalculator.

Once the run configuration for DroidActivityData is ready, we will Run the application and the application will come to life as shown in the following figure 6.3 below:

Email Activity Image
Figure-6.3

Type in an email id and click the Submit button as shown in the following figure 6.4 below:

Email Activity Image
Figure-6.4

This will pop-up a dialog box as shown in the following figure 6.5 below:

Activity Chooser Image
Figure-6.5

Hmmm ... What happened here ? Recollect the example from Part-4 where we demonstrated the DroidMultiActivity application. We used the same action name com.polarsparc.android.ACTIVITY_TWO. When the Android system receives the Intent with the action com.polarsparc.android.ACTIVITY_TWO, it matches it to the activities in the two applications - one from DroidMultiActivity and the other from this application DroidActivityData. Hence the Android system is displaying a dialog to confirm which application to use.

Click on the ActivityTwo from the application DroidActivityData as shown in the following figure 6.6 below:

Activity Chooser Image
Figure-6.6

This action will launch the Zip Activity and also display the email id from the previous Email Activity as shown in the following figure 6.7 below:

Zip Activity Image
Figure-6.7

Type in the zipcode and click the Done button as shown in the following figure 6.8 below:

Zip Activity Image
Figure-6.8

This action will complete the Zip Activity and bring us back to the main Email Activity but this time display the zipcode as shown in the following figure 6.9 below:

Email Activity Image
Figure-6.9

References

Taste of Android :: Part-1

Taste of Android :: Part-2

Taste of Android :: Part-3

Taste of Android :: Part-4

Taste of Android :: Part-5