昨天我就阅读了Google Training 关于向其他应用分享简单数据的内容,但我是个小白,内容设计了ActionBar, ShareActionProvider等比较陌生的东西,我也是查了很多的资料。这次主要是学习如何分享一些简单的数据,比如向其他应用分享文本,二进制内容;接收来自其他应用的分享。
Android应用的优点之一就是不同组件的互相分享,这样可以省去反复创造一些重复,但又无关于APP核心的功能。
所以,学会如何与其他的应用交互分享,是能起到事半功倍的效果。
这次的内容分3部分:
- 向其他的应用发送简单的数据
- 接收来自其他应用的简单数据
- 添加一个简单的分享action
第一个内容:向其他的应用发送简单的数据
分享数据主要依靠Intent,我们只要在Intent中指定好分享的action类型,data类型,type类型,然后把Intent交给系统,系统会自己去寻找能和Intent中指定的类型相匹配的Activity,然后启动。如果只有一个,就马上启动满足Intent条件的Activity,否则会显示一个满足该条件的Activity的列表,然后由用户选择。
通常来说这方面的功能需求对于社交APP比较多,用户可以向他们喜欢的社交APP去分享自己感兴趣的内容。
1.1 分享文本
ACTION_SEND action最直接的分享无疑就是文本的分享了,比如说系统内置的浏览器可以把当前浏览的网址作为文本内容向其他应用分享,下面是官方给出的示例:
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(sendIntent);
如果存在符合Intent action和MIME 类型的Activity,系统会运行它,如果存在多个,会以列表形式让用户选择。这时,使用 Intent.createChooser() 方法是个更好的选择,它有几个优点:
- 即使之前用户选择了默认的APP,它也会显示选择的列表
- 如果匹配不上,还会给出系统的提示
- 你可以设置对话框的标题
官方给出了优化后的代码:
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, "This is my text to send.");
sendIntent.setType("text/plain");
startActivity(Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)));
1.2 分享二进制内容
二进制内容的分享和文本相似,也是ACTION_SEND action 搭配合适的MIME type ,唯一不同的就是 putExtra()里面要使用EXTRA_STREAM,后一个数据的URI。最常见的二进制内容分享就是图片分享了。
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType("image/jpeg");
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));
关于setType,如果只是制定了 * / *,那么这Intent只能匹配处理通常数据类型的Activity,所以我们应该根据实际需求,尽可能去详细地设置它。
1.3 分享多个内容
如果要分享多个内容,我们应该设置 ACTION_SEND_MULTIPLE action,putExtra()也应该放入多个数据,当然了MIME type也必须要根据实际的分享内容去设置。比如说分享三张jpeg格式的图片,我们可以指定它是 image/jpeg,如果是三张不同类型的图片,我们应该指定它是 image/* 。如果类型实在是多,我们再这么设置 * / *
官方给出了下面的一个示例:
ArrayList<Uri> imageUris = new ArrayList<Uri>();
imageUris.add(imageUri1); // Add your image URIs here
imageUris.add(imageUri2);
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND_MULTIPLE);
shareIntent.putParcelableArrayListExtra(Intent.EXTRA_STREAM, imageUris);
shareIntent.setType("image/*");
startActivity(Intent.createChooser(shareIntent, "Share images to.."));
第二个内容:接受来自其他APP的分享内容
这个时候你应该考虑的是,你的APP该如何语用户交互和你希望接受的数据是什么?比如社交APP会接受文本分享,然后再向用户的朋友们展示。
2.1 更新你的Manifest文件
Intent filters会告诉系统你会接受什么样的Intent,如果Intent和你的action,data,type都对得上,系统就会把这个Activity作为启动的选项。如果Activity可以接受文本分享,一张任意格式的图片分享,多种格式的图片分享,那Manifest文件应该是这样的:
<activity android:name=".ui.MyActivity" >
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
<intent-filter>
<action android:name="android.intent.action.SEND_MULTIPLE" />
<category android:name="android.intent.category.DEFAULT" />
<data android:mimeType="image/*" />
</intent-filter>
</activity>
2.2 处理接受的分享内容
要处理来自Intent的内容,我们应该先用getIntent()得到Intent对象,然后根据Intent里面的具体数据去决定下一步怎么做,如果Activity是被其他的应用启动,这一步很重要。
void onCreate (Bundle savedInstanceState) {
...
// Get intent, action and MIME type
Intent intent = getIntent();
String action = intent.getAction();
String type = intent.getType();
if (Intent.ACTION_SEND.equals(action) && type != null) {
if ("text/plain".equals(type)) {
handleSendText(intent); // Handle text being sent
} else if (type.startsWith("image/")) {
handleSendImage(intent); // Handle single image being sent
}
} else if (Intent.ACTION_SEND_MULTIPLE.equals(action) && type != null) {
if (type.startsWith("image/")) {
handleSendMultipleImages(intent); // Handle multiple images being sent
}
} else {
// Handle other intents, such as being started from the home screen
}
...
}
void handleSendText(Intent intent) {
String sharedText = intent.getStringExtra(Intent.EXTRA_TEXT);
if (sharedText != null) {
// Update UI to reflect text being shared
}
}
void handleSendImage(Intent intent) {
Uri imageUri = (Uri) intent.getParcelableExtra(Intent.EXTRA_STREAM);
if (imageUri != null) {
// Update UI to reflect image being shared
}
}
void handleSendMultipleImages(Intent intent) {
ArrayList<Uri> imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
if (imageUris != null) {
// Update UI to reflect multiple images being shared
}
}
我们应该仔细检查接收到的数据,可能Intent的MIME类型就是错误的,也可能传来的数据很大,我们应该要在后台处理,这都是不能忘记的。
第三个内容:添加一个简单的分享 action
随着在 Android4.0(API 14)ActionProvider 的引入,我么你可以很简单的完成分享。对于ActionProvider来说,它自己就能处理好Menu的外观和行为。通过使用 ShareActionProvider,我们只需要传递给它一个Intent,剩下的就不用我们操心了。
3.1 改变Menu
在Menu资源文件里相应的< item >下,定义 android:actionProviderClass 属性。
<menu xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:id="@+id/menu_item_share"
android:showAsAction="ifRoom"
android:title="Share"
android:actionProviderClass=
"android.widget.ShareActionProvider" />
...
</menu>
3.2 设置用于分享的Intent
为了让ShareActionProvider工作,你应该提供一个Intent,关于如何设置Intent,和第一部分的内容一样,设置action,putExtra(),setType()。为了去分配一个Intent,你应该在填充菜单资源的时候找对应的MenuItem,然后调用 MenuItem.getActionProvider() 获得 ShareActionProvider实例,最后调用 setShareIntent()就行啦。
private ShareActionProvider mShareActionProvider;
...
@Override
public boolean onCreateOptionsMenu(Menu menu) {
// Inflate menu resource file.
getMenuInflater().inflate(R.menu.share_menu, menu);
// Locate MenuItem with ShareActionProvider
MenuItem item = menu.findItem(R.id.menu_item_share);
// Fetch and store ShareActionProvider
mShareActionProvider = (ShareActionProvider) item.getActionProvider();
// Return true to display menu
return true;
}
// Call to update the share intent
private void setShareIntent(Intent shareIntent) {
if (mShareActionProvider != null) {
mShareActionProvider.setShareIntent(shareIntent);
}
}
好了,就这么多了