am 45edbb70: DOC CHANGE: FileProvider training class
* commit '45edbb701ac44891aa07a403a55ee2393da9b25f': DOC CHANGE: FileProvider training class
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
|
||||
@@ -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<ResolveInfo> activities = packageManager.queryIntentActivities(mapIntent, 0);
|
||||
boolean isIntentSafe = activities.size() > 0;
|
||||
|
||||
|
||||
// Start an activity if it's safe
|
||||
if (isIntentSafe) {
|
||||
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"
|
||||
|
||||
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>
|
||||
|
||||
@@ -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"><intent-filter></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"><intent-filter></a></code>
|
||||
element. For example, if your application handles receiving text content, a single image of any
|
||||
type, or multiple images of any type, your manifest would look like:</p>
|
||||
|
||||
<pre>
|
||||
@@ -72,24 +72,24 @@ type, or multiple images of any type, your manifest would look like:</p>
|
||||
</activity>
|
||||
</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>
|
||||
|
||||
|
||||
@@ -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("text/plain");
|
||||
startActivity(sendIntent);
|
||||
</pre>
|
||||
|
||||
<p>If there's an installed application with a filter that matches
|
||||
{@link android.content.Intent#ACTION_SEND} and MIME type text/plain, the Android system will run
|
||||
it; if more than one application matches, the system displays a disambiguation dialog (a "chooser")
|
||||
that allows the user to choose an app. If you call
|
||||
<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>
|
||||
|
||||
|
||||
|
||||
@@ -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><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>
|
||||
<menu xmlns:android="http://schemas.android.com/apk/res/android">
|
||||
<item android:id="@+id/menu_item_share"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="Share"
|
||||
<strong>android:actionProviderClass="android.widget.ShareActionProvider"</strong> />
|
||||
<item
|
||||
android:id="@+id/menu_item_share"
|
||||
android:showAsAction="ifRoom"
|
||||
android:title="Share"
|
||||
<b>android:actionProviderClass=
|
||||
"android.widget.ShareActionProvider"</b> />
|
||||
...
|
||||
</menu>
|
||||
</pre>
|
||||
|
||||
<p>This delegates responsibility for the item's appearance and function to
|
||||
{@link android.widget.ShareActionProvider}. However, you will need to tell the provider what you
|
||||
would like to share.</p>
|
||||
<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
|
||||
|
||||
@@ -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"
|
||||
|
||||
Reference in New Issue
Block a user