Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 691fea72 authored by Scott Main's avatar Scott Main Committed by Android Git Automerger
Browse files

am 70645e36: Docs: Add class for Sharing Content

* commit '70645e36':
  Docs: Add class for Sharing Content
parents d70c64db 70645e36
Loading
Loading
Loading
Loading
+32.4 KiB
Loading image diff...
+46 −0
Original line number Diff line number Diff line
page.title=Sharing Content

trainingnavtop=true
startpage=true
next.title=Sending Content to Other Apps
next.link=send.html

@jd:body

<div id="tb-wrapper">
<div id="tb">

<!-- Required platform, tools, add-ons, devices, knowledge, etc. -->
<h2>Dependencies and prerequisites</h2>
<ul>
  <li>Android 1.0 or higher (greater requirements where noted)</li>
  <li>Experience with <a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and
Intent Filters</a></li>
</ul>

</div>
</div>

 
<p>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?</p> 

<p>This class shows some common ways you can send and receive content between
applications using {@link android.content.Intent} APIs and the {@link
android.view.ActionProvider}.</p>


<h2>Lessons</h2>
 
<dl> 
  <dt><b><a href="send.html">Sending Content to Other Apps</a></b></dt> 
    <dd>Learn how to set up your application to be able to send text and binary data to other
applications with intents.</dd> 
 
  <dt><b><a href="receive.html">Receiving Content from Other Apps</a></b></dt> 
    <dd>Learn how to set up your application to receive text and binary data from intents.</dd> 
                                    
  <dt><b><a href="shareaction.html">Adding an Easy Share Action</a></b></dt> 
    <dd>Learn how to add a "share" action item to your action bar.</dd> 
</dl> 
+149 −0
Original line number Diff line number Diff line
page.title=Receiving Content from Other Apps
parent.title=Sharing Content
parent.link=index.html

trainingnavtop=true
previous.title=Sending Content to Other Apps
previous.link=send.html
next.title=Adding an Easy Share Action
next.link=shareaction.html

@jd:body

<div id="tb-wrapper">
<div id="tb">

<!-- table of contents -->
<h2>This lesson teaches you to</h2>
<ol>
  <li><a href="#update-manifest">Update Your Manifest</a></li>
  <li><a href="#handling-content">Handle the Incoming Content</a></li>
</ol>

<!-- other docs (NOT javadocs) -->
<h2>You should also read</h2>
<ul>
  <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and
Intent Filters</a></li>
</ul>

</div>
</div>

<p>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 
<a href="https://market.android.com/details?id=com.google.android.apps.plus">Google+ Android
application</a> 
accepts both text <em>and</em> single or multiple images. With this app, a user can easily start a 
new Google+ post with photos from the Android Gallery app.</p>


<h2 id="update-manifest">Update Your Manifest</h2>

