传送门 ☞ 轮子的专栏 ☞ 转载请注明 ☞ http://blog.csdn.net/leverage_1229
一个Android应用程序通常有几个activities。每个act显示一个用户接口允许用户执行一个指定的任务。用户从一个act到另一个act,你的App必须使用一个Intent对象来定义你App想做些什么事。当你通过一个Intent调用startActivity()方法时,系统会使用Intent来鉴定和启动合适的App组件。一个Intent可以明确的启动一个特定的组件(如一个特定的act实例)或隐式启动任何可以处理预定动作的组件,本章我们将讲述怎么使用Intent来执行与其他Apps的一些交互,例如启动另一个App,从那个App接收结果。并使你的应用程序能够响应来自其他App的intents。
Uri number = Uri.parse("tel:5551234"); Intent callIntent = new Intent(Intent.ACTION_DIAL, number);当你的app通过startActivity()调用intent时,电话app根据给定的电话号码发起呼叫。
// 基于地址的地图点 Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"); // 或基于经纬度的地图点 // Uri location = Uri.parse("geo:37.422219,-122.08364?z=14"); // z参数表示缩放级别 Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);查看一个web页面:
Uri webpage = Uri.parse("http://www.android.com"); Intent webIntent = new Intent(Intent.ACTION_VIEW, webpage);其他种类的隐式intents需要”extra”数据来提供不同的数据类型,如一个字符串。你能使用putExtra()方法来添加一个或更多extra 数据。默认的,系统通过基于Uri的intent来确定适当的MIME(Multipurpose Internet Mail Extensions)类型。如果你在intent中不包含一个Uri,你应该使用setType()来指定intent相关联的数据类型。设置MIME类型来进一步指定activities将要接收的intent类型。
Intent emailIntent = new Intent(Intent.ACTION_SEND); //没有Uri的intent,所以需要声明”text/plain”的MIME类型 emailIntent.setType(HTTP.PLAIN_TEXT_TYPE); emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"[email protected]"}); // 收件人 emailIntent.putExtra(Intent.EXTRA_SUBJECT, "Email subject"); emailIntent.putExtra(Intent.EXTRA_TEXT, "Email message text"); emailIntent.putExtra(Intent.EXTRA_STREAM, Uri.parse("content://path/to/email/attachment"));创建一个日历事件:
Intent calendarIntent = new Intent(Intent.ACTION_INSERT, Events.CONTENT_URI); Calendar beginTime = Calendar.getInstance().set(2012, 0, 19, 7, 30); Calendar endTime = Calendar.getInstance().set(2012, 0, 19, 10, 30); calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_BEGIN_TIME, beginTime.getTimeInMillis()); calendarIntent.putExtra(CalendarContract.EXTRA_EVENT_END_TIME, endTime.getTimeInMillis()); calendarIntent.putExtra(Events.TITLE, "Ninja class"); calendarIntent.putExtra(Events.EVENT_LOCATION, "Secret dojo");注意: 对于日历事件的intent只在API Level或更高版本下才支持。
PackageManager packageManager = getPackageManager(); List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0); boolean isIntentSafe = activities.size() > 0;如isIntentSafe为true,那么表示至少有一个app能响应我们的intent。如果false,表示没有一个app能处理这个intent。
// 构建intent Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California"); Intent mapIntent = new Intent(Intent.ACTION_VIEW, location); // 验证上面的mapIntent PackageManager packageManager = getPackageManager(); List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0); boolean isIntentSafe = activities.size() > 0; // 如果它是安全的就启动这个activity if (isIntentSafe) { startActivity(mapIntent); }
Intent intent = new Intent(Intent.ACTION_SEND); ... // 用于标题的文本资源例如"Share this photo with" String title = getResources().getText(R.string.chooser_title); // 创建并启动chooser Intent chooser = Intent.createChooser(intent, title); startActivity(chooser);
static final int PICK_CONTACT_REQUEST = 1; // request code ... private void pickContact() { Intent pickContactIntent = new Intent(Intent.ACTION_PICK, new Uri("content://contacts")); pickContactIntent.setType(Phone.CONTENT_TYPE); startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST); }
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { // 检查响应的请求 if (requestCode == PICK_CONTACT_REQUEST) { // 确保请求是成功的 if (resultCode == RESULT_OK) { // Do something... } } }为了成功地处理结果,你必须明白,intent结果的格式将是什么。例如,People app(早些版本叫Contacts app)始终用content URI返回结果并识别被选择的联系人,Camera app在返回一个Bitmap。
@Override protected void onActivityResult(int requestCode, int resultCode, Intent data) { //检查响应的请求 if (requestCode == PICK_CONTACT_REQUEST) { //确保请求是成功的 if (resultCode == RESULT_OK) { // 获得指向选定联系人的URI Uri contactUri = data.getData(); //我们只需要号码(NUMBER)列 String[] projection = {Phone.NUMBER}; // 在联系人中执行查询,获得NUMBER column // 我们不需要挑选或排序 // 提示: query()方法应该在单独的线程执行,避免阻塞UI线程 // 考虑使用CursorLoader 执行查询 Cursor cursor = getContentResolver() .query(contactUri, projection, null, null, null); cursor.moveToFirst(); // 从NUMBER column中检索电话号码 int column = cursor.getColumnIndex(Phone.NUMBER); String number = cursor.getString(column); // 使用电话号码做些事情 } } }注意:Android 2.3 (API level 9)以前,在Contacts Provider执行一个查询需要申明READ_CONTACTS权限,虽然在2.3开始有一个临时的权限可以让你去读取Contacts Provider,但依旧不能查询。所以不管什么版本我们都申明READ_CONTACTS权限即可。
<activity android:name="ShareActivity"> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="text/plain"/> <data android:mimeType="image/*"/> </intent-filter> </activity>每一个传入的intent只有一个动作和一种数据类型,但声明多个<data>,<action>,<category>也是OK的,如果动作和数据类型相互排斥的话,你就应该分开它们。加入你的activity处理文本和图像,并且使用ACTION_SEND和ACTION_SENDTO intents。这样就是错误的,在这种情况下你应该使用两个<intent-filter>来分开它们。因为SENDTO必须使用Uri数据,并且需要sms和smsto的scheme。
<activity android:name="ShareActivity"> <!—为发送文本过滤; 接收SENDTO action 使用 sms URI schemes --> <intent-filter> <action android:name="android.intent.action.SENDTO"/> <category android:name="android.intent.category.DEFAULT"/> <data android:scheme="sms" /> <data android:scheme="smsto" /> </intent-filter> <!—为发送文本或图像过滤; 接收SEND action和文本或者图像数据 --> <intent-filter> <action android:name="android.intent.action.SEND"/> <category android:name="android.intent.category.DEFAULT"/> <data android:mimeType="image/*"/> <data android:mimeType="text/plain"/> </intent-filter> </activity>为了接收隐式的intents,我们必须在<intent-filter>中定义CATEGORY_DEFAULT中,如果没声明,那么你的activity不能解决处理隐式的intents。
@Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); //获得启动activity的intent Intent intent = getIntent(); Uri data = intent.getData(); // 解决intent类型想做什么 if (intent.getType().indexOf("image/") != -1) { //处理图像数据 } else if (intent.getType().equals("text/plain")) { // 处理文本 } }
// 创建intent来传递某种结果数据 Intent result = new Intent("com.example.RESULT_ACTION", Uri.parse("content://result_uri"); setResult(Activity.RESULT_OK, result); finish();我们可以只指定result code。通常是RESULT_OK或RESULT_CANCELED。你可以添加额外的intent或者不添加。默认的result code是RESULT_CANCELED。所以如果用户在你设置result之前执行Back键,那么最初的activity收到的就是RESULT_CANCELED,这并不是我们预计的结果,这个细节请注意。