After working on our first list application and finally adding the user photos to our list we now want to show you how you can use your activity in another context.
This tutorial will show you how you can use a button to open the created contact list to pick a contact and display the name of the picked contact with the “Toast widget”.
The first thing you should do: create another project to be sure to have two working application samples.
Package: com.droidnova.android.samples
Activity name: PickYourDude
Application name: Pick your dude
Lets start again with the layout. First change the name of the main.xml into button.xml because we will define the layout of our main activity where only a text and a button is visible.
After that we define a LinearLayout, a TextView and a Button. Should look like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | <?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"> <TextView android:id="@+id/button_info_text" android:text="@string/button_info_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" android:paddingTop="20dip" android:paddingBottom="20dip" /> <Button android:id="@+id/button" android:text="@string/button_text" android:layout_width="wrap_content" android:layout_height="wrap_content" android:layout_gravity="center_horizontal" /> </LinearLayout> |
From our earlier tutorials this should look familar to you. Please note the paddingTop and paddingBottom which work similar to css paddings as well as the layout_gravity property which is used for relative alignment.
After the button.xml we create a new xml named contact.xml. The content is exactly the same as the main.xml in our first list application and the addon for using photos.
Here is the whole xml:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 | <?xml version="1.0" encoding="utf-8"?> <LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" android:orientation="horizontal" android:layout_width="fill_parent" android:layout_height="fill_parent"> <ImageView android:id="@+id/contact_image" android:src="@drawable/icon" android:layout_width="wrap_content" android:layout_height="wrap_content" /> <LinearLayout android:orientation="vertical" android:layout_width="fill_parent" android:layout_height="fill_parent"> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Name: " /> <TextView android:id="@+id/contact_name" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> <LinearLayout android:orientation="horizontal" android:layout_width="wrap_content" android:layout_height="wrap_content"> <TextView android:layout_width="wrap_content" android:layout_height="wrap_content" android:text="Phone: " /> <TextView android:id="@+id/phone_number" android:layout_width="wrap_content" android:layout_height="wrap_content" /> </LinearLayout> </LinearLayout> </LinearLayout> |
Next task is to define some static strings for our application to display. We need a name for our application, a text to display above the button, a button label, a label for the contact list and the text the Toast widget should display.
So lets modify the strings.xml and define the following:
1 2 3 4 5 6 7 8 | <?xml version="1.0" encoding="utf-8"?> <resources> <string name="app_name">Pick your dude</string> <string name="button_info_text">Please choose a contact</string> <string name="button_text">Pick</string> <string name="contacts">Contacts</string> <string name="chosen">You have chosen:</string> </resources> |
Well now we can copy our ListContacts activity from the previous tutorial and rename that to Contacts. We should rename the class because we want to do more with it than just list some contacts.
After renaming the class and correcting the package definition to com.droidnova.android.samples we open the class in our IDE and we will see an error. On line 28 the old layout is still set to “main”. This needs to be changed to “contact”. The rest should be ok.
Now we modify our AndroidManifest.xml and add the Contacts activity. We also define which action can be performed on this activity. We choose PICK and VIEW and the category DEFAULT. The whole xml should look like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" android:versionCode="1" android:versionName="1.0.0" package="com.droidnova.android.samples"> <uses-permission android:name="android.permission.READ_CONTACTS" /> <uses-permission android:name="android.permission.CALL_PHONE" /> <application android:icon="@drawable/icon" android:label="@string/app_name"> <activity android:label="@string/contacts" android:name=".Contacts"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <action android:name="android.intent.action.PICK" /> <category android:name="android.intent.category.DEFAULT" /> </intent-filter> </activity> <activity android:label="@string/app_name" android:name=".PickYourDude"> <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest> |
The changes are only from line 8 to 14 where we define the activity, the actions and the category.
The next step is to create the logic. So open up the PickYourDude activity.
The first thing we should notice is the error because the code still uses the R.layout.main. Change it to the button layout.
1 | setContentView(R.layout.button); |
The text for the TextView is defined in the strings.xml and the reference is in the button.xml so we don’t have to touch the TextView ourself.
The button is also labeled automatically but we have to add an OnClickListener to execute custom code. We create our own OnClickListener named MyOnClickListener as a private inner class in PickYourDude.
1 2 3 4 5 6 | private class MyOnClickListener implements View.OnClickListener { @Override public void onClick(View v) { startActivityForResult(new Intent(Intent.ACTION_PICK), PICK_CONTACT); } } |
The method “startActivityForResult” accepts an Intent as the first parameter. The Intent has to be constructed with an action you want to trigger. In our case the ACTION_PICK.
The static class variable PICK_CONTACT is like a flag, so that we can distinguish in which context the activity was started. We define it right above our onCreate method.
1 | private static final int PICK_CONTACT = 0; |
The flag should have at least a non negative value because a value below zero is like calling the startActivity method on which we don’t get a result.
Now we have to add this OnClickListener to our button with two new lines in our onCreate method of PickYourDude.
1 2 | Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new MyOnClickListener()); |
The next thing is to implement the PICK logic in our Contacts activity.
We should modify the onListItemClick method right below the line where we set the data for the intent.
First lets get the action on which this activity was started.
1 | String action = getIntent().getAction(); |
If the action is ACTION_VIEW we just want to start the Intent to make the call.
1 2 3 | if (Intent.ACTION_VIEW.equals(action)) { startActivity(intent); } |
But if the action was ACTION_PICK, we want to set the result and pass the data back.
1 2 3 4 5 6 | if (Intent.ACTION_VIEW.equals(action)) { startActivity(intent); } else if (Intent.ACTION_PICK.equals(action)) { setResult(RESULT_OK, intent); finish(); } |
The finish() method just ends the activity to free the resources.
The whole method looks like this.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | @Override protected void onListItemClick(ListView listView, View view, int position, long id) { super.onListItemClick(listView, view, position, id); Intent intent = new Intent(Intent.ACTION_CALL); Cursor cursor = (Cursor) myAdapter.getItem(position); long phoneId = cursor.getLong(cursor.getColumnIndex(People.PRIMARY_PHONE_ID)); intent.setData(ContentUris.withAppendedId(Phones.CONTENT_URI, phoneId)); String action = getIntent().getAction(); if (Intent.ACTION_VIEW.equals(action)) { startActivity(intent); } else if (Intent.ACTION_PICK.equals(action)) { setResult(RESULT_OK, intent); finish(); } } |
Now we have to go back to the PickYourDude activity to implement what we do with the result of the activity. For that we need to override the onActivityResult method to implement our own logic.
The first parameter is the requestCode we set with the flag at the call of startActivityForResult(). In our case we check if the parameter is PICK_CONTACT.
1 2 3 4 5 6 | @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT) { // todo } } |
Next we check if the result is ok which is set on calling the method setResult in the Contracts activity.
1 2 3 4 5 6 7 8 | @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT) { if (resultCode == RESULT_OK) { // todo } } } |
In a more complete method you might want to add more sophisticated conditions to react should result not be “OK” for example.
Now we have to use the data for a content query and get the data we want, in our case the name of the contact.
1 2 3 4 5 6 7 8 9 10 11 | @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT) { if (resultCode == RESULT_OK) { Cursor contact = getContentResolver().query(data.getData(), null, null, null, null); contact.moveToFirst(); String name = contact.getString(contact.getColumnIndexOrThrow(People.NAME)); Toast.makeText(this, getString(R.string.chosen) + " " + name, Toast.LENGTH_LONG).show(); } } } |
We know how to use a Cursor so lets use one. Please don’t forget to move to the first entry of the cursor because the cursor does not point to a result by default.
After that we get the name of the contact using the Cursor and finally start the Toast widget. The widget needs a context, a string and the duration to display itself. Finally we call the show() method to display the widget.
The complete activity looks like that.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 | package com.droidnova.android.samples; import android.app.Activity; import android.content.Intent; import android.database.Cursor; import android.os.Bundle; import android.provider.Contacts.People; import android.view.View; import android.widget.Button; import android.widget.Toast; public class PickYourDude extends Activity { private static final int PICK_CONTACT = 0; @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.button); Button button = (Button) findViewById(R.id.button); button.setOnClickListener(new MyOnClickListener()); } @Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { if (requestCode == PICK_CONTACT) { if (resultCode == RESULT_OK) { Cursor contact = getContentResolver().query(data.getData(), null, null, null, null); contact.moveToFirst(); String name = contact.getString(contact.getColumnIndexOrThrow(People.NAME)); Toast.makeText(this, getString(R.string.chosen) + " " + name, Toast.LENGTH_LONG).show(); } } } private class MyOnClickListener implements View.OnClickListener { @Override public void onClick(View v) { startActivityForResult(new Intent(Intent.ACTION_PICK), PICK_CONTACT); } } } |
As you can see we used some different intents, overrode methods, extended different classes and used different layouts. Equipped with this basics you should be able to start some not-so-simple applications by yourself.
For any improvements, questions and/or hints feel free to comment.
Comments
Leave a comment Trackback