diff options
author | Scott Main <smain@google.com> | 2011-12-13 16:06:16 -0800 |
---|---|---|
committer | Scott Main <smain@google.com> | 2011-12-14 13:18:37 -0800 |
commit | 70645e363e8601550468b726251f4f52f383b9fc (patch) | |
tree | a66d45b20ce22fc781d569c730c528191230295b | |
parent | fc279e51c0bca8086b87bd49e95367c400cb61b4 (diff) | |
download | base-70645e363e8601550468b726251f4f52f383b9fc.tar.gz |
Docs: Add class for Sharing Content
Change-Id: I078a02d952e652c16f84e1b3f7613f3dc9364c97
-rw-r--r-- | docs/html/images/training/sharing/share-text-screenshot.png | bin | 0 -> 33210 bytes | |||
-rw-r--r-- | docs/html/training/sharing/index.jd | 46 | ||||
-rw-r--r-- | docs/html/training/sharing/receive.jd | 149 | ||||
-rw-r--r-- | docs/html/training/sharing/send.jd | 194 | ||||
-rw-r--r-- | docs/html/training/sharing/shareaction.jd | 115 |
5 files changed, 504 insertions, 0 deletions
diff --git a/docs/html/images/training/sharing/share-text-screenshot.png b/docs/html/images/training/sharing/share-text-screenshot.png Binary files differnew file mode 100644 index 000000000000..089221ccace6 --- /dev/null +++ b/docs/html/images/training/sharing/share-text-screenshot.png diff --git a/docs/html/training/sharing/index.jd b/docs/html/training/sharing/index.jd new file mode 100644 index 000000000000..cb133c393c41 --- /dev/null +++ b/docs/html/training/sharing/index.jd @@ -0,0 +1,46 @@ +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> diff --git a/docs/html/training/sharing/receive.jd b/docs/html/training/sharing/receive.jd new file mode 100644 index 000000000000..b2cac304325d --- /dev/null +++ b/docs/html/training/sharing/receive.jd @@ -0,0 +1,149 @@ +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"><intent-filter></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> +<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> +</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) && 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 + } +} +</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> + diff --git a/docs/html/training/sharing/send.jd b/docs/html/training/sharing/send.jd new file mode 100644 index 000000000000..d151ed03c7db --- /dev/null +++ b/docs/html/training/sharing/send.jd @@ -0,0 +1,194 @@ +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, "This is my text to send."); +sendIntent.setType("text/plain"); +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, "This is my text to send."); +sendIntent.setType("text/plain"); +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("image/jpeg"); +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<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..")); +</pre> + +<p>As before, make sure the provided {@link android.net.Uri URIs} point to data that a receiving +application can access.</p> + diff --git a/docs/html/training/sharing/shareaction.jd b/docs/html/training/sharing/shareaction.jd new file mode 100644 index 000000000000..f6be745b93b8 --- /dev/null +++ b/docs/html/training/sharing/shareaction.jd @@ -0,0 +1,115 @@ +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: </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><item></code> in your <a href="{@docRoot}guide/topics/resources/menu-resource.html">menu resource</a> file:</p> + +<pre> +<menu xmlns:android="http://schemas.android.com/apk/res/android"> + <item android:id="@+id/menu_item_share" + android:showAsAction="ifRoom" + android:title="Share" + <strong>android:actionProviderClass="android.widget.ShareActionProvider"</strong> /> + ... +</menu> +</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; +... + +@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> + + |