1page.title=Receiving Files from Another Device
2
3trainingnavtop=true
4@jd:body
5
6<div id="tb-wrapper">
7<div id="tb">
8
9<h2>This lesson teaches you to</h2>
10<ol>
11    <li><a href="#IntentFilter">Respond to a Request to Display Data</a></li>
12    <li><a href="#RequestPermissions">Request File Permissions</a></li>
13    <li><a href="#GetFilePath">Get the Directory for Copied Files</a></li>
14</ol>
15<h2>You should also read</h2>
16<ul>
17    <li>
18        <a href="{@docRoot}guide/topics/providers/content-provider-basics.html#ContentURIs"
19        >Content URIs</a>
20    </li>
21    <li>
22        <a href="{@docRoot}guide/components/intents-filters.html">Intents and Intent Filters</a>
23    </li>
24    <li>
25        <a href="{@docRoot}guide/topics/ui/notifiers/notifications.html">Notifications</a>
26    </li>
27    <li>
28        <a href="{@docRoot}guide/topics/data/data-storage.html#filesExternal"
29        >Using the External Storage</a>
30    </li>
31</ul>
32
33</div>
34</div>
35
36<p>
37    Android Beam file transfer copies files to a special directory on the receiving device. It also
38    scans the copied files using the Android Media Scanner and adds entries for media files to
39    the {@link android.provider.MediaStore} provider. This lesson shows you how to respond when the
40    file copy is complete, and how to locate the copied files on the receiving device.
41</p>
42<h2 id="IntentFilter">Respond to a Request to Display Data</h2>
43<p>
44    When Android Beam file transfer finishes copying files to the receiving device, it posts a
45    notification containing an {@link android.content.Intent} with the action
46    {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}, the MIME type of the first file that
47    was transferred, and a URI that points to the first file. When the user clicks the notification,
48    this intent is sent out to the system. To have your app respond to this intent, add an
49    <code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"
50    >&lt;intent-filter&gt;</a></code> element for the
51    <code><a href="{@docRoot}guide/topics/manifest/activity-element.html"
52    >&lt;activity&gt;</a></code> element of the {@link android.app.Activity} that should respond.
53    In the <code><a href="{@docRoot}guide/topics/manifest/intent-filter-element.html"
54    >&lt;intent-filter&gt;</a></code> element, add the following child elements:
55</p>
56<dl>
57    <dt>
58        <code><a href="{@docRoot}guide/topics/manifest/action-element.html"
59        >&lt;action android:name="android.intent.action.VIEW" /&gt;</a></code>
60    </dt>
61    <dd>
62        Matches the {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} intent sent from the
63        notification.
64    </dd>
65    <dt>
66        <code><a href="{@docRoot}guide/topics/manifest/category-element.html"
67        >&lt;category android:name="android.intent.category.CATEGORY_DEFAULT" /&gt;</a></code>
68    </dt>
69    <dd>
70        Matches an {@link android.content.Intent} that doesn't have an explicit category.
71    </dd>
72    <dt>
73        <code><a href="{@docRoot}guide/topics/manifest/data-element.html"
74        >&lt;data android:mimeType="<i>mime-type</i>" /&gt;</a></code>
75    </dt>
76    <dd>
77        Matches a MIME type. Specify only those MIME types that your app can handle.
78    </dd>
79</dl>
80<p>
81    For example, the following snippet shows you how to add an intent filter that
82    triggers the activity <code>com.example.android.nfctransfer.ViewActivity</code>:
83</p>
84<pre>
85    &lt;activity
86        android:name="com.example.android.nfctransfer.ViewActivity"
87        android:label="Android Beam Viewer" &gt;
88        ...
89        &lt;intent-filter&gt;
90            &lt;action android:name="android.intent.action.VIEW"/&gt;
91            &lt;category android:name="android.intent.category.DEFAULT"/&gt;
92            ...
93        &lt;/intent-filter&gt;
94    &lt;/activity&gt;
95</pre>
96<p class="note">
97    <strong>Note:</strong> Android Beam file transfer is not the only source of an
98    {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} intent. Other apps on the receiving
99    device can also send an {@link android.content.Intent} with this action.
100    Handling this situation is discussed in the section <a href="#GetDirectory"
101    >Get the directory from a content URI</a>.
102</p>
103<h2 id="RequestPermissions">Request File Permissions</h2>
104<p>
105    To read files that Android Beam file transfer copies to the device, request the permission
106    {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE}. For example:
107</p>
108<pre>
109    &lt;uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;</pre>
110<p>
111    If you want to copy transferred files to your app's own storage area, request the permission
112    {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE} instead.
113    {@link android.Manifest.permission#WRITE_EXTERNAL_STORAGE WRITE_EXTERNAL_STORAGE} includes
114    {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE}.
115</p>
116<p class="note">
117    <strong>Note:</strong> As of Android 4.2.2 (API level 17), the permission
118    {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE} is
119    only enforced if the user chooses to do so. Future versions of the platform may require this
120    permission in all cases. To ensure forward compatibility, request the permission now, before it
121    becomes required.
122</p>
123<p>
124    Since your app has control over its internal storage area, you don't need to request
125    write permission to copy a transferred file to your internal storage area.
126</p>
127<h2 id="GetFilePath">Get the Directory for Copied Files</h2>
128<p>
129    Android Beam file transfer copies all the files in a single transfer to one directory
130    on the receiving device. The URI in the content {@link android.content.Intent} sent by the
131    Android Beam file transfer notification points to the first transferred file. However, your
132    app may also receive an {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} intent from a
133    source other than Android Beam file transfer. To determine how you should handle the incoming
134    {@link android.content.Intent}, you need to examine its scheme and authority.
135</p>
136<p>
137    To get the scheme for the URI, call {@link android.net.Uri#getScheme() Uri.getScheme()}. The
138    following code snippet shows you how to determine the scheme and handle the URI accordingly:
139</p>
140<pre>
141public class MainActivity extends Activity {
142    ...
143    // A File object containing the path to the transferred files
144    private File mParentPath;
145    // Incoming Intent
146    private Intent mIntent;
147    ...
148    /*
149     * Called from onNewIntent() for a SINGLE_TOP Activity
150     * or onCreate() for a new Activity. For onNewIntent(),
151     * remember to call setIntent() to store the most
152     * current Intent
153     *
154     */
155    private void handleViewIntent() {
156        ...
157        // Get the Intent action
158        mIntent = getIntent();
159        String action = mIntent.getAction();
160        /*
161         * For ACTION_VIEW, the Activity is being asked to display data.
162         * Get the URI.
163         */
164        if (TextUtils.equals(action, Intent.ACTION_VIEW)) {
165            // Get the URI from the Intent
166            Uri beamUri = mIntent.getData();
167            /*
168             * Test for the type of URI, by getting its scheme value
169             */
170            if (TextUtils.equals(beamUri.getScheme(), "file")) {
171                mParentPath = handleFileUri(beamUri);
172            } else if (TextUtils.equals(
173                    beamUri.getScheme(), "content")) {
174                mParentPath = handleContentUri(beamUri);
175            }
176        }
177        ...
178    }
179    ...
180}
181</pre>
182<h3>Get the directory from a file URI</h3>
183<p>
184    If the incoming {@link android.content.Intent} contains a file URI, the URI contains the
185    absolute file name of a file, including the full directory path and file name. For Android Beam
186    file transfer, the directory path points to the location of the other transferred files, if
187    any. To get the directory path, get the path part of the URI, which contains all of the URI
188    except the <code>file:</code> prefix. Create a {@link java.io.File} from the path part, then
189    get the parent path of the {@link java.io.File}:
190</p>
191<pre>
192    ...
193    public String handleFileUri(Uri beamUri) {
194        // Get the path part of the URI
195        String fileName = beamUri.getPath();
196        // Create a File object for this filename
197        File copiedFile = new File(fileName);
198        // Get a string containing the file's parent directory
199        return copiedFile.getParent();
200    }
201    ...
202</pre>
203
204<h3 id="GetDirectory">Get the directory from a content URI</h3>
205<p>
206    If the incoming {@link android.content.Intent} contains a content URI, the URI may point to a
207    directory and file name stored in the {@link android.provider.MediaStore} content provider. You
208    can detect a content URI for {@link android.provider.MediaStore} by testing the URI's
209    authority value. A content URI for {@link android.provider.MediaStore} may come from
210    Android Beam file transfer or from another app, but in both cases you can retrieve a directory
211    and file name for the content URI.
212</p>
213<p>
214    You can also receive an incoming {@link android.content.Intent#ACTION_VIEW ACTION_VIEW}
215    intent containing a content URI for a content provider other than
216    {@link android.provider.MediaStore}. In this case, the content URI doesn't contain the
217    {@link android.provider.MediaStore} authority value, and the content URI usually doesn't point
218    to a directory.
219</p>
220<p class="note">
221    <strong>Note:</strong> For Android Beam file transfer, you receive a content URI in the
222    {@link android.content.Intent#ACTION_VIEW ACTION_VIEW} intent if the first incoming file
223    has a MIME type of "audio/*", "image/*", or "video/*", indicating that the file is media-
224    related. Android Beam file transfer indexes the media files it transfers by running Media
225    Scanner on the directory where it stores transferred files. Media Scanner writes its results
226    to the {@link android.provider.MediaStore} content provider, then it passes a content URI
227    for the first file back to Android Beam file transfer. This content URI is the one you
228    receive in the notification {@link android.content.Intent}. To get the directory
229    of the first file, you retrieve it from {@link android.provider.MediaStore} using the content
230    URI.
231</p>
232<h3>Determine the content provider</h3>
233<p>
234    To determine if you can retrieve a file directory from the content URI, determine the
235    the content provider associated with the URI by calling
236    {@link android.net.Uri#getAuthority Uri.getAuthority()} to get the URI's authority. The
237    result has two possible values:
238</p>
239<dl>
240    <dt>
241        {@link android.provider.MediaStore#AUTHORITY MediaStore.AUTHORITY}
242    </dt>
243    <dd>
244        The URI is for a file or files tracked by {@link android.provider.MediaStore}. Retrieve the
245        full file name from {@link android.provider.MediaStore}, and get directory from the file
246        name.
247    </dd>
248    <dt>
249        Any other authority value
250    </dt>
251    <dd>
252        A content URI from another content provider. Display the data associated with the content
253        URI, but don't get the file directory.
254    </dd>
255</dl>
256<p>
257    To get the directory for a {@link android.provider.MediaStore} content URI,
258    run a query that specifies the incoming content URI for the {@link android.net.Uri} argument and
259    the column {@link android.provider.MediaStore.MediaColumns#DATA MediaColumns.DATA} for the
260    projection. The returned {@link android.database.Cursor} contains the full path and name for
261    the file represented by the URI. This path also contains all the other files that Android Beam
262    file transfer just copied to the device.
263</p>
264<p>
265    The following snippet shows you how to test the authority of the content URI and retrieve the
266    the path and file name for the transferred file:
267</p>
268<pre>
269    ...
270    public String handleContentUri(Uri beamUri) {
271        // Position of the filename in the query Cursor
272        int filenameIndex;
273        // File object for the filename
274        File copiedFile;
275        // The filename stored in MediaStore
276        String fileName;
277        // Test the authority of the URI
278        if (!TextUtils.equals(beamUri.getAuthority(), MediaStore.AUTHORITY)) {
279            /*
280             * Handle content URIs for other content providers
281             */
282        // For a MediaStore content URI
283        } else {
284            // Get the column that contains the file name
285            String[] projection = { MediaStore.MediaColumns.DATA };
286            Cursor pathCursor =
287                    getContentResolver().query(beamUri, projection,
288                    null, null, null);
289            // Check for a valid cursor
290            if (pathCursor != null &amp;&amp;
291                    pathCursor.moveToFirst()) {
292                // Get the column index in the Cursor
293                filenameIndex = pathCursor.getColumnIndex(
294                        MediaStore.MediaColumns.DATA);
295                // Get the full file name including path
296                fileName = pathCursor.getString(filenameIndex);
297                // Create a File object for the filename
298                copiedFile = new File(fileName);
299                // Return the parent directory of the file
300                return new File(copiedFile.getParent());
301             } else {
302                // The query didn't work; return null
303                return null;
304             }
305        }
306    }
307    ...
308</pre>
309<p>
310    To learn more about retrieving data from a content provider, see the section
311    <a href="{@docRoot}guide/topics/providers/content-provider-basics.html#SimpleQuery"
312    >Retrieving Data from the Provider</a>.
313</p>
314