(八)Sharing Simple Data简单的数据共享

来源:互联网 发布:诺贝尔经济学奖知乎 编辑:程序博客网 时间:2024/06/02 04:44

本文首次发表于依鹏csdn博客,转载请注明出处:http://blog.csdn.net/m0_37240709/article/details/78034326


Sharing Simple Data简单的数据共享


One of the great things about Android applications is their ability to communicate and integrate with each other. Why reinvent functionality that isn't core to your application when it already exists in another application?

Android应用程序的一个伟大之处是它们能够相互通信和集成。为什么在另一个应用程序中已经存在一种功能时,重建这个功能不是你的应用的核心呢?

This class covers some common ways you can send and receive simple data between applications using Intent APIs and the ActionProvider object.

这节课包含了一些常用的方法,您可以使用Intent APIs和ActionProvider对象在应用程序之间发送和接收简单的数据。


1、Sending Simple Data to Other Apps向其他应用发送简单数据

When you construct an intent, you must specify the action you want the intent to "trigger." Android defines several actions, including ACTION_SEND which, as you can probably guess, indicates that the intent is sending data from one activity to another, even across process boundaries. To send data to another activity, all you need to do is specify the data and its type, the system will identify compatible receiving activities and display them to the user (if there are multiple options) or immediately start the activity (if there is only one option). Similarly, you can advertise the data types that your activities support receiving from other applications by specifying them in your manifest.

当您构造一个意图时,您必须指定触发意图的动作。Android定义了几个动作,包括ACTION_SEND,你可能猜到了,它表明意图是将数据从一个活动发送到另一个活动,甚至跨越进程边界。要将数据发送到另一个活动,您所需要做的就是指定数据及其类型,系统将识别共存的所有接收方activity,并将它们显示给用户(如果有多个选项)或立即启动该活动(如果只有一个选项)。类似地,你可以通过在清单文件中指定的方式,公布你的活动支持的来自其他应用数据的类型。

Sending and receiving data between applications with intents is most commonly used for social sharing of content. Intents allow users to share information quickly and easily, using their favorite applications.

在应用程序之间发送和接收数据是最常用的社交内容共享。意图允许用户使用他们最喜欢的应用程序快速、轻松地共享信息。

Note: The best way to add a share action item to an ActionBar is to use ShareActionProvider, which became available in API level 14. ShareActionProvider is discussed in the lesson about Adding an Easy Share Action.

注意:向ActionBar添加共享操作项的最佳方法是使用ShareActionProvider,它在API级别14中出现的。在关于添加一个简单的共享操作的课程中,我们讨论了ShareActionProvider。


1.1、Send Text Content发送文本内容

The most straightforward and common use of the ACTION_SEND action is sending text content from one activity to another. For example, the built-in Browser app can share the URL of the currently-displayed page as text with any application. This is useful for sharing an article or website with friends via email or social networking. Here is the code to implement this type of sharing:

ACTION_SEND操作最直接、最常见的用法是将文本内容从一个活动发送到另一个活动。例如,内置的浏览器应用程序可以将当前显示的页面的URL作为文本与任何应用程序共享。这对于通过电子邮件或社交网络与朋友分享文章或网站是很有用的。下面是实现这类共享的代码:

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);

If there's an installed application with a filter that matches ACTION_SEND and MIME type text/plain, the Android system will run it; if more than one application matches, the system displays a disambiguation dialog (a "chooser") that allows the user to choose an app.

如果有一个已安装的应用程序带有一个匹配ACTION_SEND和MIME类型为text/plain的过滤器,那么Android系统将运行它;如果有多个应用程序匹配,系统将显示一个消除歧义对话框(一个“选择器”),允许用户选择一个应用程序。

However, if you call Intent.createChooser(), passing it your Intent object, it returns a version of your intent that will always display the chooser. This has some advantages:

