Copyright © 2009, 2010, 2011, 2012 Lars Vogel
17.04.2012
Revision History | ||
---|---|---|
Revision 0.1 | 20.07.2010 | LarsVogel |
Created | ||
Revision 0.2 - 2.6 | 19.07.2010 - 17.04.2012 | LarsVogel |
bug fixes and enhancements |
Table of Contents
- 1. Android Intents
- 2. Using Intents to call Activities
- 3. Defining Intent Filters
- 4. Intents as event triggers
- 5. Share Intent and ShareActionProvider
- 6. Finding out if an Intent is available
- 7. Prerequisites for this tutorial
- 8. Tutorial: Explicit intents and data transfer between activities
- 9. Tutorial: Implicit Intents
- 10. Tutorial: Registering an IntentFilter
- 11. Tutorial: Picking an Image via Intent
- 12. Thank you
- 13. Questions and Discussion
- 14. Links and Literature
Intents
are asynchronous messages which allow Android components to request functionality from other components of the Android system. For example an Activity
can send an Intents
to the Android system which starts another Activity
. Therefore
Intents
allow to combine loosely coupled components to perform certain tasks. Intents
can be used to signal to the Android system that a certain event has occurred. Other components in Android can register to this event and will get notified. Intents
are instances of the android.content.Intent
class. Intents
are send to the Android system. Depending on how the Intent
was constructed the Android system will run an receiver determination and determine what to do. An
Intent
can also contain data. This data can be used by the receiving component. For example your application can calls via an Intent
a browser component. As data is it may send the URL to the browser component. Android supports explicit and implicit
Intents
.
Explicit
The following shows an explicit
Explicit
Intents
explicitly names the component which should be called by the Android system, by using the Java class as identifier. The following shows an explicit
Intent
. If that Intent
is correctly send to the Android system, it will start the associated class. Intent i = new Intent(this, ActivityTwo.class); i.putExtra("Value1", "This value one for ActivityTwo "); i.putExtra("Value2", "This value two ActivityTwo");
Explicit
Intents
are typically used within on application as the classes in an application are controlled by the application developer.
Implicit
For example the following tells the Android system to view a webpage. Typically the web browser is registered to this
If only one component is found, Android starts this component directly. If several components are identifier by the Android system, the user will get an selection dialog and can decide which component should be used for the
Intents
do not specify the Java class which should be called. They specify the action which should be performed and optionally an URI which should be used for this action. For example the following tells the Android system to view a webpage. Typically the web browser is registered to this
Intent
but other component could also register themself to this event. Intent intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.vogella.com"));If these
Intents
are send to the Android system it searches for all components which are registered for the specific action and the data type. If only one component is found, Android starts this component directly. If several components are identifier by the Android system, the user will get an selection dialog and can decide which component should be used for the
Intent
.
An implicit
Explicit and implicit
The component which creates the
For example you can trigger all components which have been registered to send some data via the
The component which receives the
Intent
contains the Action and optional the URI. The receiving component can get this information via the getAction()
and getData()
methods. Explicit and implicit
Intents
can also contain additional data. This data call be filled by the component which creates the Intent
. It can and can get extracted by the component which receives the Intent
. The component which creates the
Intent
can add data to it via the overloaded putExtra()
method. Extras are key/value pairs; the key is always a String. As value you can use the primitive data types (int, float,..), String, Bundle, Parceable and Serializable. For example you can trigger all components which have been registered to send some data via the
new Intent(Intent.ACTION_SEND)
This Intent
determines possible receivers via the type. What is send it defined via the putExtra
method. You can use any String as key, the following uses the keys which are predefined for the ACTION_SEND intent. Intent intent = new Intent(Intent.ACTION_SEND); intent.setType("text/plain"); intent.putExtra(android.content.Intent.EXTRA_TEXT, "News for you!"); startActivity(intent);
The component which receives the
Intent
can use the getIntent().getExtras()
method call to get the extra data. Bundle extras = getIntent().getExtras(); if (extras == null) { return; } // Get data via the key String value1 = extras.getString(Intent.EXTRA_TEXT); if (value1 != null) { // Do something with the data }
If you send an
To start an
If you call an
Intent
to the Android system, Android requires that you tell it to which type of component your Intent
should be send. To start an
Activity
use the method startActivity(Intent)
. This method is defined on the Context
object and available in every Activity
object. If you call an
Activity
with the startActivity(Intent)
method the caller requires no result from the called Activity
.
If you need some information from the called
If you use the
If the Sub-Activity is finished it can send data back to its caller via Intent. This is done in the
Once the
Activity
use the startActivityForResult()
method. public void onClick(View view) { Intent i = new Intent(this, ActivityTwo.class); i.putExtra("Value1", "This value one for ActivityTwo "); i.putExtra("Value2", "This value two ActivityTwo"); // Set the request code to any code you like, you can identify the // callback via this code startActivityForResult(i, REQUEST_CODE); }
If you use the
startActivityForResult()
method then the started Activity
is called a Sub-Activity
. If the Sub-Activity is finished it can send data back to its caller via Intent. This is done in the
finish()
method. @Override
public void finish() {
// Prepare data intent
Intent data = new Intent();
data.putExtra("returnKey1", "Swinging on a star. ");
data.putExtra("returnKey2", "You could be better then you are. ");
// Activity finished ok, return the data
setResult(RESULT_OK, data);
super.finish();
}
Once the
Sub-Activity
finished, the onActivityResult()
method in the calling Activity
will be called. @Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
if (resultCode == RESULT_OK && requestCode == REQUEST_CODE) {
if (data.hasExtra("returnKey1")) {
Toast.makeText(this, data.getExtras().getString("returnKey1"),
Toast.LENGTH_SHORT).show();
}
}
}
If an
This determination is based on
The following will register an
This is an example how you could define an Intent receiver for the ACTION.SEND Intent.
If a component does not define
The following example will register an Activity for the ACTION_SEND intent for the "text/plain" mime type.
Intent
is send to the Android system, it will determine suitable applications for this Intent
. If several components have been registered for this type of Intent
, Android offers the user the choice to open one of them. This determination is based on
IntentFiltes
. An IntentFilter
specifies the types of Intent
that an activity, service, or broadcast receiver can respond to. An IntentFilter
declares the capabilities of a component. It specifies what an Activity or Service can do and what types of broadcasts a Rseceiver can handle. It allow the corresponding component to receive Intents of the declared type. IntentFilters
are typically defined via the AndroidManifest.xml
file. For BroadcastReceiver
it is also possible to define them in coding. An IntentFilters
is defined by its category, action and data filters. It can also contain additional metadata. The following will register an
Activity
for the Intent
which is triggered when someone wants to open a webpage. <activity android:name=".BrowserActivitiy" android:label="@string/app_name"> <intent-filter> <action android:name="android.intent.action.VIEW" /> <category android:name="android.intent.category.DEFAULT" /> <data android:scheme="http"/> </intent-filter> </activity>
This is an example how you could define an Intent receiver for the ACTION.SEND Intent.
<activity android:name=".ActivityTest" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> </activity>
If a component does not define
Intent
filters, it can only be called by explicit Intents
. The following example will register an Activity for the ACTION_SEND intent for the "text/plain" mime type.
<activity android:name=".ActivityTest" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.SEND" /> <category android:name="android.intent.category.DEFAULT" /> <data android:mimeType="text/plain" /> </intent-filter> </activity>
As of Android 3.1 the Android system will by default exclude all
This is an additional security features as the user can be sure that only the applications he started will receive broadcast
BroadcastReceiver
from receiving Intents
if the corresponding application has never been started by the user or if the user explicitly stopped the application via the Android menu (in Manage Application). This is an additional security features as the user can be sure that only the applications he started will receive broadcast
Intents
. Intents
can also be used to send broadcast messages into the Android system. BroadcastReceivers
can register to event and will get notified if such an event is triggered. Your application can register to system events, e.g. a new email has arrived, system boot is complete or a phone call is received and react accordingly.
As said earlier, since Android version 3.1 the Android system will per default exclude all
BroadcastReceiver
from receiving Intents
if the corresponding application has never been started by the user or if the user explicitly stopped the application via the Android menu (in Manage Application).
As of Android 4.0 you can also add an Action Provider to your ActionBar which allows to share. For this you have to define a special menu entry and assign an
Unfortunately this does not seem to work in the Android emulator, see Bug report for details .
Intent
which contain the sharing data to it in your Activity
. <?xml version="1.0" encoding="utf-8"?> <menu xmlns:android="http://schemas.android.com/apk/res/android" > <item android:id="@+id/menu_share" android:title="Share" android:showAsAction="ifRoom" android:actionProviderClass="android.widget.ShareActionProvider" /> <item android:id="@+id/item1" android:showAsAction="ifRoom" android:title="More entries..."> </item> </menu>
@Override
public boolean onCreateOptionsMenu(Menu menu) {
getMenuInflater().inflate(R.menu.mymenu, menu);
// provider is a field in your Activity
provider = (ShareActionProvider) menu.findItem(R.id.menu_share)
.getActionProvider();
setShareIntent();
return true;
}
public void setShareIntent() {
Intent intent = new Intent(Intent.ACTION_SEND);
intent.setType("text/plain");
intent.putExtra(Intent.EXTRA_TEXT, "Message");
provider.setShareIntent(intent);
}
Unfortunately this does not seem to work in the Android emulator, see Bug report for details .
Sometimes you want to find if an application has registered for a certain intent. For example you want to check if a certain receiver is available and if you enable some functionality in your app.
This can be done via checking the
This can be done via checking the
PackageManager
. The following code checks if an Intent
exists. You can check via this method for Intent
and change your application behavior accordingly for example disable or hide menu items. public boolean isIntentAvailable(Context context, String action) {
final PackageManager packageManager = context.getPackageManager();
final Intent intent = new Intent(action);
List<ResolveInfo> resolveInfo =
packageManager.queryIntentActivities(intent,
PackageManager.MATCH_DEFAULT_ONLY);
if (resolveInfo.size() > 0) {
return true;
}
return false;
}
The following assumes that you have already basic knowledge in Android development. Please check the Android development tutorial to learn the basics.
沒有留言:
張貼留言