mobappdev (fall 2013): explicit & implicit intents, intent resolution, data transfer with...
Post on 05-Dec-2014
568 Views
Preview:
DESCRIPTION
TRANSCRIPT
MobAppDev
Explicit & Implict Intents, Intent Resolution, Data Transfer with Intents, Getting Results from Started Activities
Vladimir Kulyukin
www.vkedco.blogspot.com
Outline● Explicit Intents● Implicit Intents● Intent Resolution● Data Transfer with Intents● Get Results from Started Activities
Review: Intents
● Intents are messages that allow Android components (e.g., activities, applications, etc) to send computational requests or notifications to other Android components via Android OS
● Intents are used for requesting information, computation, or event signaling
● All intents objects are instances of android.content.Intent
Explicit Intents
Explicit Intents
● If Android OS resolves an explicit intent via its Java class identifier & the component specified by the class identifier is accessible, the component will likely be launched
● Explicit intents are typically used within one application when the developers have control over the Java class identifiers of the components
Data Transfer with Intents
● Intents can bundle and transfer data to other components via Android
● An intent sender creates an intent, puts a few key-value pairs into its bundle and sends it to Android
● An intent receiver receives an intent, checks it for the presence/absence of specific keys and then does some action
● Keys are always Strings
Explicit Intent Examples
Explicit Intents: Example 01
● Develop an app that has two Activities: PixBrowserExpIntentsActivity_01 and ImageDisplayerAct_01
● The PixBrowserExpIntentsActivity_01 activity consumes a button click and launches the ImageDisplayerAct_01 activity via an explicit intent
● The ImageDisplayerAct_01 activity displays a random image with an ImageView object
● Source code is here
Sample Screenshots
Code Fragments
Image Displayer's Layout
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:orientation="vertical" >
<ImageView
android:id="@+id/img_view_01"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:src="@drawable/img_01" />
</LinearLayout>
Main Activity's Layout<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical" >
<ImageView
android:id="@+id/img_01"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_weight="1"
android:src="@drawable/img_01" />
<LinearLayout
android:layout_width="match_parent"
android:layout_height="wrap_content" >
<Button
android:id="@+id/btn_display"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:text="@string/btn_display_txt" />
</LinearLayout>
</LinearLayout>
AndroidManifest.xml<manifest xmlns:android="http://schemas.android.com/apk/res/android" >
<application >
<activity
android:name=".PixBrowserExpIntentsActivity_01"
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=".ImageDisplayerAct_01" android:label="Image Displayer 01">
<intent-filter>
<action android:name="android.intent.action.ImageDisplayerAct_01" />
<category android:name="android.intent.category.DEFAULT" />
</intent-filter>
</activity>
</application>
</manifest>
PixBrowserExpIntentsActivity_01.onCreate()protected Button mBtnDisplay = null;
protected Activity mThisAct = null;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_pix_browser_exp_intents_activity_01);
mBtnDisplay = (Button) this.findViewById(R.id.btn_display);
mThisAct = this;
// Button click creates an explicit intent to request a launch of ImageDisplayerAct01
mBtnDisplay.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
// 1. Create an explicit intent
Intent i = new Intent(mThisAct, ImageDisplayerAct_01.class);
// 2. Request Android to consider it.
startActivity(i); }});
}
ImageDisplayerAct_01.onCreate()
protected ImageView mImgView = null;
protected void onCreate(Bundle savedInstanceState) {
mImgView = (ImageView) this.findViewById(R.id.img_view_01);
mImgView.setImageDrawable(null);
int img_num = new Random().nextInt(8) + 1;
switch ( img_num ) {
case 1: mImgView.setBackgroundResource(R.drawable.img_01); break;
case 2: mImgView.setBackgroundResource(R.drawable.img_02); break;
// Other cses for 3 to 8
}
Toast.makeText(this, getResources().getString(R.string.randome_img_msg) + " " + img_num,
Toast.LENGTH_SHORT).show();
}
Explicit Intents: Example 02● Develop an app that has two Activities: MainLauncher and
ImageDisplayerAct02
● The MainLauncher activity consumes a button click and launches the ImageDisplayerAct02 activity via an explicit intent AND passes to the ImageDisplayerAct02 the numerical ID of the image to display
● The ImageDisplayerAct02 activity displays the requested image in an ImageView object
● We will call this project ExplicitIntentsApp02
● Source code is here
Code Fragments
MainLauncherAct.onCreate() mBtnDisplay.setOnClickListener(
new OnClickListener() {
public void onClick(View v) {
// 1. Create an explicit intent
Intent i = new Intent(mThisAct, ImageDisplayerAct02.class);
// 2. Generate a random number in [1, 8]
int random_img_id = new Random().nextInt(8) + 1;
// 3. Put key-value pair into the intent.
i.putExtra(mRes.getString(R.string.img_id_key), random_img_id);
// 4. Toast which image is requested.
Toast.makeText(mThisAct,
mRes.getString(R.string.img_display_request_msg) + " "
+ random_img_id, Toast.LENGTH_SHORT).show();
// 5. Request Android to run it.
startActivity(i);}});
}
ImageDisplayerAct02.onCreate()
// 1. Get the intent
Intent i = this.getIntent();
// 2. Check to see if it contains an integer keyed on R.string.img_id_key.
// default to 0 if it does not.
int img_num = i.getIntExtra(mRes.getString(R.string.img_id_key), 0);
// 3. If it does, display it
if (img_num > 0) {
switch (img_num) {
case 1: mImgView.setBackgroundResource(R.drawable.img_01); break;
case 2: mImgView.setBackgroundResource(R.drawable.img_02); break;
// handle other cases from 3 to 8
}
// Set the text of the mTV text view to the appropriate message.
mTV.setText(mRes.getString(R.string.img_display_msg) + " " + img_num);
Implicit Intents
Implicit Intents● Implicit intents provide a mechanism for anonymous
(no explicit activity specification) requests ● An activity asks Android OS to do an action by
specifying high-level requirements but without knowing which activity or application will actually perform the action
● The requesting action can specify a URI to the data which the performing activity must process or add that data to the implicit intent
Native Android Actions● Android OS defines many actions that can be satisfied by
native or 3-rd party components and are launched via implicit intents
● Here are some examples: – ACTION_ANSWER – open an activity that handles incoming
calls– ACTION_CALL – open an activity with a phone dialer– ACTION_PICK – launch an activity to pick an item from a list of
items– ACTION_WEB_SEARCH – launch an activity to perform a web
search– ACTION_VIEW – launch an activity that can view the specified
data in a reasonable manner
Implicit Intents
● Implicit intents provide a mechanism for anonymous requests
● An implicit intent is launched with startActivity(Intent i)
● Activities and applications use intent filters to tell Android ecosystem about the actions they respond to and/or which data types they work with
● An component that has an intent filter is called an intent filter
Intent Filter's Structure● Action
– Name of the action being serviced– Name should be a unique string– Best practice is to use the Java package
naming convention ● Category
– When the action should be serviced● Data
– Data types that the action can work with
Intent Resolution
● Intent resolution starts when an activity calls startActivity() or startActivityForResult() with some intent Intnt
● Android OS gets the list of all intent filters available from the installed packages
● Intent filters that do not match Intnt's requested action or category are removed from the list
Intent Resolution● An action match occurs when Intnt's action
and the filter's action are the same or no action is specified
● A category match occurs when Intnt's categories and the filter's categories are the same
● A data match occurs when Intnt's data types are the same as the filter's data types
Intent Resolution
● Native Android components are part of the Intent resolution process
● Native components are no different from 3rd-part components
● Native components do not have higher-priorities and can be completely replaced with 3rd-party components with the user's consent
● Android ecosystem does not give anyone a priori advantages to any components
Implicit Intent Example
● Develop an app that uses an implicit intent to request Android ecosystem to find a component that can display the wiki entry about Kurt Gödel
● This implicit intent must contain two components: Intent.ACTION_VIEW and the URI (e.g., URL of a web page)
● The default native component that responds to this intent is the web browser
● Source code is here
Sample Screenshots
Code Fragments
Wiki Constant in /res/values/strings.xml
<resources>
...
<string name=”kurt_godel_wiki_url”>
http://en.wikipedia.org/wiki/Kurt_Godel
</string>
...
</resources>
Launching Intent for Viewing URL
public class GodelWikiPageBrowserAct extends Activity {
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.godel_wiki_page_browser_act_layout);
Intent myIntent = new Intent(Intent.ACTION_VIEW,
Uri.parse(getResources().getString(R.string.kurt_godel_wiki_url)));
this.startActivity(myIntent);
}
…
}
Getting Results from
Started Activities
startActivity() vs startActivityForResult()
● In some cases, a component wants to get a result from an activity that it wants to launch either explicitly or implicity
● In this case, the launching component must use startActivityForResult() and implement onActivityResult()
● startActivityForResult() takes an intent and a request code (intenger constant)
● onActivityResult() is called when Android ecosystem responds to the intent launcher
startActivity() vs startActivityForResult()
● In some cases, a component wants to get a result from an activity that it wants to launch either explicitly or implicity
● In this case, the launching component must use startActivityForResult() and implement onActivityResult()
● startActivityForResult() takes an intent and a request code (intenger constant)
● onActivityResult() is called when Android ecosystem responds to the intent launcher
Example
● Develop an app that attaches uses an implicit intent to check for the availability of the Text-to-Speech (TTS) engine
● If the the TTS data are not installed, another intent is launched to install the data
● If all installations are successful, the app displays an activity that allows the user to enter texts and send them to the TTS
● Source code is here
Sample Screenshots
Code Fragments
Launching Intent with Expected Result
// The request type constants.
private static final int REQ_TTS_STATUS_CHECK = 0;
// PICO TTS object
private TextToSpeech mTts = null;
// Create intent to check tts data
Intent checkTtsIntent =
new Intent(TextToSpeech.Engine.ACTION_CHECK_TTS_DATA);
startActivityForResult(checkTtsIntent, REQ_TTS_STATUS_CHECK);
Processing Intent's Resultprotected void onActivityResult(int requestCode, int resultCode, Intent data) {
if ( requestCode == REQ_TTS_STATUS_CHECK ) {
switch ( resultCode ) {
case TextToSpeech.Engine.CHECK_VOICE_DATA_PASS:
mTts = new TextToSpeech(this, this); break;
case TextToSpeech.Engine.CHECK_VOICE_DATA_BAD_DATA:
case TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_DATA:
case TextToSpeech.Engine.CHECK_VOICE_DATA_MISSING_VOLUME:
Intent installIntent = new Intent();
installIntent.setAction(TextToSpeech.Engine.ACTION_INSTALL_TTS_DATA);
startActivity(installIntent);
case TextToSpeech.Engine.CHECK_VOICE_DATA_FAIL:
default: Log.d(TAG, getResources().getString(R.string.tts_unavailable));
}
}}
Stopping or Shutting TTSpublic void onStop() {
super.onStop();
if ( mTts != null ) { mTts.stop(); }
}
public void onPause() {
super.onPause();
if ( mTts != null ) { mTts.stop(); }
}
public void onDestroy() {
super.onDestroy();
mTts.shutdown();
}
References● http://developer.android.com/reference/android/content/Intent.html
http://developer.android.com/reference/android/speech/tts/package-summary.html
top related