在很多情况下,一个应用程序包含了很多Activity,这多Activity之间的交互都是通过
intent进行交互的,如从这个界面跳转到下一个界面,或者界面之间的数据交互
在不同的APP之间,Android也提供了很好的机制给我们用户数据交互
同样也是 intent,只是叫法不一样了
Activity之间的交互是叫做 explicit Intent(明确的意图) ,
现在不同的APP之间叫做 implicit intent(含蓄的意图);
explicit Intent的用法:
A调用B,在A中定义:
Intent intent = new Intent(a_Activity.this,b_Activity.class );
StartActivity(intent );
在APP之间交互:
一、使用URI(应用程序之间的定位符)来进行数据交互
如:
显示网页:
Uri uri = Uri.parse("http://www.google.com");
Intent it = new Intent(Intent.ACTION_VIEW,uri);
startActivity(it);
显示地图:
Uri uri = Uri.parse("geo:38.899533,-77.036476");
Intent it = new Intent(Intent.Action_VIEW,uri);
startActivity(it);
二、添加额外的数据进行交互,你可以绑定你想要的任意类型的数据到extra data,使用的各种 putExtra()方法
如下所示,你可以使用URI,绑定额外的数据,如果不适用URI,必须使用 setType()指定你所绑定到Intent的数据是什么类型的;
- Send an email with an attachment:
Intent emailIntent = new Intent(Intent.ACTION_SEND);
// The intent does not have a URI, so declare the "text/plain" MIME type
emailIntent.setType(HTTP.PLAIN_TEXT_TYPE);
emailIntent.putExtra(Intent.EXTRA_EMAIL, new String[] {"jon@example.com"}); // recipients
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"));
// You can also attach multiple items by passing an ArrayList of Uris
- Create a calendar event:
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");
确定有一个APP接收你的intent:
如果你发了一个intent,设备上没有任何一个APP可以接收,并回应你去处理Intent,那么你的APP将会 Crash
为了确认能够知道,是否有APP响应你的Intent,Android提供了一个接口
,调用这个接口即可返回一个list,如果这个list不为空,就可以放心的去发送Intent了,如下例子说明:
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(intent, 0);
boolean isIntentSafe = activities.size() > 0;
使用Intent启动Activity
startActivity(intent);
下面有个例子说明,怎么使用Intent去访问 map,并且检查了是否有APP存在去处理intent
// Build the intent
Uri location = Uri.parse("geo:0,0?q=1600+Amphitheatre+Parkway,+Mountain+View,+California");
Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
// Verify it resolves
PackageManager packageManager = getPackageManager();
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;
// Start an activity if it's safe
if (isIntentSafe) {
startActivity(mapIntent);
}
显示APP让用户选择:
很多情况下,我们发送的Intent,可能不止一个APP响应,比如:你要分享一些照片在社交网站,可能手机上就有
很多社交的APP,新浪,QQ,微信等等,因此我们需要做一下处理,让用户自己选择用哪个APP,如下图所示
下面的代码展示了怎么 创建 chooser
Intent intent = new Intent(Intent.ACTION_SEND);
...
// Always use string resources for UI text.
// This says something like "Share this photo with"
String title = getResources().getString(R.string.chooser_title);
// Create intent to show chooser
Intent chooser = Intent.createChooser(intent, title);
// Verify the intent will resolve to at least one activity
if (intent.resolveActivity(getPackageManager()) != null) {
startActivity(chooser);
}
另一种启动另外的APP的方式
除了上面讲到的 startActivity()方法之外,还有一个方法可以启动另外的APP
并且能够获取APP给的返回结果,这种方法也是非常常见的
如,我们要调用相机去拍照,拍完照后,想要得到拍的照片;或者是调用联系人APP找某个联系人的联系方式,也需要返回结果的
这种方法就是 startActivityForResult() ,使用 startActivityForResult() 函数时,既可以使用 implicit Intent,又可以使用 explicit Intent
startActivityForResult()的用法和 StartActivity的用法基本差不多,
但是 startActivityForResult()的使用需要传递一个 整型参数 request code 表明你想要获取什么样的结果
我们的Activity通过一个回调函数 onActivityResult() 获取返回的结果
下面一个例子是,如何去调用联系人APP选择一个联系人,并获取返回的结果:
static final int PICK_CONTACT_REQUEST = 1; // The request code
...
private void pickContact() {
Intent pickContactIntent = new Intent(Intent.ACTION_PICK, Uri.parse("content://contacts"));
pickContactIntent.setType(Phone.CONTENT_TYPE); // Show user only contacts w/ phone numbers
startActivityForResult(pickContactIntent, PICK_CONTACT_REQUEST);
}
当用户操作完成之后,系统会自动调用我们Activity的 onActivityResult();
因此我们需要重写这个函数:
这个方法会返回三个参数:
@1: request code,即传给APP的code
@2:获取的结果是否成功, RESULT_OK表明获取成功, RESULT_CANCELED 表明获取失败
@3:返回的结果数据,由intent携带
因此为了能够正确的去得到我们想要的结果,需要对这个intent包含的数据格式很了解,才能将数据解析出来
比如:联系人APP,返回的就是Content URI表明选择的联系人,而Camera返回的就是一个bitmap格式的数据,
以下的代码说明了怎么获取联系认的电话号码,并不做深入的了解,因为要想深入了解需要去了解 content providers
</pre><pre name="code" class="html">@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
// Check which request it is that we're responding to
if (requestCode == PICK_CONTACT_REQUEST) {
// Make sure the request was successful
if (resultCode == RESULT_OK) {
// Get the URI that points to the selected contact
Uri contactUri = data.getData();
// We only need the NUMBER column, because there will be only one row in the result
String[] projection = {Phone.NUMBER};
// Perform the query on the contact to get the NUMBER column
// We don't need a selection or sort order (there's only one result for the given URI)
// CAUTION: The query() method should be called from a separate thread to avoid blocking
// your app's UI thread. (For simplicity of the sample, this code doesn't do that.)
// Consider using CursorLoader to perform the query.
Cursor cursor = getContentResolver()
.query(contactUri, projection, null, null, null);
cursor.moveToFirst();
// Retrieve the phone number from the NUMBER column
int column = cursor.getColumnIndex(Phone.NUMBER);
String number = cursor.getString(column);
// Do something with the phone number...
}
}
}
这里需要注意的是: query()查询的方法,最好另起一个线程去完成,不要在UI线程里做这个操作,因为他很有可能会阻塞UI线程