1 of 30

CMPS 121

Intents and Sharing

Luca de Alfaro

Portions of this presentations are based on content taken from the Android Developers Site. The work was created and shared by the Android Open Source Project and used according to terms described in the Creative Commons 2.5 Attribution License.

2 of 30

Intents

Used to activate:

  • Activities: an Intent is passed to Context.startActivity() or Context.startActivityForResult().
  • Services: an intent is passed to Context.startService(), Context.bindService()
  • Broadcast receivers: intents are passed to Context.sendBroadcast(), ...

3 of 30

Explicit intents

Used to start specific activities.

Intent intent = new Intent(this, MyOtherActivity.class);

startActivity(intent);

Used to start specific activities.

If you want not a new activity object, but to recicle the “most recent” MyOtherActivity, you need to add flags to the activies.

The following will recycle the top copy of the new activity on the stack:

intent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);

4 of 30

Sharing Data

How do we share data across activity? How do we keep global data in an application? There are many ways:

  • Attach data to an intent via a bundle.
  • Put the data into the application preferences (this also persists it).
  • Write data to the filesystem.
  • Use a database (sqlite is built in).
  • Use a singleton class, shared by all activities.
  • ...

We will give you detailed code for all of the above.

5 of 30

Attaching extra data to an intent

From StackOverflow:

String str = "My Data"; //Data you want to send�Intent intent = new Intent(FirstActivity.this, SecondActivity.class);�intent.putExtra("name", str);�startActivity(intent);

Also:

Intent i = new Intent(getApplicationContext(), NewActivity.class);�i.putExtra("new_variable_name","value");�startActivity(i);

Then in the new Activity, retrieve those values:

Bundle extras = getIntent().getExtras();�if (extras != null) {� String value = extras.getString("new_variable_name");�}

6 of 30

Sharing via singleton class

public class AppInfo {

private static AppInfo instance = null;

protected AppInfo() {

// Exists only to defeat instantiation.

}

// Here are some values we want to keep global.

public String username;

public String email;

public static AppInfo getInstance(Context context) {

if(instance == null) {

instance = new AppInfo();

instance.username = null;

instance.email = null;

}

return instance;

}

}

7 of 30

Sharing via singleton class

@Override

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

// Gets a reference to our shared information.

applicationInfo = AppInfo.getInstance(getApplicationContext());

applicationInfo.username = "Luca";

}

Some notes:

  • You cannot assume that the content of the singleton class is initialized. It can disappear if your app is recycled by the system, and re-created later.

8 of 30

Sharing (and storing) via Preferences

@Override

protected void onStop(){

super.onStop();

// We need an Editor object to make preference changes.

SharedPreferences settings =

PreferenceManager.getDefaultSharedPreferences(this);

// Or:

// SharedPreferences settings = getSharedPreferences(PREFS_NAME, 0);

SharedPreferences.Editor editor = settings.edit();

editor.putBoolean("silentMode", mSilentMode);

// Commit the edits!

editor.commit();

}

9 of 30

Preferences, continued

public class Calc extends Activity {

public static final String PREFS_NAME = "MyPrefsFile";

@Override

protected void onCreate(Bundle state){

super.onCreate(state);

. . .

// Restore preferences

SharedPreferences settings =

PreferenceManager.getDefaultSharedPreferences(this);;

boolean silent = settings.getBoolean("silentMode", false);

setSilent(silent);

}

10 of 30

Implicit intents

They are later bound to activities; you don't designate the activity explicitly. Components:

  • Action
  • Data (a URI)

And optionally:

  • Category
  • Type (MIME type) for the intent data
  • component (in which case the rest is optional)
  • extras: a Bundle of extra information. Bundle = a place where you can put/get other information.

11 of 30

Examples of action/data pairs

  • ACTION_VIEW content://contacts/people/1 -- Display information about the person whose identifier is "1".
  • ACTION_DIAL content://contacts/people/1 -- Display the phone dialer with the person filled in.
  • ACTION_VIEW tel:123 -- Display the phone dialer with the given number filled in. Note how the VIEW action does what what is considered the most reasonable thing for a particular URI.
  • ACTION_DIAL tel:123 -- Display the phone dialer with the given number filled in.
  • ACTION_EDIT content://contacts/people/1 -- Edit information about the person whose identifier is "1".
  • ACTION_VIEW content://contacts/people/ -- Display a list of people, which the user can browse through.

12 of 30

Example of implicit intent

Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:555-1234"));

startActivity(intent);

13 of 30

Starting activities for results

Use startActivityForResult. You pass also a request code to identify the request.

private static final int MY_REQUEST = 1;

Intent intent = new Intent(this, MyOtherActivity.class);

startActivityForResult(intent, MY_REQUEST);

Another example:

private static final int PICK_CONTACT_SUBACTIVITY = 2;

Uri uri = Uri.parse("content://contacts/people");

Intent intent = new Intent(Intent.ACTION_PICK, uri);

startActivityForResult(intent, PICK_CONTACT_SUBACTIVITY);

14 of 30

Returning results

Button okButton = (Button) findViewById(R.id.ok_button);

okButton.setOnClickListener(new View.OnClickListener() {

public void onClick(View view) {

Uri data = Uri.parse("content://horses/" + selected_horse_id);

Intent result = new Intent(null, data);

result.putExtra(IS_INPUT_CORRECT, inputCorrect);

result.putExtra(SELECTED_PISTOL, selectedPistol);

setResult(RESULT_OK, result); // Or: setResult(RESULT_CANCELED, null);

finish();

}

});

15 of 30

Handling the results

You need to override the onAcivityResults event handler of the activity. The handler receives:

