am 45edbb70: DOC CHANGE: FileProvider training class

* commit '45edbb701ac44891aa07a403a55ee2393da9b25f':
  DOC CHANGE: FileProvider training class
This commit is contained in:
Joe Malin
2013-10-12 15:46:02 -07:00
committed by Android Git Automerger
15 changed files with 981 additions and 145 deletions

View File

@@ -20,7 +20,8 @@ previous.link=result.html
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Simple Data</a></li>
<li><a href="{@docRoot}training/secure-file-sharing/index.html">Sharing Files</a>
</ul>
</div>
</div>
@@ -152,7 +153,7 @@ implicit intents will resolve to your activity.</p>
<p>For more information about sending and receiving {@link android.content.Intent#ACTION_SEND}
intents that perform social sharing behaviors, see the lesson about <a
href="{@docRoot}training/sharing/receive.html">Receiving Content from Other Apps</a>.</p>
href="{@docRoot}training/sharing/receive.html">Receiving Simple Data from Other Apps</a>.</p>
<h2 id="HandleIntent">Handle the Intent in Your Activity</h2>

View File

@@ -19,7 +19,8 @@ Lifecycle</a>)</li>
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Simple Data</a></li>
<li><a href="{@docRoot}training/secure-file-sharing/index.html">Sharing Files</a>
<li><a
href="http://android-developers.blogspot.com/2009/11/integrating-application-with-intents.html">
Integrating Application with Intents (blog post)</a></li>
@@ -49,7 +50,7 @@ interactions with other apps, such as start another app, receive a result from t
make your app able to respond to intents from other apps.</p>
<h2>Lessons</h2>
<dl>
<dt><b><a href="sending.html">Sending the User to Another App</a></b></dt>
<dd>Shows how you can create implicit intents to launch other apps that can perform an
@@ -59,5 +60,5 @@ action.</dd>
<dt><b><a href="filters.html">Allowing Other Apps to Start Your Activity</a></b></dt>
<dd>Shows how to make activities in your app open for use by other apps by defining
intent filters that declare the implicit intents your app accepts.</dd>
</dl>
</dl>

View File

