Home | History | Annotate | Download | only in beam-files
      1 page.title=Receiving Files from Another Device
      2 
      3 trainingnavtop=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>
    141 public 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