  • Request code, matching the one used in the intent.
  • Result code (Activity.RESULT_OK or Activity.RESULT_CANCELED, typically)
  • Data: a URI, and/or an extras Bundle.

16 of 30

Handling the results: example

private static final int SHOW_SUB_ACTIVITY_ONE = 1;

private static final int SHOW_SUB_ACTIVITY_TWO = 2;

@Override

public void onActivityResult(int requestCode,

int resultCode,

Intent data) {

super.onActivityResult(requestCode, resultCode, data);

switch(requestCode) {

case (SHOW_SUB_ACTIVITY_ONE) : {

if (resultCode == Activity.RESULT_OK) {

Uri horse = data.getData();

boolean inputCorrect = data.getBooleanExtra(IS_INPUT_CORRECT, false);

String selectedPistol = data.getStringExtra(SELECTED_PISTOL);

}

break;

...

17 of 30

Intent filters

You can add an intent filter (in the manifest) to an activity, service, or broadcast receiver, to declare an interest in performing given actions, or to listen to broadcast events.

To be launchable:

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

18 of 30

Action test

<intent-filter . . . >

<action android:name="com.example.project.SHOW_CURRENT" />

<action android:name="com.example.project.SHOW_RECENT" />

<action android:name="com.example.project.SHOW_PENDING" />

. . .

</intent-filter>

  • Must match at least one action (provided there is an action test; otherwise, the test vacuously passes).

19 of 30

Category test

<intent-filter . . . >

<category android:name="android.intent.category.DEFAULT" />

<category android:name="android.intent.category.BROWSABLE" />

. . .

</intent-filter>

  • All categories must match.
  • Implicit intents always have the category android.intent.category.DEFAULT

20 of 30

Data test

<intent-filter . . . >

<data android:mimeType="video/mpeg" android:scheme="http" . . . />

<data android:mimeType="audio/mpeg" android:scheme="http" . . . />

. . .

</intent-filter>

  • At least one data test must pass.

21 of 30

Finding the intent that launched the activity

@Override

public void onCreate(Bundle icicle) {

super.onCreate(icicle);

setContentView(R.layout.main);

Intent intent = getIntent();

String action = intent.getAction();

Uri data = intent.getData();

}

22 of 30

To decline performing the intent

Intent intent = getIntent();

if (isDuringBreak)

startNextMatchingActivity(intent);

23 of 30

Example of filter, from Notepad

<activity android:name="NotesList" android:label="@string/title_notes_list">

<intent-filter>

<action android:name="android.intent.action.MAIN" />

<category android:name="android.intent.category.LAUNCHER" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.VIEW" />

<action android:name="android.intent.action.EDIT" />

<action android:name="android.intent.action.PICK" />

<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.GET_CONTENT" />

<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />

</intent-filter>

</activity>

24 of 30

Examples of matching intents

action: android.intent.action.MAIN

Launches the activity with no data specified.

action: android.intent.action.MAIN

category: android.intent.category.LAUNCHER

Launches the activity with no data selected specified. This is the actual intent used by the Launcher to populate its top-level list. All activities with filters that match this action and category are added to the list.

25 of 30

Examples of matching intents

action: android.intent.action.VIEW

data: content://com.google.provider.NotePad/notes

Asks the activity to display a list of all the notes under content://com.google.provider.NotePad/notes. The user can then browse through the list and get information about the items in it.

action: android.intent.action.PICK

data: content://com.google.provider.NotePad/notes

Asks the activity to display a list of the notes under content://com.google.provider.NotePad/notes. The user can then pick a note from the list, and the activity will return the URI for that item back to the activity that started the NoteList activity.

action: android.intent.action.GET_CONTENT

data type: vnd.android.cursor.item/vnd.google.note

Asks the activity to supply a single item of Note Pad data.

26 of 30

Example of filter

<activity android:name="NoteEditor"

android:theme="@android:style/Theme.Light"

android:label="@string/title_note" >

<intent-filter android:label="@string/resolve_edit">

<action android:name="android.intent.action.VIEW" />

<action android:name="android.intent.action.EDIT" />

<action android:name="com.android.notepad.action.EDIT_NOTE" />

<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />

</intent-filter>

<intent-filter>

<action android:name="android.intent.action.INSERT" />

<category android:name="android.intent.category.DEFAULT" />

<data android:mimeType="vnd.android.cursor.dir/vnd.google.note" />

</intent-filter>

</activity>

27 of 30

Example of filter

<activity android:name="TitleEditor"

android:label="@string/title_edit_title"

android:theme="@android:style/Theme.Dialog">

<intent-filter android:label="@string/resolve_title">

<action android:name="com.android.notepad.action.EDIT_TITLE" />

<category android:name="android.intent.category.DEFAULT" />

<category android:name="android.intent.category.ALTERNATIVE" />

<category android:name="android.intent.category.SELECTED_ALTERNATIVE" />

<data android:mimeType="vnd.android.cursor.item/vnd.google.note" />

</intent-filter>

</activity>

28 of 30

Broadcast events - sending

  • Create an intent.
  • Use PutExtra, setAction, setData, setType, setDataAndType, addCategory, on the intent.
  • sendBroadcast(intent);

29 of 30

Broadcast events - receiving

<receiver android:name=".LifeformDetectedBroadcastReceiver">

<intent-filter>

<action android:name="com.paad.action.NEW_LIFEFORM"/>

</intent-filter>

</receiver>

public class LifeformDetectedBroadcastReceiver extends BroadcastReceiver {

@Override

public void onReceive(Context context, Intent intent) {

// Get the lifeform details from the intent.

Uri data = intent.getData();

String type = intent.getStringExtra("type");

double lat = intent.getDoubleExtra("latitude", 0);

double lng = intent.getDoubleExtra("longitude", 0);

...

30 of 30

Native broadcast actions