<p>Intent filters inform the system what intents an application component is willing to accept. 
Just as you constructed an intent with action {@link android.content.Intent#ACTION_SEND} in the 
<a href="{@docRoot}training/sharing/send.html">Send Content to Other Apps Using Intents</a> 
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 
<code><a
href="{@docRoot}guide/topics/intents/intents-filters.html#ifs">&lt;intent-filter&gt;</a></code> 
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:</p>

<pre>
&lt;activity android:name=&quot;.ui.MyActivity&quot; &gt;
    &lt;intent-filter&gt;
        &lt;action android:name=&quot;android.intent.action.SEND&quot; /&gt;
        &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
        &lt;data android:mimeType=&quot;image/*&quot; /&gt;
    &lt;/intent-filter&gt;
    &lt;intent-filter&gt;
        &lt;action android:name=&quot;android.intent.action.SEND&quot; /&gt;
        &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
        &lt;data android:mimeType=&quot;text/plain&quot; /&gt;
    &lt;/intent-filter&gt;
    &lt;intent-filter&gt;
        &lt;action android:name=&quot;android.intent.action.SEND_MULTIPLE&quot; /&gt;
        &lt;category android:name=&quot;android.intent.category.DEFAULT&quot; /&gt;
        &lt;data android:mimeType=&quot;image/*&quot; /&gt;
    &lt;/intent-filter&gt;
&lt;/activity&gt;
</pre>

<p class="note"><strong>Note:</strong> For more information on intent filters and intent resolution 
please read <a href="{@docRoot}guide/topics/intents/intents-filters.html#ifs">Intents and Intent
Filters</a></p>

<p>When another application tries to share any of these things by constructing an intent and passing
it to {@link android.content.Context#startActivity(android.content.Intent) startActivity()}, your
application will be listed as an option in the intent chooser (see figure 1). If the user selects
your application, the corresponding activity (<code>.ui.MyActivity</code> in the example above) will
be started. It is then up to you to handle the content appropriately within your code and UI.</p>


<h2 id="handling-content">Handle the Incoming Content</h2>

<p>To handle the content delivered by an {@link android.content.Intent}, start by calling {@link
android.content.Intent#getIntent(String) getIntent()} 
to get {@link android.content.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.</p>

<pre>
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) &amp;&amp; type != null) {
        if (&quot;text/plain&quot;.equals(type)) {
            handleSendText(intent); // Handle text being sent
        } else if (type.startsWith(&quot;image/&quot;)) {
            handleSendImage(intent); // Handle single image being sent
        }
    } else if (Intent.ACTION_SEND_MULTIPLE.equals(action) &amp;&amp; type != null) {
        if (type.startsWith(&quot;image/&quot;)) {
            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&lt;Uri&gt; imageUris = intent.getParcelableArrayListExtra(Intent.EXTRA_STREAM);
    if (imageUris != null) {
        // Update UI to reflect multiple images being shared
    }
}
</pre>

<p class="caution"><strong>Caution:</strong> 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.</p>

<p>Updating the UI can be as simple as populating an {@link android.widget.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.</p>
+194 −0
Original line number Diff line number Diff line
page.title=Sending Content to Other Apps
parent.title=Sharing Content
parent.link=index.html

trainingnavtop=true
next.title=Receiving Content from Other Apps
next.link=receive.html

@jd:body

<div id="tb-wrapper">
<div id="tb">

<!-- table of contents -->
<h2>This lesson teaches you to</h2>
<ol>
  <li><a href="#send-text-content">Send Text Content</a></li>
  <li><a href="#send-binary-content">Send Binary Content</a></li>
  <li><a href="#send-multiple-content">Send Multiple Pieces of Content</a></li>
</ol>

<!-- other docs (NOT javadocs) -->
<h2>You should also read</h2>
<ul>
  <li><a href="{@docRoot}guide/topics/intents/intents-filters.html">Intents and
Intent Filters</a></li>
</ul>

</div>
</div>

<p>When you construct an intent, you must specify the action you want the intent to "trigger." 
Android defines several actions, including {@link android.content.Intent#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 speicify 
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.</p>

<p>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 social applications.</p>

<p><strong>Note:</strong> The best way to add a share action item to an 
{@link android.app.ActionBar} is to use {@link android.widget.ShareActionProvider}, which became 
available in API level 14. {@link android.widget.ShareActionProvider} is discussed in the lesson 
about <a href="shareaction.html">Adding an Easy Share Action</a>.</p>


<h2 id="send-text-content">Send Text Content</h2>

<div class="figure" style="width:220px">
<img src="{@docRoot}images/training/sharing/share-text-screenshot.png" alt="" id="figure1" />
<p class="img-caption">
  <strong>Figure 1.</strong> Screenshot of {@link android.content.Intent#ACTION_SEND} intent chooser
on a handset.
</p>
</div>

<p>The most straightforward and common use of the {@link android.content.Intent#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:</p>

<pre>
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, &quot;This is my text to send.&quot;);
sendIntent.setType(&quot;text/plain&quot;);
startActivity(sendIntent);
</pre>

<p>If there's an installed application with a filter that matches 
{@link android.content.Intent#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. If you call 
{@link android.content.Intent#createChooser(android.content.Intent, CharSequence)
Intent.createChooser()} 
for the intent, Android will <strong>always</strong> display the chooser. This has some
advantages:</p>

<ul>
  <li>Even if the user has previously selected a default action for this intent, the chooser will
still be displayed.</li>
  <li>If no applications match, Android displays a system message.</li>
  <li>You can specify a title for the chooser dialog.</li>
</ul>

<p>Here's the updated code:</p>

<pre>
Intent sendIntent = new Intent();
sendIntent.setAction(Intent.ACTION_SEND);
sendIntent.putExtra(Intent.EXTRA_TEXT, &quot;This is my text to send.&quot;);
sendIntent.setType(&quot;text/plain&quot;);
startActivity(<strong>Intent.createChooser(sendIntent, getResources().getText(R.string.send_to)</strong>);
</pre>

<p>The resulting dialog is shown in figure 1.</p>

<p>Optionally, you can set some standard extras for the intent: 
{@link android.content.Intent#EXTRA_EMAIL}, {@link android.content.Intent#EXTRA_CC}, 
{@link android.content.Intent#EXTRA_BCC}, {@link android.content.Intent#EXTRA_SUBJECT}. However, 
if the receiving application is not designed to use them, nothing will happen. You can use 
custom extras as well, but there's no effect unless the receiving application understands them. 
Typically, you'd use custom extras defined by the receiving application itself.</p>

<p class="note"><strong>Note:</strong> Some e-mail applications, such as Gmail, expect a 
{@link java.lang.String String[]} for extras like {@link android.content.Intent#EXTRA_EMAIL} and 
{@link android.content.Intent#EXTRA_CC}, use 
{@link android.content.Intent#putExtra(String,String[]) putExtra(String, String[])} to add these 
to your intent.</p>


<h2 id="send-binary-content">Send Binary Content</h2>

<p>Binary data is shared using the {@link android.content.Intent#ACTION_SEND} action combined with
setting the appropriate MIME type and placing the URI to the data in an extra named {@link
android.content.Intent#EXTRA_STREAM}. This is commonly used to share an image but can be used to
share any type of binary content:</p>

<pre>
Intent shareIntent = new Intent();
shareIntent.setAction(Intent.ACTION_SEND);
shareIntent.putExtra(Intent.EXTRA_STREAM, uriToImage);
shareIntent.setType(&quot;image/jpeg&quot;);
startActivity(Intent.createChooser(shareIntent, getResources().getText(R.string.send_to)));
</pre>

<p>Note the following:</p>
<ul>
  <li>You can use a MIME type of {@code "*/*"}, but this will only match activities that are able to
handle generic data streams.</li>
  <li>The receiving application needs permission to access the data the {@link android.net.Uri}
points to. There are a number of ways to handle this:
  <ul>
    <li>Write the data to a file on external/shared storage (such as the SD card), which all apps
can read. Use {@link android.net.Uri#fromFile(java.io.File) Uri.fromFile()} to create the
{@link android.net.Uri} that can be passed to the share intent. However, keep in mind that not
all applications process a {@code file://} style {@link android.net.Uri}.</li>
    <li>Write the data to a file in your own application directory using {@link
android.content.Context#openFileOutput(java.lang.String, int) openFileOutput()} with mode {@link
android.content.Context#MODE_WORLD_READABLE} after which {@link
android.content.Context#getFileStreamPath(java.lang.String) getFileStreamPath()} can be used to
return a {@link java.io.File}. As with the previous option, {@link
android.net.Uri#fromFile(java.io.File) Uri.fromFile()} will create a {@code file://} style {@link
android.net.Uri} for your share intent.</li>
    <li>Media files like images, videos and audio can be scanned and added to the system {@link
android.provider.MediaStore} using {@link
android.media.MediaScannerConnection#scanFile(android.content.Context, java.lang.String[],
java.lang.String[], android.media.MediaScannerConnection.OnScanCompletedListener) scanFile()}. The
{@link
android.media.MediaScannerConnection.OnScanCompletedListener#onScanCompleted(java.lang.String,
android.net.Uri) onScanCompleted()} callback returns a {@code content://} style {@link
android.net.Uri} suitable for including in your share intent.</li>
    <li>Images can be inserted into the system {@link android.provider.MediaStore} using {@link
android.provider.MediaStore.Images.Media#insertImage(android.content.ContentResolver,
android.graphics.Bitmap, java.lang.String, java.lang.String) insertImage()} which will return a
{@code content://} style {@link android.net.Uri} suitable for including in a share intent.</li>
    <li>Store the data in your own {@link android.content.ContentProvider}, make sure that other
apps have the correct permission to access your provider (or use <a
href="{@docRoot}guide/topics/security/security.html#uri">per-URI permissions</a>).</li>
  </ul>
  </li>
</ul>


<h2 id="send-multiple-content">Send Multiple Pieces of Content</h2>

<p>To share multiple pieces of content, use the {@link android.content.Intent#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 {@code
"image/jpeg"}. For a mixture of image types, it should be {@code "image/*"} to match an activity
that handles any type of image. You should only use {@code "*/*"} 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:</p>

<pre>
ArrayList&lt;Uri&gt; imageUris = new ArrayList&lt;Uri&gt;();
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(&quot;image/*&quot;);
startActivity(Intent.createChooser(shareIntent, &quot;Share images to..&quot;));
</pre>

<p>As before, make sure the provided {@link android.net.Uri URIs} point to data that a receiving
application can access.</p>
+115 −0
Original line number Diff line number Diff line
page.title=Adding an Easy Share Action
parent.title=Sharing Content
parent.link=index.html

trainingnavtop=true
previous.title=Receiving Content from Other Apps
previous.link=receive.html

@jd:body

<div id="tb-wrapper">
<div id="tb">

<!-- table of contents -->
<h2>This lesson teaches you to</h2>
<ol>
  <li><a href="#update-menus">Update Menu Declarations</a></li>
  <li><a href="#set-share-intent">Set the Share Intent</a></li>
</ol>

<!-- other docs (NOT javadocs) -->
<h2>You should also read</h2>
<ul>
  <li><a href="{@docRoot}guide/topics/ui/actionbar.html">Action Bar</a></li>
</ul>

</div>
</div>


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

<p class="note"><strong>Note:&nbsp;</strong> {@link android.widget.ShareActionProvider} is available
starting with API Level 14 and higher.</p>


<div class="figure" style="width:200px">
<img src="{@docRoot}images/ui/actionbar-shareaction.png" alt="" id="figure1" />
<p class="img-caption">
  <strong>Figure 1.</strong> The {@link android.widget.ShareActionProvider} in the Gallery app.
</p>
</div>

<h2 id="update-menus">Update Menu Declarations</h2>

<p>To get started with {@link android.widget.ShareActionProvider ShareActionProviders}, define the <code>android:actionProviderClass</code> attribute for the corresponding <code>&lt;item&gt;</code> in your <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a> file:</p>

<pre>
&lt;menu xmlns:android=&quot;http://schemas.android.com/apk/res/android&quot;&gt;
    &lt;item android:id=&quot;@+id/menu_item_share&quot;
        android:showAsAction=&quot;ifRoom&quot;
        android:title=&quot;Share&quot;
        <strong>android:actionProviderClass=&quot;android.widget.ShareActionProvider&quot;</strong> /&gt;
    ...
&lt;/menu&gt;
</pre>

<p>This delegates responsibility for the item's appearance and function to 
{@link android.widget.ShareActionProvider}. However, you will need to tell the provider what you 
would like to share.</p>


<h2 id="set-share-intent">Set the Share Intent</h2>

<p>In order for {@link android.widget.ShareActionProvider} to function, you must provide it a share
intent. This share intent should be the same as described in the <a
href="{@docRoot}training/sharing/send.html">Sending Content to Other Apps</a>
lesson, with action {@link android.content.Intent#ACTION_SEND} and additional data set via extras
like {@link android.content.Intent#EXTRA_TEXT} and {@link android.content.Intent#EXTRA_STREAM}. To
assign a share intent, first find the corresponding {@link android.view.MenuItem} while inflating
your menu resource in your {@link android.app.Activity} or {@link android.app.Fragment}. Next, call
{@link android.view.MenuItem#getActionProvider() MenuItem.getActionProvider()} to retreive an
instance of {@link android.widget.ShareActionProvider}. Use {@link
android.widget.ShareActionProvider#setShareIntent(android.content.Intent) setShareIntent()} to
update the share intent associated with that action item. Here's an example:</p>

<pre>
private ShareActionProvider mShareActionProvider;
...

&#64;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);
    }
}
</pre>

<p>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.</p>

<p>For further discussion about the {@link android.widget.ShareActionProvider}, see the <a
href="{@docRoot}guide/topics/ui/actionbar.html#ActionProvider">Action Bar</a> guide.</p>