@@ -21,7 +21,8 @@ next.link=filters.html
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Simple Data</a></li>
<li><a href="{@docRoot}training/secure-file-sharing/index.html">Sharing Files</a>
</ul>
</div>
@@ -71,7 +72,7 @@ private void pickContact() {
<h2 id="ReceiveResult">Receive the Result</h2>
<p>When the user is done with the subsequent activity and returns, the system calls your activity's
<p>When the user is done with the subsequent activity and returns, the system calls your activity's
{@link android.app.Activity#onActivityResult onActivityResult()} method. This method includes three
arguments:</p>

View File

@@ -22,7 +22,7 @@ next.link=result.html
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Content</a></li>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Simple Data</a></li>
</ul>
</div>
@@ -200,7 +200,7 @@ Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
PackageManager packageManager = {@link android.content.Context#getPackageManager()};
List&lt;ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
boolean isIntentSafe = activities.size() > 0;
// Start an activity if it's safe
if (isIntentSafe) {
startActivity(mapIntent);

View File

@@ -0,0 +1,8 @@
page.title=Building Apps with Content Sharing
page.trainingcourse=true
@jd:body
<p>These classes teach you how to create apps that share data between apps and devices.</p>

View File

@@ -0,0 +1,80 @@
page.title=Sharing Files
trainingnavtop=true
startpage=true
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>Dependencies and prerequisites</h2>
<ul>
<li>Android 1.6 (API Level 4) or higher</li>
<li>Familiarity with file operations such as opening, reading, and writing files</li>
</ul>
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}guide/topics/data/data-storage.html">Storage Options</a></li>
<li><a href="{@docRoot}training/basics/data-storage/files.html">Saving Files</a>
<li><a href="{@docRoot}training/sharing/index.html">Sharing Simple Data</a></li>
</ul>
</div>
</div>
<p>
Apps often have a need to offer one or more of their files to another app. For example, an image
gallery may want to offer files to image editors, or a file management app may want to allow
users to copy and paste files between areas in external storage. One way a sending app can
share a file is to respond to a request from the receiving app.
</p>
<p>
In all cases, the only secure way to offer a file from your app to another app is to send the
receiving app the file's content URI and grant temporary access permissions to that URI.
Content URIs with temporary URI access permissions are secure because they apply only to the
app that receives the URI, and they expire automatically. The Android
{@link android.support.v4.content.FileProvider} component provides the method
{@link android.support.v4.content.FileProvider#getUriForFile getUriForFile()} for
generating a file's content URI.
</p>
<p>
If you want to share small amounts of text or numeric data between apps, you should send an
{@link android.content.Intent} that contains the data. To learn how to send simple data with an
{@link android.content.Intent}, see the training class
<a href="{@docRoot}training/sharing/index.html">Sharing Simple Data</a>.
</p>
<p>
This class explains how to securely share files from your app to another app using content URIs
generated by the Android {@link android.support.v4.content.FileProvider} component and
temporary permissions that you grant to the receiving app for the content URI.
</p>
<h2>Lessons</h2>
<dl>
<dt><b><a href="setup-sharing.html">Setting Up File Sharing</a></b></dt>
<dd>
Learn how to set up your app to share files.
</dd>
<dt><b><a href="share-file.html">Sharing a File</a></b></dt>
<dd>
Learn how to offer a file to another app by generating a content URI for the file,
granting access permissions to the URI, and sending the URI to the app.
</dd>
<dt><b><a href="request-file.html">Requesting a Shared File</a></b></dt>
<dd>
Learn how to request a file shared by another app, receive the content URI for the file,
and use the content URI to open the file.
</dd>
<dt>
<b><a href="retrieve-info.html">Retrieving File Information</a></b>
</dt>
<dd>
Learn how an app can use a content URI generated by a
{@link android.support.v4.content.FileProvider} to retrieve file information including
MIME type and file size.
</dd>
</dl>

View File

@@ -0,0 +1,147 @@
page.title=Requesting a Shared File
trainingnavtop=true
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#SendRequest">Send a Request for the File</a></li>
<li><a href="#OpenFile">Access the Requested File</a>
</ol>
<h2>You should also read</h2>
<ul>
<li>
<a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html#SimpleQuery"
>Retrieving Data from the Provider</a>
</li>
</ul>
</div>
</div>
<p>
When an app wants to access a file shared by another app, the requesting app (the client)
usually sends a request to the app sharing the files (the server). In most cases, the request
starts an {@link android.app.Activity} in the server app that displays the files it can share.
The user picks a file, after which the server app returns the file's content URI to the
client app.
</p>
<p>
This lesson shows you how a client app requests a file from a server app, receives the file's
content URI from the server app, and opens the file using the content URI.
</p>
<h2 id="SendRequest">Send a Request for the File</h2>
<p>
To request a file from the server app, the client app calls
{@link android.app.Activity#startActivityForResult startActivityForResult} with an
{@link android.content.Intent} containing the action such as
{@link android.content.Intent#ACTION_PICK ACTION_PICK} and a MIME type that the client app
can handle.
</p>
<p>
For example, the following code snippet demonstrates how to send an
{@link android.content.Intent} to a server app in order to start the
{@link android.app.Activity} described in <a href="share-file.html#SendURI"
>Sharing a File</a>:
</p>
<pre>
public class MainActivity extends Activity {
private Intent mRequestFileIntent;
private ParcelFileDescriptor mInputPFD;
...
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
mRequestFileIntent = new Intent(Intent.ACTION_PICK);
mRequestFileIntent.setType("image/jpg");
...
}
...
protected void requestFile() {
/**
* When the user requests a file, send an Intent to the
* server app.
* files.
*/
startActivityForResult(mRequestFileIntent, 0);
...
}
...
}
</pre>
<h2 id="OpenFile">Access the Requested File</h2>
<p>
The server app sends the file's content URI back to the client app in an
{@link android.content.Intent}. This {@link android.content.Intent} is passed to the client
app in its override of {@link android.app.Activity#onActivityResult onActivityResult()}. Once
the client app has the file's content URI, it can access the file by getting its
{@link java.io.FileDescriptor}.
</p>
<p>
<p>
File security is preserved in this process because the content URI is the only piece of data
that the client app receives. Since this URI doesn't contain a directory path, the client app
can't discover and open any other files in the server app. Only the client app gets access to
the file, and only for the permissions granted by the server app. The permissions are temporary,
so once the client app's task stack is finished, the file is no longer accessible outside the
server app.
</p>
<p>
The next snippet demonstrates how the client app handles the
{@link android.content.Intent} sent from the server app, and how the client app gets the
{@link java.io.FileDescriptor} using the content URI:
</p>
<pre>
/*
* When the Activity of the app that hosts files sets a result and calls
* finish(), this method is invoked. The returned Intent contains the
* content URI of a selected file. The result code indicates if the
* selection worked or not.
*/
&#64;Override
public void onActivityResult(int requestCode, int resultCode,
Intent returnIntent) {
// If the selection didn't work
if (resultCode != RESULT_OK) {
// Exit without doing anything else
return;
} else {
// Get the file's content URI from the incoming Intent
Uri returnUri = returnIntent.getData();
/*
* Try to open the file for "read" access using the
* returned URI. If the file isn't found, write to the
* error log and return.
*/
try {
/*
* Get the content resolver instance for this context, and use it
* to get a ParcelFileDescriptor for the file.
*/
mInputPFD = getContentResolver().openFileDescriptor(returnUri, "r");
} catch (FileNotFoundException e) {
e.printStackTrace();
Log.e("MainActivity", "File not found.");
return;
}
// Get a regular file descriptor for the file
FileDescriptor fd = mInputPFD.getFileDescriptor();
...
}
}
</pre>
<p>
The method {@link android.content.ContentResolver#openFileDescriptor openFileDescriptor()}
returns a {@link android.os.ParcelFileDescriptor} for the file. From this object, the client
app gets a {@link java.io.FileDescriptor} object, which it can then use to read the file.
</p>

View File

@@ -0,0 +1,110 @@
page.title=Retrieving File Information
trainingnavtop=true
@jd:body
<div id="tb-wrapper">
<div id="tb">
<!-- table of contents -->
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#RetrieveMimeType">Retrieve a File's MIME Type</a></li>
<li><a href="#RetrieveFileInfo">Retrieve a File's Name and Size</a></li>
</ol>
<!-- other docs (NOT javadocs) -->
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}guide/topics/providers/content-provider-basics.html#SimpleQuery"
>Retrieving Data from the Provider</a></li>
</ul>
</div>
</div>
<p>
Before a client app tries to work with a file for which it has a content URI, the app can
request information about the file from the server app, including the file's data type and
file size. The data type helps the client app to determine if it can handle the file, and the
file size helps the client app set up buffering and caching for the file.
</p>
<p>
This lesson demonstrates how to query the server app's
{@link android.support.v4.content.FileProvider} to retrieve a file's MIME type and size.
</p>
<h2 id="RetrieveMimeType">Retrieve a File's MIME Type</h2>
<p>
A file's data type indicates to the client app how it should handle the file's contents. To get
the data type of a shared file given its content URI, the client app calls
{@link android.content.ContentResolver#getType ContentResolver.getType()}. This method returns
the file's MIME type. By default, a
{@link android.support.v4.content.FileProvider} determines the file's MIME type from its
filename extension.
</p>
<p>
The following code snippet demonstrates how a client app retrieves the MIME type of a file once
the server app has returned the content URI to the client:
</p>
<pre>
...
/*
* Get the file's content URI from the incoming Intent, then
* get the file's MIME type
*/
Uri returnUri = returnIntent.getData();
String mimeType = getContentResolver().getType(returnUri);
...
</pre>
<h2 id="RetrieveFileInfo">Retrieve a File's Name and Size</h2>
<p>
The {@link android.support.v4.content.FileProvider} class has a default implementation of the
{@link android.support.v4.content.FileProvider#query query()} method that returns the
name and size of the file associated with a content URI in a
{@link android.database.Cursor}. The default implementation returns two columns:
</p>
<dl>
<dt>{@link android.provider.OpenableColumns#DISPLAY_NAME DISPLAY_NAME}</dt>
<dd>
The file's name, as a {@link java.lang.String}. This value is the same as the value returned
by {@link java.io.File#getName File.getName()}.
</dd>
<dt>{@link android.provider.OpenableColumns#SIZE SIZE}</dt>
<dd>
The size of the file in bytes, as a {@code long} This value is the same as the value
returned by {@link java.io.File#length File.length()}
</dd>
</dl>
<p>
The client app can get both the {@link android.provider.OpenableColumns#DISPLAY_NAME
DISPLAY_NAME} and {@link android.provider.OpenableColumns#SIZE SIZE} for a file by setting all
of the arguments of {@link android.support.v4.content.FileProvider#query query()} to
{@code null} except for the content URI. For example, this code snippet retrieves a file's
{@link android.provider.OpenableColumns#DISPLAY_NAME DISPLAY_NAME} and
{@link android.provider.OpenableColumns#SIZE SIZE} and displays each one in separate
{@link android.widget.TextView}:
</p>
<pre>
...
/*
* Get the file's content URI from the incoming Intent,
* then query the server app to get the file's display name
* and size.
*/
Uri returnUri = returnIntent.getData();
Cursor returnCursor =
getContentResolver().query(returnUri, null, null, null, null);
/*
* Get the column indexes of the data in the Cursor,
* move to the first row in the Cursor, get the data,
* and display it.
*/
int nameIndex = returnCursor.getColumnIndex(OpenableColumns.DISPLAY_NAME);
int sizeIndex = returnCursor.getColumnIndex(OpenableColumns.SIZE);
returnCursor.moveToFirst();
TextView nameView = (TextView) findViewById(R.id.filename_text);
TextView sizeView = (TextView) findViewById(R.id.filesize_text);
nameView.setText(returnCursor.getString(nameIndex));
sizeView.setText(Long.toString(returnCursor.getLong(sizeIndex)));
...
</pre>

View File

@@ -0,0 +1,136 @@
page.title=Setting Up File Sharing
trainingnavtop=true
@jd:body
<div id="tb-wrapper">
<div id="tb">
<!-- table of contents -->
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#DefineProvider">Specify the FileProvider</a></li>
<li><a href="#DefineMetaData">Specify Sharable Directories</a></li>
</ol>
<h2>You should also read</h2>
<ul>
<li><a href="{@docRoot}guide/topics/data/data-storage.html">Storage Options</a></li>
<li><a href="{@docRoot}training/basics/data-storage/files.html">Saving Files</a>
</ul>
</div>
</div>
<p>
To securely offer a file from your app to another app, you need to configure your app to offer
a secure handle to the file, in the form of a content URI. The Android
{@link android.support.v4.content.FileProvider} component generates content URIs for
files, based on specifications you provide in XML. This lesson shows you how to add the default
implementation of {@link android.support.v4.content.FileProvider} to your app, and how to
specify the files you want to offer to other apps.
</p>
<h2 id="DefineProvider">Specify the FileProvider</h2>
<p>
Defining a {@link android.support.v4.content.FileProvider} for your app requires an entry in
your manifest. This entry specifies the authority to use in generating content URIs, as well as
the name of an XML file that specifies the directories your app can share.
</p>
<p>
The following snippet shows you how to add to your manifest the
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
>&lt;provider&gt;</a></code> element that specifies the
{@link android.support.v4.content.FileProvider} class, the authority, and the
XML file name:
</p>
<pre>
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.myapp"&gt;
&lt;application
...&gt;
&lt;provider
android:name="android.support.v4.content.FileProvider"
android:authorities="com.example.myapp.fileprovider"
android:grantUriPermissions="true"
android:exported="false"&gt;
&lt;meta-data
android:name="android.support.FILE_PROVIDER_PATHS"
android:resource="&#64;xml/filepaths" /&gt;
&lt;/provider&gt;
...
&lt;/application&gt;
&lt;/manifest&gt;</pre>
<p>
In this example, the <code><a href="{@docRoot}guide/topics/manifest/provider-element.html#auth"
>android:authorities</a></code> attribute specifies the URI authority
that you want to use for content URIs generated by the
{@link android.support.v4.content.FileProvider}.
In the example, the authority is <code>com.example.myapp.fileprovider</code>. For your own
app, specify an authority consisting of the app's
<code><a href="{@docRoot}guide/topics/manifest/manifest-element.html#package"
>android:package</a></code> value with the string "fileprovider" appended to it. To learn more
about the authority value, see the topic
<a href="{@docRoot}guide/topics/providers/content-provider-basics.html#ContentURIs"
>Content URIs</a> and the documentation for the
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html#auth"
>android:authorities</a></code> attribute.
</p>
<p>
The <code><a href="{@docRoot}guide/topics/manifest/meta-data-element.html"
>&lt;meta-data&gt;</a></code> child element of the
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
>&lt;provider&gt;</a></code> points to an XML file that specifies the directories you want to
share. The <code>android:resource</code> attribute is the path and name of the file, without
the <code>.xml</code> extension.The contents of this file are described in the next section.
</p>
<h2 id="DefineMetaData">Specify Sharable Directories</h2>
<p>
Once you have added the {@link android.support.v4.content.FileProvider} to your app manifest,
you need to specify the directories that contain the files you want to share. To specify the
directories, start by creating the file <code>filepaths.xml</code> in the <code>res/xml/</code>
subdirectory of your project. In this file, specify the directories by adding an XML element for
each directory. The following snippet shows you an example of the contents of
<code>res/xml/filepaths.xml</code>. The snippet also demonstrates how to share a subdirectory
of the <code>files/</code> directory in your internal storage area:
</p>
<pre>
&lt;paths&gt;
&lt;files-path path="images/" name="myimages" /&gt;
&lt;/paths&gt;</pre>
<p>
In this example, the <code>&lt;files-path&gt;</code> tag shares directories within the
<code>files/</code> directory of your app's internal storage. The <code>path</code> attribute
shares the <code>images/</code> subdirectory of <code>files/</code>. The <code>name</code>
attribute tells the {@link android.support.v4.content.FileProvider} to add the path segment
<code>myimages</code> to content URIs for files in the <code>files/images/</code> subdirectory.
</p>
<p>
The <code>&lt;paths&gt;</code> element can have multiple children, each specifying a different
directory to share. In addition to the <code>&lt;files-path&gt;</code> element, you can
use the <code>&lt;external-path&gt;</code> element to share directories in external storage, and
the <code>&lt;cache-path&gt;</code> element to share directories in your internal cache
directory. To learn more about the child elements that specify shared directories, see the
{@link android.support.v4.content.FileProvider} reference documentation.
</p>
<p class="note">
<strong>Note:</strong> The XML file is the only way you can specify the directories you want to
share; you can't programmatically add a directory.
</p>
<p>
You now have a complete specification of a {@link android.support.v4.content.FileProvider}
that generates content URIs for files in the <code>files/</code> directory of your app's
internal storage or for files in subdirectories of <code>files/</code>. When your app generates
a content URI for a file, it contains the authority specified in the
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
>&lt;provider&gt;</a></code> element (<code>com.example.myapp.fileprovider</code>),
the path <code>myimages/</code>, and the name of the file.
</p>
<p>
For example, if you define a {@link android.support.v4.content.FileProvider} according to the
snippets in this lesson, and you request a content URI for the file
<code>default_image.jpg</code>, {@link android.support.v4.content.FileProvider} returns the
following URI:
</p>
<pre>
content://com.example.myapp.fileprovider/myimages/default_image.jpg</pre>

View File

@@ -0,0 +1,298 @@
page.title=Sharing a File
trainingnavtop=true
@jd:body
<div id="tb-wrapper">
<div id="tb">
<h2>This lesson teaches you to</h2>
<ol>
<li><a href="#ReceiveRequests">Receive File Requests</a></li>
<li><a href="#CreateFileSelection">Create a File Selection Activity</a></li>
<li><a href="#RespondToRequest">Respond to a File Selection</a></li>
<li><a href="#GrantPermissions">Grant Permissions for the File</a></li>
<li><a href="#ShareFile">Share the File with the Requesting App</a>
</ol>
<h2>You should also read</h2>
<ul>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html#ContentURI"
>Designing Content URIs</a>
</li>
<li>
<a href="{@docRoot}guide/topics/providers/content-provider-creating.html#Permissions"
>Implementing Content Provider Permissions</a>
</li>
<li>
<a href="{@docRoot}guide/topics/security/permissions.html">Permissions</a>
</li>
<li>
<a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>
</li>
</ul>
</div>
</div>
<p>
Once you have set up your app to share files using content URIs, you can respond to other apps'
requests for those files. One way to respond to these requests is to provide a file selection
interface from the server app that other applications can invoke. This approach allows a client
application to let users select a file from the server app and then receive the selected file's
content URI.
</p>
<p>
This lesson shows you how to create a file selection {@link android.app.Activity} in your app
that responds to requests for files.
</p>
<h2 id="ReceiveRequests">Receive File Requests</h2>
<p>
To receive requests for files from client apps and respond with a content URI, your app should
provide a file selection {@link android.app.Activity}. Client apps start this
{@link android.app.Activity} by calling {@link android.app.Activity#startActivityForResult
startActivityForResult()} with an {@link android.content.Intent} containing the action
{@link android.content.Intent#ACTION_PICK ACTION_PICK}. When the client app calls
{@link android.app.Activity#startActivityForResult startActivityForResult()}, your app can
return a result to the client app, in the form of a content URI for the file the user selected.
</p>
<p>
To learn how to implement a request for a file in a client app, see the lesson
<a href="request-file.html">Requesting a Shared File</a>.
</p>
<h2 id="CreateFileSelection">Create a File Selection Activity</h2>
<p>
To set up the file selection {@link android.app.Activity}, start by specifying the
{@link android.app.Activity} in your manifest, along with an intent filter
that matches the action {@link android.content.Intent#ACTION_PICK ACTION_PICK} and the
categories {@link android.content.Intent#CATEGORY_DEFAULT CATEGORY_DEFAULT} and
{@link android.content.Intent#CATEGORY_OPENABLE CATEGORY_OPENABLE}. Also add MIME type filters
for the files your app serves to other apps. The following snippet shows you how to specify the
new {@link android.app.Activity} and intent filter:
</p>
<pre>
&lt;manifest xmlns:android="http://schemas.android.com/apk/res/android"&gt;
...
&lt;application&gt;
...
&lt;activity
android:name=".FileSelectActivity"
android:label="&#64;"File Selector" &gt;
&lt;intent-filter&gt;
&lt;action
android:name="android.intent.action.PICK"/&gt;
&lt;category
android:name="android.intent.category.DEFAULT"/&gt;
&lt;category
android:name="android.intent.category.OPENABLE"/&gt;
&lt;data android:mimeType="text/plain"/&gt;
&lt;data android:mimeType="image/*"/&gt;
&lt;/intent-filter&gt;
&lt;/activity&gt;</pre>
<h3>Define the file selection Activity in code</h3>
<p>
Next, define an {@link android.app.Activity} subclass that displays the files available from
your app's <code>files/images/</code> directory in internal storage and allows the user to pick
the desired file. The following snippet demonstrates how to define this
{@link android.app.Activity} and respond to the user's selection:
</p>
<pre>
public class MainActivity extends Activity {
// The path to the root of this app's internal storage
private File mPrivateRootDir;
// The path to the "images" subdirectory
private File mImagesDir;
// Array of files in the images subdirectory
File[] mImageFiles;
// Array of filenames corresponding to mImageFiles
String[] mImageFilenames;
// Initialize the Activity
&#64;Override
protected void onCreate(Bundle savedInstanceState) {
...
// Set up an Intent to send back to apps that request a file
mResultIntent =
new Intent("com.example.myapp.ACTION_RETURN_FILE");
// Get the files/ subdirectory of internal storage
mPrivateRootDir = getFilesDir();
// Get the files/images subdirectory;
mImagesDir = new File(mPrivateRootDir, "images");
// Get the files in the images subdirectory
mImageFiles = mImagesDir.listFiles();
// Set the Activity's result to null to begin with
setResult(Activity.RESULT_CANCELED, null);
/*
* Display the file names in the ListView mFileListView.
* Back the ListView with the array mImageFilenames, which
* you can create by iterating through mImageFiles and
* calling File.getAbsolutePath() for each File
*/
...
}
...
}</pre>
<h2 id="RespondToRequest">Respond to a File Selection</h2>
<p>
Once a user selects a shared file, your application must determine what file was selected and
then generate a content URI for the file. Since the {@link android.app.Activity} displays the
list of available files in a {@link android.widget.ListView}, when the user clicks a file name
the system calls the method {@link android.widget.AdapterView.OnItemClickListener#onItemClick
onItemClick()}, in which you can get the selected file.
</p>
<p>
In {@link android.widget.AdapterView.OnItemClickListener#onItemClick onItemClick()}, get a
{@link java.io.File} object for the file name of the selected file and pass it as an argument to
{@link android.support.v4.content.FileProvider#getUriForFile getUriForFile()}, along with the
authority that you specified in the
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
>&lt;provider&gt;</a></code> element for the {@link android.support.v4.content.FileProvider}.
The resulting content URI contains the authority, a path segment corresponding to the file's
directory (as specified in the XML meta-data), and the name of the file including its
extension. How {@link android.support.v4.content.FileProvider} maps directories to path
segments based on XML meta-data is described in the section
<a href="setup-sharing.html#DefineMetaData">Specify Sharable Directories</a>.
</p>
<p>
The following snippet shows you how to detect the selected file and get a content URI for it:
</p>
<pre>
protected void onCreate(Bundle savedInstanceState) {
...
// Define a listener that responds to clicks on a file in the ListView
mFileListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
&#64;Override
/*
* When a filename in the ListView is clicked, get its
* content URI and send it to the requesting app
*/
public void onItemClick(AdapterView&lt;?&gt; adapterView,
View view,
int position,
long rowId) {
/*
* Get a File for the selected file name.
* Assume that the file names are in the
* mImageFilename array.
*/
File requestFile = new File(mImageFilename[position]);
/*
* Most file-related method calls need to be in
* try-catch blocks.
*/
// Use the FileProvider to get a content URI
try {
fileUri = FileProvider.getUriForFile(
MainActivity.this,
"com.example.myapp.fileprovider",
requestFile);
} catch (IllegalArgumentException e) {
Log.e("File Selector",
"The selected file can't be shared: " +
clickedFilename);
}
...
}
});
...
}</pre>
<p>
Remember that you can only generate content URIs for files that reside in a directory
you've specified in the meta-data file that contains the <code>&lt;paths&gt;</code> element, as
described in the section <a href="setup-sharing.html#DefineMetaData"
>Specify Sharable Directories</a>. If you call
{@link android.support.v4.content.FileProvider#getUriForFile getUriForFile()} for a
{@link java.io.File} in a path that you haven't specified, you receive an
{@link java.lang.IllegalArgumentException}.
</p>
<h2 id="GrantPermissions">Grant Permissions for the File</h2>
<p>
Now that you have a content URI for the file you want to share with another app, you need to
allow the client app to access the file. To allow access, grant permissions to the client app by
adding the content URI to an {@link android.content.Intent} and then setting permission flags on
the {@link android.content.Intent}. The permissions you grant are temporary and expire
automatically when the receiving app's task stack is finished.
</p>
<p>
The following code snippet shows you how to set read permission for the file:
</p>
<pre>
protected void onCreate(Bundle savedInstanceState) {
...
// Define a listener that responds to clicks in the ListView
mFileListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
&#64;Override
public void onItemClick(AdapterView&lt;?&gt; adapterView,
View view,
int position,
long rowId) {
...
if (fileUri != null) {
// Grant temporary read permission to the content URI
mResultIntent.addFlags(
Intent.FLAG_GRANT_READ_URI_PERMISSION);
}
...
}
...
});
...
}</pre>
<p class="caution">
<strong>Caution:</strong> Calling {@link android.content.Intent#setFlags setFlags()} is the only
way to securely grant access to your files using temporary access permissions. Avoid calling
{@link android.content.Context#grantUriPermission Context.grantUriPermission()} method for a
file's content URI, since this method grants access that you can only revoke by
calling {@link android.content.Context#revokeUriPermission Context.revokeUriPermission()}.
</p>
<h2 id="ShareFile">Share the File with the Requesting App</h2>
<p>
To share the file with the app that requested it, pass the {@link android.content.Intent}
containing the content URI and permissions to {@link android.app.Activity#setResult
setResult()}. When the {@link android.app.Activity} you have just defined is finished, the
system sends the {@link android.content.Intent} containing the content URI to the client app.
The following code snippet shows you how to do this:
</p>
<pre>
protected void onCreate(Bundle savedInstanceState) {
...
// Define a listener that responds to clicks on a file in the ListView
mFileListView.setOnItemClickListener(
new AdapterView.OnItemClickListener() {
&#64;Override
public void onItemClick(AdapterView&lt;?&gt; adapterView,
View view,
int position,
long rowId) {
...
if (fileUri != null) {
...
// Put the Uri and MIME type in the result Intent
mResultIntent.setDataAndType(
fileUri,
getContentResolver().getType(fileUri));
// Set the result
MainActivity.this.setResult(Activity.RESULT_OK,
mResultIntent);
} else {
mResultIntent.setDataAndType(null, "");
MainActivity.this.setResult(RESULT_CANCELED,
mResultIntent);
}
}
});</pre>
<p>
Provide users with an way to return immediately to the client app once they have chosen a file.
One way to do this is to provide a checkmark or <b>Done</b> button. Associate a method with
the button using the button's
<code><a href="{@docRoot}reference/android/view/View.html#attr_android:onClick"
>android:onClick</a></code> attribute. In the method, call
{@link android.app.Activity#finish finish()}. For example:
</p>
<pre>
public void onDoneClick(View v) {
// Associate a method with the Done button
finish();
}</pre>

View File

@@ -1,4 +1,4 @@
page.title=Sharing Content
page.title=Sharing Simple Data
page.tags="intents","share"
trainingnavtop=true
@@ -20,26 +20,26 @@ Intent Filters</a></li>
</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>
already exists in another application?</p>
<p>This class covers some common ways you can send and receive content between
<p>This class covers some common ways you can send and receive simple data between
applications using {@link android.content.Intent} APIs and the {@link
android.view.ActionProvider} object.</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>
<dl>
<dt><b><a href="send.html">Sending Simple Data 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 Simple Data 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>

View File

@@ -1,5 +1,5 @@
page.title=Receiving Content from Other Apps
parent.title=Sharing Content
page.title=Receiving Simple Data from Other Apps
parent.title=Sharing Simple Data
parent.link=index.html
trainingnavtop=true
@@ -30,26 +30,26 @@ Intent Filters</a></li>
</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
<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://play.google.com/store/apps/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
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.
Similar to how 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
<p>Intent filters inform the system what intents an application component is willing to accept.
Similar to how you constructed an intent with action {@link android.content.Intent#ACTION_SEND} in
the <a href="{@docRoot}training/sharing/send.html">Sending Simple Data to Other Apps</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/components/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
href="{@docRoot}guide/components/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>
@@ -72,24 +72,24 @@ type, or multiple images of any type, your manifest would look like:</p>
&lt;/activity&gt;
</pre>
<p class="note"><strong>Note:</strong> For more information on intent filters and intent resolution
<p class="note"><strong>Note:</strong> For more information on intent filters and intent resolution
please read <a href="{@docRoot}guide/components/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. If the user selects your application,
the corresponding activity (<code>.ui.MyActivity</code> in the example above) will be started. It
application will be listed as an option in the intent chooser. 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
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>
@@ -143,7 +143,7 @@ know what some other application may send you. For example, the wrong MIME type
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
<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>

View File

@@ -1,9 +1,9 @@
page.title=Sending Content to Other Apps
parent.title=Sharing Content
page.title=Sending Simple Data to Other Apps
parent.title=Sharing Simple Data
parent.link=index.html
trainingnavtop=true
next.title=Receiving Content from Other Apps
next.title=Receiving Simple Data from Other Apps
next.link=receive.html
@jd:body
@@ -29,22 +29,22 @@ Intent Filters</a></li>
</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 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
<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 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.</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
<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 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
<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>
@@ -58,10 +58,10 @@ 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
<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>
@@ -72,12 +72,12 @@ 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
<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()}
Intent.createChooser()}
for the intent, Android will <strong>always</strong> display the chooser. This has some
advantages:</p>
@@ -100,17 +100,17 @@ startActivity(<strong>Intent.createChooser(sendIntent, getResources().getText(R.
<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.
<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
<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>

View File

@@ -3,7 +3,7 @@ parent.title=Sharing Content
parent.link=index.html
trainingnavtop=true
previous.title=Receiving Content from Other Apps
previous.title=Receiving Simple Data from Other Apps
previous.link=receive.html
@jd:body
@@ -28,7 +28,7 @@ previous.link=receive.html
</div>
<p>Implementing an effective and user friendly share action in your {@link android.app.ActionBar}
<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
@@ -47,36 +47,48 @@ starting with API Level 14 and higher.</p>
<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>
<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;item
android:id=&quot;@+id/menu_item_share&quot;
android:showAsAction=&quot;ifRoom&quot;
android:title=&quot;Share&quot;
<b>android:actionProviderClass=
"android.widget.ShareActionProvider"</b> /&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>
<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>
<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 Simple Data 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 retrieve 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;
@@ -105,8 +117,8 @@ private void setShareIntent(Intent 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
<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} object, see the <a

View File

@@ -192,33 +192,91 @@ include the action bar on devices running Android 2.1 or higher."
</ul>
</li>
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/sharing/index.html"
description=
"How to take your app interaction to the next level by sharing
information with other apps, receive information back, and provide a simple and
scalable way to perform Share actions with user content."
>Sharing Content</a>
</div>
<ul>
<li><a href="<?cs var:toroot ?>training/sharing/send.html">
Sending Content to Other Apps
</a>
</li>
<li><a href="<?cs var:toroot ?>training/sharing/receive.html">
Receiving Content from Other Apps
</a>
</li>
<li><a href="<?cs var:toroot ?>training/sharing/shareaction.html">
Adding an Easy Share Action
</a>
</li>
</ul>
</li>
</ul>
</li><!-- end getting started -->
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/building-content-sharing.html">
<span class="small">Building Apps with</span><br/>Content Sharing
</a>
</div>
<ul>
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/sharing/index.html"
description=
"How to take your app interaction to the next level by sharing
information with other apps, receive information back, and provide a simple and
scalable way to perform Share actions with user content."
>Sharing Simple Data</a>
</div>
<ul>
<li>
<a href="<?cs var:toroot ?>training/sharing/send.html">
Sending Simple Data to Other Apps
</a>
</li>
<li>
<a href="<?cs var:toroot ?>training/sharing/receive.html">
Receiving Simple Data from Other Apps
</a>
</li>
<li>
<a href="<?cs var:toroot ?>training/sharing/shareaction.html">
Adding an Easy Share Action
</a>
</li>
</ul>
</li>
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot?>training/secure-file-sharing/index.html"
description=
"How to provide secure access to a file associated with your app using a content
URI and temporary access permissions."
>Sharing Files</a>
</div>
<ul>
<li>
<a href="<?cs var:toroot ?>training/secure-file-sharing/setup-sharing.html">
Setting Up File Sharing
</a>
</li>
<li>
<a href="<?cs var:toroot ?>training/secure-file-sharing/share-file.html">
Sharing a File
</a>
</li>
<li>
<a href="<?cs var:toroot ?>training/secure-file-sharing/request-file.html">
Requesting a Shared File
</a>
</li>
<li>
<a href="<?cs var:toroot ?>training/secure-file-sharing/retrieve-info.html">
Retrieving File Information
</a>
</li>
</ul>
</li>
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/beam-files/index.html"
description=
"How to transfer files between devices using the NFC Android Beam feature."
>Sharing Files with NFC</a>
</div>
<ul>
<li>
<a href="<?cs var:toroot ?>training/beam-files/send-files.html"
>Sending Files to Another Device</a>
</li>
<li><a href="<?cs var:toroot ?>training/beam-files/receive-files.html"
>Receiving Files from Another Device</a></li>
</ul>
</li>
</ul>
</li>
@@ -423,22 +481,6 @@ include the action bar on devices running Android 2.1 or higher."
</li>
</ul>
</li>
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/beam-files/index.html"
description=
"How to transfer files between devices using the NFC Android Beam feature."
>Sharing Files with NFC</a>
</div>
<ul>
<li>
<a href="<?cs var:toroot ?>training/beam-files/send-files.html"
>Sending Files to Another Device</a>
</li>
<li><a href="<?cs var:toroot ?>training/beam-files/receive-files.html"
>Receiving Files from Another Device</a></li>
</ul>
</li>
<li class="nav-section">
<div class="nav-section-header">
<a href="<?cs var:toroot ?>training/basics/network-ops/index.html"