但是,如果您调用Intent.createChooser(),将它传递给您的意图对象,它将返回您的意图的一个版本,该版本将始终显示选择器。这有一些优点:

  • Even if the user has previously selected a default action for this intent, the chooser will still be displayed. 即使用户已经为这个意图选择了一个默认的操作,仍然会显示选择器。
  • If no applications match, Android displays a system message. 如果没有应用程序匹配,Android会显示系统消息。
  • You can specify a title for the chooser dialog. 您可以为选择器对话框指定一个标题。

Here's the updated code:

这是更新后的代码:

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)));

The resulting dialog is shown in figure 1.

结果对话框如图1所示。

Figure 1. Screenshot of ACTION_SEND intent chooser on a handset.

图1所示。在手机上显示动作发送意图的截图。

Optionally, you can set some standard extras for the intent: EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC, EXTRA_SUBJECT. If the receiving application is not designed to use them, it simply ignores them.

另外,你还可以给intent设置一些标准的附加功能,如: EXTRA_EMAIL, EXTRA_CC, EXTRA_BCC, EXTRA_SUBJECT。如果接收方应用程序没有被设计用来使用它们,那么就会简单的忽略它们。

Note: Some e-mail applications, such as Gmail, expect a String[] for extras like EXTRA_EMAIL and EXTRA_CC, use putExtra(String, String[]) to add these to your intent.

注意:一些电子邮件应用程序,如Gmail,期望有字符串数组作为附加部分,如EXTRA_EMAIL和EXTRA_CC,使用putExtra(String, String[])方法将其添加到你的意图。


1.2、Send Binary Content发送二进制内容

Binary data is shared using the ACTION_SEND action combined with setting the appropriate MIME type and placing the URI to the data in an extra named EXTRA_STREAM. This is commonly used to share an image but can be used to share any type of binary content:

使用ACTION_SEND操作和设置适当的MIME类型,并将URI放置在命名为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)));

Note the following:

请注意以下几点:

  • You can use a MIME type of "*/*", but this will only match activities that are able to handle generic data streams. 您可以使用MIME类型“*/*”,但是这只会匹配能够处理通用数据流的活动。
  • The receiving application needs permission to access the data the Uri points to. The recommended ways to do this are: 接收应用程序需要权限去访问Uri所指向的数据。推荐的方法是:
    • Store the data in your own ContentProvider, making sure that other apps have the correct permission to access your provider. The preferred mechanism for providing access is to use per-URI permissions which are temporary and only grant access to the receiving application. An easy way to create a ContentProvider like this is to use the FileProvider helper class. 将数据存储在您自己的ContentProvider中,确保其他应用程序有正确的权限访问您的提供者。提供访问的首选机制是使用每个uri的权限,这些权限是临时的,并且只允许访问接收应用程序。创建这样一个ContentProvider的简单方法是使用FileProvider助手类。
    • Use the system MediaStore. The MediaStore is primarily aimed at video, audio and image MIME types, however beginning with Android 3.0 (API level 11) it can also store non-media types (see MediaStore.Files for more info). Files can be inserted into the MediaStore using scanFile() after which a content:// style Uri suitable for sharing is passed to the provided onScanCompleted() callback. Note that once added to the system MediaStore the content is accessible to any app on the device. 使用系统MediaStore。MediaStore主要针对的是视频、音频和图像MIME类型,不过从Android 3.0(API级别11)开始,它还可以存储非媒体类型(更多信息见MediaStore.Files)。文件可以使用scanFile()插入到MediaStore中,在一个内容之后,://类型适合共享的Uri传递给onScanCompleted()回调。注意,一旦添加到系统MediaStore,该设备上的任何应用都可以访问内容。


1.3、Send Multiple Pieces of Content发送多条内容

To share multiple pieces of content, use the ACTION_SEND_MULTIPLE action together with a list of URIs pointing to the content. The MIME type varies according to the mix of content you're sharing. For example, if you share 3 JPEG images, the type is still "image/jpeg". For a mixture of image types, it should be "image/*" to match an activity that handles any type of image. You should only use "*/*" if you're sharing out a wide variety of types. As previously stated, it's up to the receiving application to parse and process your data. Here's an example:

