Professional Documents
Culture Documents
Lars Vogel
Version 2.7 Copyright 2009, 2010, 2011, 2012 Lars Vogel 17.07.2012
Revision History
Revision 0.1
20.07.2010
Lars Vogel
Created
19.07.2010 - 17.07.2012
Lars Vogel
Using Intents in Android This tutorials describes what Intents are and how to use them in Android. It is based on Eclipse 3.7, Java 1.6 and Android 4.0.4 (Ice Cream Sandwich).
Table of Contents
1. Android Intents 1.1. Overview 1.2. Explicit Intents 1.3. Implicit Intents 1.4. Data Transfer 2. Using Intents to call Activities 2.1. Calling Activities 2.2. Calling Sub-Activities for result data
3. Defining Intent Filters 3.1. Overview 3.2. Example: Register your Activity as Browser 3.3. Example: Register your Activity for the Share Intent 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 14.1. Source Code 14.2. Android Resources 14.3. vogella Resources
1. Android Intents
1.1. Overview
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 it may send the URL to the browser component. Android supports explicit and implicit Intents.
Explicit Intents are typically used within on application as the classes in an application are controlled by the application developer.
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.
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; }
If you send 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.
// 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() {
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(); } } }
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.
If a component does not define an Intent filter, it can only be called by explicit Intents.
</intent-filter>
</activity>
If a component does not define an Intent filter, it can only be called by explicit Intents.
<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 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 .
Based on the result you can adjust your application for example you could disable or hide certan menu items.
android:minHeight="60dip" android:text="First Activity. Press button to call second activity" android:textSize="20sp" > </TextView>
</LinearLayout>
<EditText android:id="@+id/input1"
</GridLayout>
<application android:icon="@drawable/icon" android:label="@string/app_name" > <activity android:name=".ActivityOne" 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="ActivityTwo" android:label="ActivityTwo" > </activity> </application>
</manifest>
import android.app.Activity; import android.content.Intent; import android.os.Bundle; import android.view.View; import android.widget.Toast;
public class ActivityOne extends Activity { private static final int REQUEST_CODE = 10;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); }
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); }
@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(); } } } } package de.vogella.android.intent.explicit;
import android.app.Activity;
@Override
public void onCreate(Bundle bundle) { super.onCreate(bundle); setContentView(R.layout.second); Bundle extras = getIntent().getExtras(); if (extras == null) { return; } String value1 = extras.getString("Value1"); String value2 = extras.getString("Value2"); if (value1 != null && value2 != null) { EditText text1 = (EditText) findViewById(R.id.input1); EditText text2 = (EditText) findViewById(R.id.input2); text1.setText(value1); text2.setText(value2); } }
@Override
Run your application. The first will send data to the second Activity which will be shown on the user interface. If you select back on your phone, the first Activity will display a Toast with the data from the second Activity.
</resources>
</GridLayout>
To be able to use certain intents you need to register then for your application. Maintain the following AndroidManifest.xml.
<uses-permission android:name="android.permission.CALL_PRIVILEGED" > </uses-permission> <uses-permission android:name="android.permission.CALL_PHONE" > </uses-permission> <uses-permission android:name="android.permission.CAMERA" > </uses-permission> <uses-permission android:name="android.permission.READ_CONTACTS" > </uses-permission> <uses-permission android:name="android.permission.INTERNET"/>
<application android:icon="@drawable/icon" android:label="@string/app_name" > <activity android:name=".CallIntentsActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" />
</manifest>
Change your activity to the following. We will start the new intent with the method startActivityForResult() which allow us to specify a desired result code. Once the intent is finished the method onActivityResult() is called and you can perform actions based on the result of the activity.
package de.vogella.android.intent.implicit;
import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.view.View; import android.widget.ArrayAdapter; import android.widget.Spinner; import android.widget.Toast;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); spinner = (Spinner) findViewById(R.id.spinner); ArrayAdapter adapter = ArrayAdapter.createFromResource(this, R.array.intents, android.R.layout.simple_spinner_item); adapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item); spinner.setAdapter(adapter);
public void onClick(View view) { int position = spinner.getSelectedItemPosition(); Intent intent = null; switch (position) { case 0: intent = new Intent(Intent.ACTION_VIEW, Uri.parse("http://www.vogella.com")); break; case 1: intent = new Intent(Intent.ACTION_CALL, Uri.parse("tel:(+49)12345789")); break; case 2: intent = new Intent(Intent.ACTION_DIAL, Uri.parse("tel:(+49)12345789")); startActivity(intent); break; case 3: intent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:50.123,7.1434?z=19")); break; case 4: intent = new Intent(Intent.ACTION_VIEW, Uri.parse("geo:0,0?q=query")); break; case 5: intent = new Intent("android.media.action.IMAGE_CAPTURE"); break; case 6: intent = new Intent(Intent.ACTION_VIEW, Uri.parse("content://contacts/people/"));
@Override
public void onActivityResult(int requestCode, int resultCode, Intent data) { if (resultCode == Activity.RESULT_OK && requestCode == 0) { String result = data.toURI(); Toast.makeText(this, result, Toast.LENGTH_LONG); } }
If you start your application you should see an list of buttons and if you press the button, different activities should be performed. Note that you didn't specify any receiving application only the thing that should be done.
Create the Android project "de.vogella.android.intent.browserfilter" with the Activity called BrowserActivity. Register your Activity to the Intent via the Intent.Action_VIEW action and the scheme "http" via the following AndroidManifest.xml. The manifest also declares the permission to access the Internet.
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="de.vogella.android.intent.browserfilter" android:versionCode="1" android:versionName="1.0" >
<application android:icon="@drawable/icon" android:label="@string/app_name" > <activity android:name=".BrowserActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.VIEW" />
</manifest>
Install your application. If you now trigger an Intent to open an URL your should be able to select your own component. You can for example trigger this Intent via the example from the implicit tutorials.
package de.vogella.android.intent.browserfilter;
import android.app.Activity; import android.content.Intent; import android.net.Uri; import android.os.Bundle; import android.os.StrictMode; import android.widget.TextView;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState);
// To keep this example simple, we allow network access // in the user interface thread
StrictMode.ThreadPolicy policy = new StrictMode.ThreadPolicy.Builder() .permitAll().build(); StrictMode.setThreadPolicy(policy);
} }
If you select you component the HTML code should be loaded into your text view.
</LinearLayout>
import android.app.Activity; import android.content.Intent; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.os.Bundle; import android.view.View; import android.widget.ImageView;
public class ImagePickActivity extends Activity { private static final int REQUEST_CODE = 1; private Bitmap bitmap; private ImageView imageView;
@Override
public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); imageView = (ImageView) findViewById(R.id.result); }
public void pickImage(View View) { Intent intent = new Intent(); intent.setType("image/*"); intent.setAction(Intent.ACTION_GET_CONTENT); intent.addCategory(Intent.CATEGORY_OPENABLE); startActivityForResult(intent, REQUEST_CODE); }
@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) { InputStream stream = null; if (requestCode == REQUEST_CODE && resultCode == Activity.RESULT_OK) try {
imageView.setImageBitmap(bitmap); } catch (FileNotFoundException e) { e.printStackTrace(); } finally { if (stream != null) try { stream.close(); } catch (IOException e) { e.printStackTrace(); } } } }
If you run this application you can select an Image from your Image library on your Android phone and assign it to your ImageView.