1page.title=Sending Files to Another Device 2 3trainingnavtop=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 ><manifest></a></code> element: 76<pre> 77 <uses-permission android:name="android.permission.NFC" /> 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 ><manifest></a></code> element: 88<pre> 89 <uses-permission 90 android:name="android.permission.READ_EXTERNAL_STORAGE" /> 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 ><uses-feature></a></code> element as a child 105 of the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html" 106 ><manifest></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 ><uses-feature></a></code> element: 113</p> 114<pre> 115<uses-feature 116 android:name="android.hardware.nfc" 117 android:required="true" /></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 ><uses-sdk></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<uses-feature android:name="android.hardware.nfc" android:required="false" /></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> 157public class MainActivity extends Activity { 158 ... 159 NfcAdapter mNfcAdapter; 160 // Flag to indicate that Android Beam is available 161 boolean mAndroidBeamAvailable = false; 162 ... 163 @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 < 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> 209public 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 @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> 239public class MainActivity extends Activity { 240 ... 241 // Instance that returns available files from this app 242 private FileUriCallback mFileUriCallback; 243 ... 244 @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