要共享多个内容,可以使用ACTION_SEND_MULTIPLE动作,同时使用指向内容的uri列表。MIME类型根据您共享的内容的混合而有所不同。例如,如果您共享3个JPEG图像,那么该类型仍然是“image/jpeg”。对于图像类型的混合,应该是“image/*”来匹配处理任何类型图像的活动。如果你在分享各种各样的类型,你应该只使用“*/*”。如前所述,应由接收应用程序来解析和处理您的数据。这里有一个例子:

ArrayList<Uri> imageUris = new ArrayList<Uri>();imageUris.add(imageUri1); // Add your image URIs hereimageUris.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.."));

As before, make sure the provided URIs point to data that a receiving application can access.

与前面一样,确保所提供的uri指向接收应用程序能够访问的数据。


2、Receiving Simple Data from Other Apps接收来自其他应用程序的简单数据

Just as your application can send data to other applications, so too can it easily receive data from applications. Think about how users interact with your application, and what data types you want to receive from other applications. For example, a social networking application would likely be interested in receiving text content, like an interesting web URL, from another app. The Google+ Android application accepts both text and single or multiple images. With this app, a user can easily start a new Google+ post with photos from the Android Gallery app.

正如您的应用程序可以向其他应用程序发送数据一样,它也可以很容易地从应用程序接收数据。考虑用户如何与应用程序交互,以及您希望从其他应用程序接收哪些数据类型。例如,一个社交网络应用程序可能会对从另一个应用程序接收文本内容感兴趣,比如一个有趣的web URL,Google+Android应用程序同时接受文本和单个或多个图像。有了这款应用,用户就可以轻松地在Google+上使用Android相册应用的照片。


2.1、Update Your Manifest更新清单文件

Intent filters inform the system what intents an application component is willing to accept. Similar to how you constructed an intent with action ACTION_SEND in the Sending Simple Data to Other Apps lesson, you create intent filters in order to be able to receive intents with this action. You define an intent filter in your manifest, using the <intent-filter> element. For example, if your application handles receiving text content, a single image of any type, or multiple images of any type, your manifest would look like:

意图过滤器通知系统,应用组件愿意接受什么意图。类似于在“发送简单数据发送给其他应用程序”课程中所讲的,如何使用ACTION_SEND动作来创建意图,您创建意图过滤器,就是为了能够通过该活动接收意图。您可以使用<intent-filter>元素在清单中定义一个意图过滤器。例如,如果您的应用程序处理接收文本内容、任何类型的单一图像或任何类型的多个图像,您的清单将会是这样的:

<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>

Note: For more information on intent filters and intent resolution please read Intents and Intent Filters

注意:对于意图过滤器和意图解析的更多信息,请阅读意图和意图过滤器

When another application tries to share any of these things by constructing an intent and passing it to startActivity(), your application will be listed as an option in the intent chooser. If the user selects your application, the corresponding activity (.ui.MyActivity in the example above) will be started. It is then up to you to handle the content appropriately within your code and UI.

当另一个应用程序试图通过构造一个意图并将其传递给startActivity()来共享这些内容时,您的应用程序将在意图选择器中被列为一个选项。如果用户选择您的应用程序,相应的活动(上面的例子中的.ui.MyActivity)将会启动。然后由您负责在代码和UI中适当地处理内容。


2.2、Handle the Incoming Content处理传入的内容

To handle the content delivered by an Intent, start by calling getIntent() to get Intent object. Once you have the object, you can examine its contents to determine what to do next. Keep in mind that if this activity can be started from other parts of the system, such as the launcher, then you will need to take this into consideration when examining the intent.

为了处理由意图传递的内容,首先调用getIntent()来获取意图对象。一旦您拥有了对象,您就可以检查它的内容,以确定下一步要做什么。请记住,如果这个活动可以从系统的其他部分开始,比如启动器,那么在检查意图时,您需要考虑这个问题。

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    }}

