第一章 分享简单的数据
android程序一件很不错的事情就是可以和不同的程序进行数据共享。为什么要构造不属于程序的核心呢?
这章主要讲述你可以在不同的程序间通过Intent和ActionProvider发送和接收数据。
1. 向其它程序发送简单的数据
当你创建一个intent的时候,你应该指定你的intent将要触发的操作。android定义了许多的动作,其中包括ACTION_SEND,就像你猜的那样,表明这个intent可以向其它的activity发送数据,甚至是向其它程序发送数据。向其它的activity发送数据很简单,所有你需要做的就是指定数据,和它的类型,系统会识别出可以接收处理的程序,然后把这些程序呈现给用户供用户选择,如果只有一个程序的话,系统就会直接打开那个程序。同样的,你可以在manifest中指定相关的内容,接收其它的activity向你发送的数据。
通过intent在不同的程序间发送数据是最常用的方式,intent可以快速地传递用户的数据简单地向用户最喜欢的app分享数据。
注意最佳的分享数据的方式在在ActionBar中使用ShareActionProvider。
2. 发送文本消息
这直接和普通的使用ACTION_SEND方式是从一个activity向另一个activity发送文本内容。比如,内置的浏览器可以向其它的任何程序分享现在网址所显示的网页。
这是非常有用的,比如通过email或者是社交网络分享一片文章或者网站,下面是一个实现的例子
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);
如果这里有一个app它的过滤器中含有ACTION_SEND和mine类型是text/plain,安卓系统就会运行它。如果这里多余一个app可供选择,那么系统就会把这些app给用户选择。
但是,如果你调用Intent.createChooser(),传递你的Intent对象,你总是会显示选择器,这样做有以下的好处:
不管用户之前有没有设置默认的程序,它都会把选择器给用户选择。
如果没有程序可供选择,那么Android系统就会提示一些系统信息。
你可以制定选择器的标题。
下面是更新的代码
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)));
可供选择的,下面是一个标准的intent携带信息:EXTRA_EMAIL
,EXTRA_CC
,EXTRA_BCC
,EXTRA_SUBJECT
。 如果接收程序没有去使用他们,那么它们会忽略这些信息。
注意一些邮箱app,比如gmail,会从intent的extra的EXTRA_EMAIL, EXTRA_CC, 中得到字符串数组。
3. 发送二进制内容
二进制数据通常使用ACTION和MINE结合的方式向其它的activity发送,会把uri数据放置在额外内容中,EXTRA命名为EXTRA_STREAM,下面是一个分享图片的最常见的使用,但是可以用来分享其它的任何二进制内容。
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)));
需要注意下面的内容:
你可以使用"*/*"为mime类型,但是这只会匹配普通的数据资源。
接收的对象需要权限去获取指定的Uri内容,建议的做法是如下:
将你要分享的数据存储在你自己的ContentProvider中,确保其它的程序有权限获取你的provider.通常的机制是通过per_URI permission,它会确保接收数据的程序有暂时的访问权限。一个简单的方法就是使用FileProvider帮组类创建一个ContentProvider实例。
使用系统MediaStore,这个MediaStore主要是针对视频,音频图片文件。文件可以通过MediaStore的scanFile函数,里面传递content://的Uri进行分享。
4. 发送很多的内容
为了分享更多的数据,可以使用ACTION_SEND_MULTIPLE动作和一系列的只向这个内容的uri,这个MIME类型可以各种各样。比如你分享3张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.."));
第二章 从其它的程序中接收数据
就像你可以给其它啊程序发送数据那样,你也可以接收其它程序的数据。想象别的程序怎么和你的程序打交道,你想从别的程序中的到什么样的数据类型。比如,一个社交网络程序会对一个文本雷人,一个有趣的网址,感兴趣。Google+会接收文本,单张图片或者多张图片。使用这个app,用户很容易就可以从gallery app中开启一个新的Google+程序。
1. 更新你的Manifest文件
intent过滤器告诉系统它能过接收什么样的intent。像之前的文章你构建intent那样,你可以创建intent 过滤器,这样就可以接收其它程序的动作。你使用<intent-filter>元素在你的manifest文件中定义intent filter文件。比如,如果你的程序可以接收处理文本内容,或者其它的图片内容,那么你的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>
当其它的程序要分享那些内容构建intent并且通过startActivity启动的时候,你的程序就会被intent 选择器列出来供用户选择。如果用户选择你的程序,那么对应的(.ui.MyActivity)Activity就会被启动,然后你需要写合适的程序处理这些内容。
2. 处理发送过来的intent
为了处理通过Intent发送过来的内容,你可以通过getIntent获取一个intent对象。一旦你有了这个对象,你可以检查它的内容,然后在决定下一步怎么做。记住入股这个Activity可以被别的程序启动,你需要把intent考虑进去。
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
}
}
注意:检查传送过来的数据的时候需要格外的小心,你永远不知道别数据给你传送了什么。比如错误的mine类型,或者是超大的文件。记住不要在UI线程上做这些事情,应该单独开一个线程处理这些数据。
更新一个ui可以很简单就像弹出一个编辑框,也可以很复杂就像是处理一个有趣的照片,这些都是取决于你的程序想怎么做。
第三章 增加一个简单的分享动作
在你的ActionBar实现一个有效的用户友好的分享按键。一个AnctionProvider, 一旦添加到你的列表中,可以对他进行外观和行为的改造。
在ShareActionProvider中,你提供一个分享的intent,r然后这个分享做了其余的事情。
1. 更新菜单申明
开启一个ShareActionProviders,你需要定于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>
你还要高数provider你需要分享什么东西。
2. 设置分享intent
为了使ShareActionProvider工作,你必须提供一个share intent, 这个分享intent和你之前文章中描述的一样,有ACTION_SEND和其它的一些数据。为了分享intent,你首先需要找到Activity或者fragment对应的MenuItem,接下来通过MenuItem.getActionProvider()接收到一个ShareActionProvider实例,然后使用setShareIntent来根性你的分享intent,下面是一个示例
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);
}
}
你可以在很多时候更新你的内容,比如你向设置信息,或者更新ui,比如你想在gallery app中全屏查看照片,你就可以通过share intent 跳转到那个界面上。
更多的信息请参考ShareActionProvider 对象。