Lab 3: Intents
Explicit Intent
- Copy the Lab2 project directory to a new directory named Lab3a.
- Modify the NumberAdapter implementation and make it more like a true dynamic data adapter
- Create a new class named Item. An Item will represent a data entity that will provide the data that we wish to display in an individual grid cell.
- Add a private final int field named index.
- Let the IDE generate the constructor.
- Right-click the field and use Refactor->Encapsulate Fields option to generate the "getter" method.
- Use the Code->Override Methods menu to override the equals(), hashCode() and toString() methods.
- Return 31 + ( 31 * index ) from the hashCode() method.
- Add a method getTitle() that returns the String "Cell i" i is the index (or index + 1).
- Make the overridden toString() method return getTitle().
- Add a method getDescription() that returns the result of getTitle() repeated 100 times or so (separated by a space).
- Implement equals() similar to return ( o instanceof Item ) && index == ( (Item) o ).index;
- Create a new class of kind Singleton named Database. This will serve as our Data Access Object (DAO) for this project.
-
- Introduce a private final field of type Map<Integer,Item> named map and initialize it to a HashMap instance. This will just cache Item instance we create to avoid re-creating the same Item entity multiple times as the user scrolls the grid view.
- Create a new method named getItem that takes an int parameter and returns an Item.
- Check the map instance for a key at specified parameter.
- If an entry does not exist, insert a new entry.
- Return the value stored in the map for the specified parameter.
- Create a new method named getCount() that returns the number of items available in our database (100 for instance).
- Use the Item class in NumberAdapter
-
- Modify the getItem() method to use the getItem method in the Database singleton.
- Modify the getCount() method to use the getCount method in the Database singleton.
- Modify the getView() method to use the Object (Item instance) returned by getItem() to set the tag and text in the TextView.
final Item item = (Item) getItem( position );
textView.setTag( item );
textView.setText( item.getTitle() );
- Create a new class named Item. An Item will represent a data entity that will provide the data that we wish to display in an individual grid cell.
- Add a new blank activity named ItemView to the project (in the same package as other sources). This will be used to display the details of a user selected Item from the grid view.
- Edit the layout file for the activity and add two TextView's to it - title (for displaying item title) and description (for displaying item description). Set the lines property for the description widget to 10 or so.
- Edit the onCreate() method in the activity and retrieve the item index in the intent to set the text in the TextView.
final int index = getIntent().getExtras().getInt( "index" );
final Item item = Database.getInstance().getItem( index );
( (TextView) findViewById( R.id.title ) ).setText( item.getTitle() );
( ( TextView) findViewById( R.id.description ) ).setText( item.getDescription() );
- Modify the ClickListener class that handles clicks on the grid cells to create a new intent and start the ItemView activity instead of displaying the Toast message.
final TextView tv = (TextView) v;
final Item item = (Item) tv.getTag();
final Intent intent = new Intent( context, ItemView.class );
intent.putExtra( "index", item.getIndex() );
context.startActivity( intent ); - Run and check the application.
- Update the test suite to match the changes. Edit the MainActivityTest source file
-
- Remove the allCells method.
- Modify the cell() method to use the Item instance for validation instead of the hard-coded string.
- Modify the onClick() method to validate the title and description displayed in the ItemView activity after performing the click.
sleep( 500 );
onView( withId( R.id.title ) ).check( matches( withText( item.getTitle() ) ) );
onView( withId( R.id.description ) ).check( matches( withText( item.getDescription() ) ) );
Implicit Intent
We will now make our ItemView activity available to be launched from other applications installed on the device/emulator. To do so will add an intent-filter for the ItemView activity, and then create a new application that will use an implicit intent to launch the ItemView activity developed earlier.
- Edit the manifest file and add intent filters to the ItemView activity.
<intent-filter>
<action android:name="android.intent.action.VIEW"/>
<category android:name="android.intent.category.DEFAULT"/>
<data android:mimeType="mis142/item"/>
</intent-filter> - Run the application to register the intent filter in Android.
- Create a new empty activity project named Lab3b. Remove the appcompat library support and set the instrumentation runner for testing.
- Edit the layout file and add a button with text "Launch Item View".
- Attach a click listener to the button which will launch the ItemView activity in the Lab3a application.
final Button button = (Button) findViewById( R.id.button );
button.setOnClickListener( new OnClickListener() {
@Override
public void onClick( View v )
{
final Intent intent = new Intent( Intent.ACTION_VIEW );
intent.putExtra( "index", 10 );
intent.setType( "mis142/item" );
if ( intent.resolveActivity( getPackageManager() ) != null ) startActivity( intent );
else Log.e( getClass().getName(), "Unable to resolve intent" );
}
} ); - Run the Lab3b application and verify that the ItemView activity is loaded.
- Create an automated test class as before, add a Rule and a test onClick method. Sleep 500 milliseconds after performing the click action on the button and verify that a new View with specified title is loaded.
assertNotNull( "View not found", onView( withText( "Cell 11" ) ) );