Caution: Take extra care to check the incoming data, you never know what some other application may send you. For example, the wrong MIME type might be set, or the image being sent might be extremely large. Also, remember to process binary data in a separate thread rather than the main ("UI") thread.

注意:要格外小心地检查输入的数据,你永远不知道其他应用程序可能会给你发送什么信息。例如,可能设置错误的MIME类型,或者发送的图像可能非常大。另外,请记住在一个单独的线程中处理二进制数据,而不是主线程(UI线程)。

Updating the UI can be as simple as populating an EditText, or it can be more complicated like applying an interesting photo filter to an image. It's really specific to your application what happens next.

更新UI可以像填充EditText一样简单,也可以更复杂一些,比如将一个有趣的照片过滤器应用到图像上。这对你的应用程序来说是非常具体的,接下来会发生什么。


3、Adding an Easy Share Action添加一个简单的共享活动

Implementing an effective and user friendly share action in your ActionBar is made even easier with the introduction of ActionProvider in Android 4.0 (API Level 14). An ActionProvider, once attached to a menu item in the action bar, handles both the appearance and behavior of that item. In the case of ShareActionProvider, you provide a share intent and it does the rest.

通过在Android 4.0中引入ActionProvider(API级别14),在ActionBar中实现有效的和用户友好的共享操作变得更加容易。ActionProvider一旦连接到动作栏中的菜单项,就会处理该条目的外观和行为。对于ShareActionProvider,您提供一个共享意图,它将完成了其余的工作。

Note: ShareActionProvider is available starting with API Level 14 and higher.

注意:从API级别14和更高的API开始,可以使用ShareActionProvider。


3.1、Update Menu Declarations更新菜单声明

To get started with ShareActionProviders, define the android:actionProviderClass attribute for the corresponding <item> in your menu resource file:

以ShareActionProviders开始, 在你的菜单资源文件对应的< 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>

This delegates responsibility for the item's appearance and function to ShareActionProvider. However, you will need to tell the provider what you would like to share.

这将把项目的界面和功能委托给ShareActionProvider。但是,您需要告诉提供者您想要共享的内容。


3.2、Set the Share Intent设置共享意图

In order for ShareActionProvider to function, you must provide it a share intent. This share intent should be the same as described in the Sending Simple Data to Other Apps lesson, with action ACTION_SEND and additional data set via extras like EXTRA_TEXT and EXTRA_STREAM. To assign a share intent, first find the corresponding MenuItem while inflating your menu resource in your Activity or Fragment. Next, call MenuItem.getActionProvider() to retrieve an instance of ShareActionProvider. Use setShareIntent() to update the share intent associated with that action item. Here's an example:

为了让ShareActionProvider发挥作用,您必须为它提供一个共享的意图。这一共享意图应该与“向其他应用程序发送的简单数据”课程中的一样,通过ACTION_SEND动作和附加的数据设置,如EXTRA_TEXT和EXTRA_STREAM。为了分配一个共享意图,首先在Activity或Fragment中增加菜单资源时,首先找到相应的MenuItem。接下来,调用MenuItem.getActionProvider()来检索ShareActionProvider的实例。使用setShareIntent()来更新与该操作项相关联的共享意图。这里有一个例子:

private ShareActionProvider mShareActionProvider;...@Overridepublic 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 intentprivate void setShareIntent(Intent shareIntent) {    if (mShareActionProvider != null) {        mShareActionProvider.setShareIntent(shareIntent);    }}

You may only need to set the share intent once during the creation of your menus, or you may want to set it and then update it as the UI changes. For example, when you view photos full screen in the Gallery app, the sharing intent changes as you flip between photos.

您可能只需要在创建菜单时设置共享意图,或者您可能想设置它,然后在UI更改时更新它。例如,你在相册应用中全屏查看照片,当你在照片之间切换时,分享意图会发生变化。

For further discussion about the ShareActionProvider object, see Action Views and Action Providers.

有关ShareActionProvider对象的进一步讨论,请参阅动作视图和动作提供者。

原创粉丝点击