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.
Intents
Used to activate:
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);
Sharing Data
How do we share data across activity? How do we keep global data in an application? There are many ways:
We will give you detailed code for all of the above.
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");�}
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;
}
}
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:
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();
}
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);
}
Implicit intents
They are later bound to activities; you don't designate the activity explicitly. Components:
And optionally:
Examples of action/data pairs
Example of implicit intent
Intent intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:555-1234"));
startActivity(intent);
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);
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();
}
});
Handling the results
You need to override the onAcivityResults event handler of the activity. The handler receives:
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;
...
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>
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>
Category test
<intent-filter . . . >
<category android:name="android.intent.category.DEFAULT" />
<category android:name="android.intent.category.BROWSABLE" />
. . .
</intent-filter>
Data test
<intent-filter . . . >
<data android:mimeType="video/mpeg" android:scheme="http" . . . />
<data android:mimeType="audio/mpeg" android:scheme="http" . . . />
. . .
</intent-filter>
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();
}
To decline performing the intent
Intent intent = getIntent();
if (isDuringBreak)
startNextMatchingActivity(intent);
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>
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.
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.
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>
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>
Broadcast events - sending
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);
...
Native broadcast actions
And lots more (see documentation).