DOC CHANGE: FileProvider training class
Change-Id: Idad8840dec02150733f23cfefdeaf152a260f63a
This commit is contained in:
@@ -20,7 +20,8 @@ previous.link=result.html
|
|||||||
|
|
||||||
<h2>You should also read</h2>
|
<h2>You should also read</h2>
|
||||||
<ul>
|
<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>
|
</ul>
|
||||||
</div>
|
</div>
|
||||||
</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}
|
<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
|
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>
|
<h2 id="HandleIntent">Handle the Intent in Your Activity</h2>
|
||||||
|
|||||||
@@ -19,7 +19,8 @@ Lifecycle</a>)</li>
|
|||||||
|
|
||||||
<h2>You should also read</h2>
|
<h2>You should also read</h2>
|
||||||
<ul>
|
<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
|
<li><a
|
||||||
href="http://android-developers.blogspot.com/2009/11/integrating-application-with-intents.html">
|
href="http://android-developers.blogspot.com/2009/11/integrating-application-with-intents.html">
|
||||||
Integrating Application with Intents (blog post)</a></li>
|
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>
|
make your app able to respond to intents from other apps.</p>
|
||||||
|
|
||||||
<h2>Lessons</h2>
|
<h2>Lessons</h2>
|
||||||
|
|
||||||
<dl>
|
<dl>
|
||||||
<dt><b><a href="sending.html">Sending the User to Another App</a></b></dt>
|
<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
|
<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>
|
<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
|
<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>
|
intent filters that declare the implicit intents your app accepts.</dd>
|
||||||
</dl>
|
</dl>
|
||||||
|
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ next.link=filters.html
|
|||||||
|
|
||||||
<h2>You should also read</h2>
|
<h2>You should also read</h2>
|
||||||
<ul>
|
<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>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -71,7 +72,7 @@ private void pickContact() {
|
|||||||
|
|
||||||
<h2 id="ReceiveResult">Receive the Result</h2>
|
<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
|
{@link android.app.Activity#onActivityResult onActivityResult()} method. This method includes three
|
||||||
arguments:</p>
|
arguments:</p>
|
||||||
|
|
||||||
|
|||||||
@@ -22,7 +22,7 @@ next.link=result.html
|
|||||||
|
|
||||||
<h2>You should also read</h2>
|
<h2>You should also read</h2>
|
||||||
<ul>
|
<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>
|
</ul>
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
@@ -200,7 +200,7 @@ Intent mapIntent = new Intent(Intent.ACTION_VIEW, location);
|
|||||||
PackageManager packageManager = {@link android.content.Context#getPackageManager()};
|
PackageManager packageManager = {@link android.content.Context#getPackageManager()};
|
||||||
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
|
List<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
|
||||||
boolean isIntentSafe = activities.size() > 0;
|
boolean isIntentSafe = activities.size() > 0;
|
||||||
|
|
||||||
// Start an activity if it's safe
|
// Start an activity if it's safe
|
||||||
if (isIntentSafe) {
|
if (isIntentSafe) {
|
||||||
startActivity(mapIntent);
|
startActivity(mapIntent);
|
||||||
|
|||||||
8
docs/html/training/building-content-sharing.jd
Normal file
8
docs/html/training/building-content-sharing.jd
Normal 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>
|
||||||
80
docs/html/training/secure-file-sharing/index.jd
Normal file
80
docs/html/training/secure-file-sharing/index.jd
Normal 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>
|
||||||
|
|
||||||
|
|
||||||
147
docs/html/training/secure-file-sharing/request-file.jd
Normal file
147
docs/html/training/secure-file-sharing/request-file.jd
Normal 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;
|
||||||
|
...
|
||||||
|
@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.
|
||||||
|
*/
|
||||||
|
@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>
|
||||||
110
docs/html/training/secure-file-sharing/retrieve-info.jd
Normal file
110
docs/html/training/secure-file-sharing/retrieve-info.jd
Normal 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>
|
||||||
136
docs/html/training/secure-file-sharing/setup-sharing.jd
Normal file
136
docs/html/training/secure-file-sharing/setup-sharing.jd
Normal 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"
|
||||||
|
><provider></a></code> element that specifies the
|
||||||
|
{@link android.support.v4.content.FileProvider} class, the authority, and the
|
||||||
|
XML file name:
|
||||||
|
</p>
|
||||||
|
<pre>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||||
|
package="com.example.myapp">
|
||||||
|
<application
|
||||||
|
...>
|
||||||
|
<provider
|
||||||
|
android:name="android.support.v4.content.FileProvider"
|
||||||
|
android:authorities="com.example.myapp.fileprovider"
|
||||||
|
android:grantUriPermissions="true"
|
||||||
|
android:exported="false">
|
||||||
|
<meta-data
|
||||||
|
android:name="android.support.FILE_PROVIDER_PATHS"
|
||||||
|
android:resource="@xml/filepaths" />
|
||||||
|
</provider>
|
||||||
|
...
|
||||||
|
</application>
|
||||||
|
</manifest></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"
|
||||||
|
><meta-data></a></code> child element of the
|
||||||
|
<code><a href="{@docRoot}guide/topics/manifest/provider-element.html"
|
||||||
|
><provider></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>
|
||||||
|
<paths>
|
||||||
|
<files-path path="images/" name="myimages" />
|
||||||
|
</paths></pre>
|
||||||
|
<p>
|
||||||
|
In this example, the <code><files-path></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><paths></code> element can have multiple children, each specifying a different
|
||||||
|
directory to share. In addition to the <code><files-path></code> element, you can
|
||||||
|
use the <code><external-path></code> element to share directories in external storage, and
|
||||||
|
the <code><cache-path></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"
|
||||||
|
><provider></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>
|
||||||
|
|
||||||
298
docs/html/training/secure-file-sharing/share-file.jd
Normal file
298
docs/html/training/secure-file-sharing/share-file.jd
Normal 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>
|
||||||
|
<manifest xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
|
...
|
||||||
|
<application>
|
||||||
|
...
|
||||||
|
<activity
|
||||||
|
android:name=".FileSelectActivity"
|
||||||
|
android:label="@"File Selector" >
|
||||||
|
<intent-filter>
|
||||||
|
<action
|
||||||
|
android:name="android.intent.action.PICK"/>
|
||||||
|
<category
|
||||||
|
android:name="android.intent.category.DEFAULT"/>
|
||||||
|
<category
|
||||||
|
android:name="android.intent.category.OPENABLE"/>
|
||||||
|
<data android:mimeType="text/plain"/>
|
||||||
|
<data android:mimeType="image/*"/>
|
||||||
|
</intent-filter>
|
||||||
|
</activity></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
|
||||||
|
@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"
|
||||||
|
><provider></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() {
|
||||||
|
@Override
|
||||||
|
/*
|
||||||
|
* When a filename in the ListView is clicked, get its
|
||||||
|
* content URI and send it to the requesting app
|
||||||
|
*/
|
||||||
|
public void onItemClick(AdapterView<?> 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><paths></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() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> 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() {
|
||||||
|
@Override
|
||||||
|
public void onItemClick(AdapterView<?> 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>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
page.title=Sharing Content
|
page.title=Sharing Simple Data
|
||||||
page.tags="intents","share"
|
page.tags="intents","share"
|
||||||
|
|
||||||
trainingnavtop=true
|
trainingnavtop=true
|
||||||
@@ -20,26 +20,26 @@ Intent Filters</a></li>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
|
|
||||||
<p>One of the great things about Android applications is their ability to communicate and
|
<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
|
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
|
applications using {@link android.content.Intent} APIs and the {@link
|
||||||
android.view.ActionProvider} object.</p>
|
android.view.ActionProvider} object.</p>
|
||||||
|
|
||||||
|
|
||||||
<h2>Lessons</h2>
|
<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>
|
<dl>
|
||||||
<dd>Learn how to add a "share" action item to your action bar.</dd>
|
<dt><b><a href="send.html">Sending Simple Data to Other Apps</a></b></dt>
|
||||||
</dl>
|
<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>
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
page.title=Receiving Content from Other Apps
|
page.title=Receiving Simple Data from Other Apps
|
||||||
parent.title=Sharing Content
|
parent.title=Sharing Simple Data
|
||||||
parent.link=index.html
|
parent.link=index.html
|
||||||
|
|
||||||
trainingnavtop=true
|
trainingnavtop=true
|
||||||
@@ -30,26 +30,26 @@ Intent Filters</a></li>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>Just as your application can send data to other applications, so too can it easily receive data
|
<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
|
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
|
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
|
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
|
<a href="https://play.google.com/store/apps/details?id=com.google.android.apps.plus">Google+ Android
|
||||||
application</a>
|
application</a>
|
||||||
accepts both text <em>and</em> single or multiple images. With this app, a user can easily start 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>
|
new Google+ post with photos from the Android Gallery app.</p>
|
||||||
|
|
||||||
|
|
||||||
<h2 id="update-manifest">Update Your Manifest</h2>
|
<h2 id="update-manifest">Update Your Manifest</h2>
|
||||||
|
|
||||||
<p>Intent filters inform the system what intents an application component is willing to accept.
|
<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
|
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>
|
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
|
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
|
define an intent filter in your manifest, using the
|
||||||
<code><a
|
<code><a
|
||||||
href="{@docRoot}guide/components/intents-filters.html#ifs"><intent-filter></a></code>
|
href="{@docRoot}guide/components/intents-filters.html#ifs"><intent-filter></a></code>
|
||||||
element. For example, if your application handles receiving text content, a single image of any
|
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>
|
type, or multiple images of any type, your manifest would look like:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -72,24 +72,24 @@ type, or multiple images of any type, your manifest would look like:</p>
|
|||||||
</activity>
|
</activity>
|
||||||
</pre>
|
</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
|
please read <a href="{@docRoot}guide/components/intents-filters.html#ifs">Intents and Intent
|
||||||
Filters</a></p>
|
Filters</a></p>
|
||||||
|
|
||||||
<p>When another application tries to share any of these things by constructing an intent and passing
|
<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
|
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,
|
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
|
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>
|
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>
|
<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
|
<p>To handle the content delivered by an {@link android.content.Intent}, start by calling {@link
|
||||||
android.content.Intent#getIntent(String) getIntent()}
|
android.content.Intent#getIntent(String) getIntent()}
|
||||||
to get {@link android.content.Intent} object. Once you have the object, you can examine its
|
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
|
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
|
parts of the system, such as the launcher, then you will need to take this into consideration when
|
||||||
examining the intent.</p>
|
examining the intent.</p>
|
||||||
|
|
||||||
<pre>
|
<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
|
image being sent might be extremely large. Also, remember to process binary data in a separate
|
||||||
thread rather than the main ("UI") thread.</p>
|
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
|
<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
|
be more complicated like applying an interesting photo filter to an image. It's really specific
|
||||||
to your application what happens next.</p>
|
to your application what happens next.</p>
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,9 @@
|
|||||||
page.title=Sending Content to Other Apps
|
page.title=Sending Simple Data to Other Apps
|
||||||
parent.title=Sharing Content
|
parent.title=Sharing Simple Data
|
||||||
parent.link=index.html
|
parent.link=index.html
|
||||||
|
|
||||||
trainingnavtop=true
|
trainingnavtop=true
|
||||||
next.title=Receiving Content from Other Apps
|
next.title=Receiving Simple Data from Other Apps
|
||||||
next.link=receive.html
|
next.link=receive.html
|
||||||
|
|
||||||
@jd:body
|
@jd:body
|
||||||
@@ -29,22 +29,22 @@ Intent Filters</a></li>
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>When you construct an intent, you must specify the action you want the intent to "trigger."
|
<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
|
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,
|
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
|
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
|
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
|
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
|
one option). Similarly, you can advertise the data types that your activities support receiving
|
||||||
from other applications by specifying them in your manifest.</p>
|
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
|
<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
|
sharing of content. Intents allow users to share information quickly and easily, using their
|
||||||
favorite applications.</p>
|
favorite applications.</p>
|
||||||
|
|
||||||
<p><strong>Note:</strong> The best way to add a share action item to an
|
<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
|
{@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
|
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>
|
about <a href="shareaction.html">Adding an Easy Share Action</a>.</p>
|
||||||
|
|
||||||
|
|
||||||
@@ -58,10 +58,10 @@ on a handset.
|
|||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<p>The most straightforward and common use of the {@link android.content.Intent#ACTION_SEND}
|
<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
|
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
|
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
|
for sharing an article or website with friends via email or social networking. Here is the code to
|
||||||
implement this type of sharing:</p>
|
implement this type of sharing:</p>
|
||||||
|
|
||||||
<pre>
|
<pre>
|
||||||
@@ -72,12 +72,12 @@ sendIntent.setType("text/plain");
|
|||||||
startActivity(sendIntent);
|
startActivity(sendIntent);
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>If there's an installed application with a filter that matches
|
<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
|
{@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")
|
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
|
that allows the user to choose an app. If you call
|
||||||
{@link android.content.Intent#createChooser(android.content.Intent, CharSequence)
|
{@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
|
for the intent, Android will <strong>always</strong> display the chooser. This has some
|
||||||
advantages:</p>
|
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>The resulting dialog is shown in figure 1.</p>
|
||||||
|
|
||||||
<p>Optionally, you can set some standard extras for the intent:
|
<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_EMAIL}, {@link android.content.Intent#EXTRA_CC},
|
||||||
{@link android.content.Intent#EXTRA_BCC}, {@link android.content.Intent#EXTRA_SUBJECT}. However,
|
{@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
|
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.
|
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>
|
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
|
<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 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#EXTRA_CC}, use
|
||||||
{@link android.content.Intent#putExtra(String,String[]) putExtra(String, String[])} to add these
|
{@link android.content.Intent#putExtra(String,String[]) putExtra(String, String[])} to add these
|
||||||
to your intent.</p>
|
to your intent.</p>
|
||||||
|
|
||||||
|
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ parent.title=Sharing Content
|
|||||||
parent.link=index.html
|
parent.link=index.html
|
||||||
|
|
||||||
trainingnavtop=true
|
trainingnavtop=true
|
||||||
previous.title=Receiving Content from Other Apps
|
previous.title=Receiving Simple Data from Other Apps
|
||||||
previous.link=receive.html
|
previous.link=receive.html
|
||||||
|
|
||||||
@jd:body
|
@jd:body
|
||||||
@@ -28,7 +28,7 @@ previous.link=receive.html
|
|||||||
</div>
|
</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
|
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
|
(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
|
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>
|
<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>
|
<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>
|
<pre>
|
||||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||||
<item android:id="@+id/menu_item_share"
|
<item
|
||||||
android:showAsAction="ifRoom"
|
android:id="@+id/menu_item_share"
|
||||||
android:title="Share"
|
android:showAsAction="ifRoom"
|
||||||
<strong>android:actionProviderClass="android.widget.ShareActionProvider"</strong> />
|
android:title="Share"
|
||||||
|
<b>android:actionProviderClass=
|
||||||
|
"android.widget.ShareActionProvider"</b> />
|
||||||
...
|
...
|
||||||
</menu>
|
</menu>
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>This delegates responsibility for the item's appearance and function to
|
<p>
|
||||||
{@link android.widget.ShareActionProvider}. However, you will need to tell the provider what you
|
This delegates responsibility for the item's appearance and function to
|
||||||
would like to share.</p>
|
{@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>
|
<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
|
<p>
|
||||||
intent. This share intent should be the same as described in the <a
|
In order for {@link android.widget.ShareActionProvider} to function, you must provide it a share
|
||||||
href="{@docRoot}training/sharing/send.html">Sending Content to Other Apps</a>
|
intent. This share intent should be the same as described in the
|
||||||
lesson, with action {@link android.content.Intent#ACTION_SEND} and additional data set via extras
|
<a href="{@docRoot}training/sharing/send.html">Sending Simple Data to Other Apps</a> lesson,
|
||||||
like {@link android.content.Intent#EXTRA_TEXT} and {@link android.content.Intent#EXTRA_STREAM}. To
|
with action {@link android.content.Intent#ACTION_SEND} and additional data set via extras
|
||||||
assign a share intent, first find the corresponding {@link android.view.MenuItem} while inflating
|
like {@link android.content.Intent#EXTRA_TEXT} and {@link android.content.Intent#EXTRA_STREAM}.
|
||||||
your menu resource in your {@link android.app.Activity} or {@link android.app.Fragment}. Next, call
|
To assign a share intent, first find the corresponding {@link android.view.MenuItem} while
|
||||||
{@link android.view.MenuItem#getActionProvider() MenuItem.getActionProvider()} to retreive an
|
inflating your menu resource in your {@link android.app.Activity} or
|
||||||
instance of {@link android.widget.ShareActionProvider}. Use {@link
|
{@link android.app.Fragment}. Next, call {@link android.view.MenuItem#getActionProvider
|
||||||
android.widget.ShareActionProvider#setShareIntent(android.content.Intent) setShareIntent()} to
|
MenuItem.getActionProvider()} to retrieve an instance of
|
||||||
update the share intent associated with that action item. Here's an example:</p>
|
{@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>
|
<pre>
|
||||||
private ShareActionProvider mShareActionProvider;
|
private ShareActionProvider mShareActionProvider;
|
||||||
@@ -105,8 +117,8 @@ private void setShareIntent(Intent shareIntent) {
|
|||||||
}
|
}
|
||||||
</pre>
|
</pre>
|
||||||
|
|
||||||
<p>You may only need to set the share intent once during the creation of your menus, or you may
|
<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
|
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>
|
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
|
<p>For further discussion about the {@link android.widget.ShareActionProvider} object, see the <a
|
||||||
|
|||||||
@@ -192,33 +192,91 @@ include the action bar on devices running Android 2.1 or higher."
|
|||||||
</ul>
|
</ul>
|
||||||
</li>
|
</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>
|
</ul>
|
||||||
</li><!-- end getting started -->
|
</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>
|
</li>
|
||||||
</ul>
|
</ul>
|
||||||
</li>
|
</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">
|
<li class="nav-section">
|
||||||
<div class="nav-section-header">
|
<div class="nav-section-header">
|
||||||
<a href="<?cs var:toroot ?>training/basics/network-ops/index.html"
|
<a href="<?cs var:toroot ?>training/basics/network-ops/index.html"
|
||||||
|
|||||||
Reference in New Issue
Block a user