Home | History | Annotate | Download | only in beam-files
      1 page.title=Sending Files to Another Device
      2 
      3 trainingnavtop=true
      4 @jd:body
      5 
      6 
      7 <div id="tb-wrapper">
      8 <div id="tb">
      9 
     10 <!-- table of contents -->
     11 <h2>This lesson teaches you to</h2>
     12 <ol>
     13   <li><a href="#DeclareFeatures">Declare Features in the Manifest</a>
     14   <li><a href="#TestAndroidBeam">Test for Android Beam File Transfer Support</a></li>
     15   <li>
     16     <a href="#CreateCallback"
     17     >Create a Callback Method That Provides Files</a>
     18   </li>
     19   <li><a href="#ProvideUri">Specify the Files to Send</a>
     20 </ol>
     21 
     22 <h2>You should also read</h2>
     23 <ul>
     24     <li><a href="{@docRoot}guide/topics/data/data-storage.html">Storage Options</a></li>
     25 </ul>
     26 
     27 </div>
     28 </div>
     29 <p>
     30     This lesson shows you how to design your app to send large files to another device using
     31     Android Beam file transfer. To send files, you request permission to use NFC and external
     32     storage, test to ensure your device supports NFC, and provide URIs to Android Beam file
     33     transfer.
     34 </p>
     35 <p>
     36     The Android Beam file transfer feature has the following requirements:
     37 </p>
     38 <ol>
     39     <li>
     40         Android Beam file transfer for large files is only available in Android 4.1 (API level 16)
     41         and higher.
     42     </li>
     43     <li>
     44         Files you want to transfer must reside in external storage. To learn more about using
     45         external storage, read <a href="{@docRoot}guide/topics/data/data-storage.html#filesExternal"
     46         >Using the External Storage</a>.
     47     </li>
     48     <li>
     49         Each file you want to transfer must be world-readable. You can set this permission by
     50         calling the method {@link java.io.File#setReadable File.setReadable(true,false)}.
     51     </li>
     52     <li>
     53         You must provide a file URI for the files you want to transfer. Android Beam file transfer
     54         is unable to handle content URIs generated by
     55         {@link android.support.v4.content.FileProvider#getUriForFile FileProvider.getUriForFile}.
     56     </li>
     57 </ol>
     58 
     59 <h2 id="DeclareFeatures">Declare Features in the Manifest</h2>
     60 <p>
     61     First, edit your app manifest to declare the permissions and features your app needs.
     62 </p>
     63 <h3>Request Permissions</h3>
     64 <p>
     65     To allow your app to use Android Beam file transfer to send files from external storage using
     66     NFC, you must request the following permissions in your app manifest:
     67 </p>
     68 <dl>
     69     <dt>
     70         {@link android.Manifest.permission#NFC NFC}
     71     </dt>
     72     <dd>
     73         Allows your app to send data over NFC. To specify this permission, add the following element
     74         as a child of the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"
     75         >&lt;manifest&gt;</a></code> element:
     76 <pre>
     77     &lt;uses-permission android:name="android.permission.NFC" /&gt;
     78 </pre>
     79     </dd>
     80     <dt>
     81         {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE}
     82     </dt>
     83     <dd>
     84         Allows your app to read from external storage. To specify this permission, add the following
     85         element as a child of the
     86         <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"
     87         >&lt;manifest&gt;</a></code> element:
     88 <pre>
     89     &lt;uses-permission
     90             android:name="android.permission.READ_EXTERNAL_STORAGE" /&gt;
     91 </pre>
     92     <p class="note">
     93         <strong>Note:</strong> As of Android 4.2.2 (API level 17), this permission is not
     94         enforced. Future versions of the platform may require it for apps that want to read from
     95         external storage. To ensure forward compatibility, request the permission now, before it
     96         becomes required.
     97     </p>
     98     </dd>
     99 </dl>
    100 <h3>Specify the NFC feature</h3>
    101 <p>
    102     Specify that your app uses NFC, by adding a
    103     <code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"
    104     >&lt;uses-feature&gt;</a></code> element as a child
    105     of the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html"
    106     >&lt;manifest&gt;</a></code> element. Set the <code>android:required</code> attribute to
    107     <code>true</code> to indicate that your app won't function unless NFC is present.
    108 </p>
    109 <p>
    110     The following snippet shows you how to specify the
    111     <code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html"
    112     >&lt;uses-feature&gt;</a></code> element:
    113 </p>
    114 <pre>
    115 &lt;uses-feature
    116     android:name="android.hardware.nfc"
    117     android:required="true" /&gt;</pre>
    118 <p>
    119     Note that if your app only uses NFC as an option, but still functions if NFC isn't present, you
    120     should set <code>android:required</code> to <code>false</code>, and test for NFC in code.
    121 </p>
    122 <h3>Specify Android Beam file transfer</h3>
    123 <p>
    124     Since Android Beam file transfer is only available in Android 4.1 (API level 16) and later,
    125     if your app depends on Android Beam file transfer for a key part of its functionality you must
    126     specify the <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html"
    127     >&lt;uses-sdk&gt;</a></code> element with the
    128     <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min"
    129     >android:minSdkVersion</a>="16"</code> attribute. Otherwise, you can set
    130     <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min"
    131     >android:minSdkVersion</a></code> to another value as necessary, and test for the platform
    132     version in code, as described in the following section.
    133 </p>
    134 <h2 id="TestAndroidBeam">Test for Android Beam File Transfer Support</h2>
    135 <p>
    136     To specify in your app manifest that NFC is optional, you use the following element:
    137 </p>
    138 <pre>
    139 &lt;uses-feature android:name="android.hardware.nfc" android:required="false" /&gt;</pre>
    140 <p>
    141     If you set the attribute
    142     <code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#required"
    143     >android:required</a>="false"</code>, you must test for NFC support and Android Beam file
    144     transfer support in code.
    145 </p>
    146 <p>
    147     To test for Android Beam file transfer support in code, start by testing that the device
    148     supports NFC by calling {@link android.content.pm.PackageManager#hasSystemFeature
    149     PackageManager.hasSystemFeature()} with the argument
    150     {@link android.content.pm.PackageManager#FEATURE_NFC FEATURE_NFC}. Next, check that the Android
    151     version supports Android Beam file transfer by testing the value of
    152     {@link android.os.Build.VERSION#SDK_INT}. If Android Beam file transfer is supported, get an
    153     instance of the NFC controller, which allows you to communicate with the NFC hardware.
    154     For example:
    155 </p>
    156 <pre>
    157 public class MainActivity extends Activity {
    158     ...
    159     NfcAdapter mNfcAdapter;
    160     // Flag to indicate that Android Beam is available
    161     boolean mAndroidBeamAvailable  = false;
    162     ...
    163     &#64;Override
    164     protected void onCreate(Bundle savedInstanceState) {
    165         ...
    166         // NFC isn't available on the device
    167         if (!PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)) {
    168             /*
    169              * Disable NFC features here.
    170              * For example, disable menu items or buttons that activate
    171              * NFC-related features
    172              */
    173             ...
    174         // Android Beam file transfer isn't supported
    175         } else if (Build.VERSION.SDK_INT &lt;
    176                 Build.VERSION_CODES.JELLY_BEAN_MR1) {
    177             // If Android Beam isn't available, don't continue.
    178             mAndroidBeamAvailable = false;
    179             /*
    180              * Disable Android Beam file transfer features here.
    181              */
    182             ...
    183         // Android Beam file transfer is available, continue
    184         } else {
    185         mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
    186         ...
    187         }
    188     }
    189     ...
    190 }</pre>
    191 
    192 <h2 id="CreateCallback">
    193     Create a Callback Method that Provides Files
    194 </h2>
    195 <p>
    196     Once you've verified that the device supports Android Beam file transfer, add a callback
    197     method that the system invokes when Android Beam file transfer detects that the user wants
    198     to send files to another NFC-enabled device. In this callback method, return an array of
    199     {@link android.net.Uri} objects. Android Beam file transfer copies the files represented by
    200     these URIs to the receiving device.
    201 </p>
    202 <p>
    203     To add the callback method, implement the
    204     {@link android.nfc.NfcAdapter.CreateBeamUrisCallback} interface and its method
    205     {@link android.nfc.NfcAdapter.CreateBeamUrisCallback#createBeamUris createBeamUris()}. The
    206     following snippet shows you how to do this:
    207 </p>
    208 <pre>
    209 public class MainActivity extends Activity {
    210     ...
    211     // List of URIs to provide to Android Beam
    212     private Uri[] mFileUris = new Uri[10];
    213     ...
    214     /**
    215      * Callback that Android Beam file transfer calls to get
    216      * files to share
    217      */
    218     private class FileUriCallback implements
    219             NfcAdapter.CreateBeamUrisCallback {
    220         public FileUriCallback() {
    221         }
    222         /**
    223          * Create content URIs as needed to share with another device
    224          */
    225         &#64;Override
    226         public Uri[] createBeamUris(NfcEvent event) {
    227             return mFileUris;
    228         }
    229     }
    230     ...
    231 }
    232 </pre>
    233 <p>
    234     Once you've implemented the interface, provide the callback to Android Beam file transfer by
    235     calling {@link android.nfc.NfcAdapter#setBeamPushUrisCallback setBeamPushUrisCallback()}. The
    236     following snippet shows you how to do this:
    237 </p>
    238 <pre>
    239 public class MainActivity extends Activity {
    240     ...
    241     // Instance that returns available files from this app
    242     private FileUriCallback mFileUriCallback;
    243     ...
    244     &#64;Override
    245     protected void onCreate(Bundle savedInstanceState) {
    246         ...
    247         // Android Beam file transfer is available, continue
    248         ...
    249         mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
    250         /*
    251          * Instantiate a new FileUriCallback to handle requests for
    252          * URIs
    253          */
    254         mFileUriCallback = new FileUriCallback();
    255         // Set the dynamic callback for URI requests.
    256         mNfcAdapter.setBeamPushUrisCallback(mFileUriCallback,this);
    257         ...
    258     }
    259     ...
    260 }
    261 </pre>
    262 <p class="note">
    263     <strong>Note:</strong> You can also provide the array of {@link android.net.Uri} objects
    264     directly to the NFC framework through your app's {@link android.nfc.NfcAdapter} instance. Choose
    265     this approach if you can define the URIs to transfer before the NFC touch event occurs.
    266     To learn more about this approach, see {@link android.nfc.NfcAdapter#setBeamPushUris
    267     NfcAdapter.setBeamPushUris()}.
    268 </p>
    269 <h2 id="ProvideUri">Specify the Files to Send</h2>
    270 <p>
    271     To transfer one or more files to another NFC-enabled device, get a file URI (a URI with a
    272     <code>file</code> scheme) for each file and then add the URI to an array of
    273     {@link android.net.Uri} objects. To transfer a file, you must also have permanent read access
    274     for the file. For example, the following snippet shows you how to get a file URI from a file
    275     name and then add the URI to the array:
    276 </p>
    277 <pre>
    278         /*
    279          * Create a list of URIs, get a File,
    280          * and set its permissions
    281          */
    282         private Uri[] mFileUris = new Uri[10];
    283         String transferFile = "transferimage.jpg";
    284         File extDir = getExternalFilesDir(null);
    285         File requestFile = new File(extDir, transferFile);
    286         requestFile.setReadable(true, false);
    287         // Get a URI for the File and add it to the list of URIs
    288         fileUri = Uri.fromFile(requestFile);
    289         if (fileUri != null) {
    290             mFileUris[0] = fileUri;
    291         } else {
    292             Log.e("My Activity", "No File URI available for file.");
    293         }
    294 </pre>
    295