| page.title=Sending Files to Another Device |
| |
| 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="#DeclareFeatures">Declare Features in the Manifest</a> |
| <li><a href="#TestAndroidBeam">Test for Android Beam File Transfer Support</a></li> |
| <li> |
| <a href="#CreateCallback" |
| >Create a Callback Method That Provides Files</a> |
| </li> |
| <li><a href="#ProvideUri">Specify the Files to Send</a> |
| </ol> |
| |
| <h2>You should also read</h2> |
| <ul> |
| <li><a href="{@docRoot}guide/topics/data/data-storage.html">Storage Options</a></li> |
| </ul> |
| |
| </div> |
| </div> |
| <p> |
| This lesson shows you how to design your app to send large files to another device using |
| Android Beam file transfer. To send files, you request permission to use NFC and external |
| storage, test to ensure your device supports NFC, and provide URIs to Android Beam file |
| transfer. |
| </p> |
| <p> |
| The Android Beam file transfer feature has the following requirements: |
| </p> |
| <ol> |
| <li> |
| Android Beam file transfer for large files is only available in Android 4.1 (API level 16) |
| and higher. |
| </li> |
| <li> |
| Files you want to transfer must reside in external storage. To learn more about using |
| external storage, read <a href="{@docRoot}guide/topics/data/data-storage.html#filesExternal" |
| >Using the External Storage</a>. |
| </li> |
| <li> |
| Each file you want to transfer must be world-readable. You can set this permission by |
| calling the method {@link java.io.File#setReadable File.setReadable(true,false)}. |
| </li> |
| <li> |
| You must provide a file URI for the files you want to transfer. Android Beam file transfer |
| is unable to handle content URIs generated by |
| {@link android.support.v4.content.FileProvider#getUriForFile FileProvider.getUriForFile}. |
| </li> |
| </ol> |
| |
| <h2 id="DeclareFeatures">Declare Features in the Manifest</h2> |
| <p> |
| First, edit your app manifest to declare the permissions and features your app needs. |
| </p> |
| <h3>Request Permissions</h3> |
| <p> |
| To allow your app to use Android Beam file transfer to send files from external storage using |
| NFC, you must request the following permissions in your app manifest: |
| </p> |
| <dl> |
| <dt> |
| {@link android.Manifest.permission#NFC NFC} |
| </dt> |
| <dd> |
| Allows your app to send data over NFC. To specify this permission, add the following element |
| as a child of the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html" |
| ><manifest></a></code> element: |
| <pre> |
| <uses-permission android:name="android.permission.NFC" /> |
| </pre> |
| </dd> |
| <dt> |
| {@link android.Manifest.permission#READ_EXTERNAL_STORAGE READ_EXTERNAL_STORAGE} |
| </dt> |
| <dd> |
| Allows your app to read from external storage. To specify this permission, add the following |
| element as a child of the |
| <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html" |
| ><manifest></a></code> element: |
| <pre> |
| <uses-permission |
| android:name="android.permission.READ_EXTERNAL_STORAGE" /> |
| </pre> |
| <p class="note"> |
| <strong>Note:</strong> As of Android 4.2.2 (API level 17), this permission is not |
| enforced. Future versions of the platform may require it for apps that want to read from |
| external storage. To ensure forward compatibility, request the permission now, before it |
| becomes required. |
| </p> |
| </dd> |
| </dl> |
| <h3>Specify the NFC feature</h3> |
| <p> |
| Specify that your app uses NFC, by adding a |
| <code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html" |
| ><uses-feature></a></code> element as a child |
| of the <code><a href="{@docRoot}guide/topics/manifest/manifest-element.html" |
| ><manifest></a></code> element. Set the <code>android:required</code> attribute to |
| <code>true</code> to indicate that your app won't function unless NFC is present. |
| </p> |
| <p> |
| The following snippet shows you how to specify the |
| <code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html" |
| ><uses-feature></a></code> element: |
| </p> |
| <pre> |
| <uses-feature |
| android:name="android.hardware.nfc" |
| android:required="true" /></pre> |
| <p> |
| Note that if your app only uses NFC as an option, but still functions if NFC isn't present, you |
| should set <code>android:required</code> to <code>false</code>, and test for NFC in code. |
| </p> |
| <h3>Specify Android Beam file transfer</h3> |
| <p> |
| Since Android Beam file transfer is only available in Android 4.1 (API level 16) and later, |
| if your app depends on Android Beam file transfer for a key part of its functionality you must |
| specify the <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html" |
| ><uses-sdk></a></code> element with the |
| <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min" |
| >android:minSdkVersion</a>="16"</code> attribute. Otherwise, you can set |
| <code><a href="{@docRoot}guide/topics/manifest/uses-sdk-element.html#min" |
| >android:minSdkVersion</a></code> to another value as necessary, and test for the platform |
| version in code, as described in the following section. |
| </p> |
| <h2 id="TestAndroidBeam">Test for Android Beam File Transfer Support</h2> |
| <p> |
| To specify in your app manifest that NFC is optional, you use the following element: |
| </p> |
| <pre> |
| <uses-feature android:name="android.hardware.nfc" android:required="false" /></pre> |
| <p> |
| If you set the attribute |
| <code><a href="guide/topics/manifest/uses-feature-element.html#required" |
| >android:required</a>="false"</code>, you must test for NFC support and Android Beam file |
| transfer support in code. |
| </p> |
| <p> |
| To test for Android Beam file transfer support in code, start by testing that the device |
| supports NFC by calling {@link android.content.pm.PackageManager#hasSystemFeature |
| PackageManager.hasSystemFeature()} with the argument |
| {@link android.content.pm.PackageManager#FEATURE_NFC FEATURE_NFC}. Next, check that the Android |
| version supports Android Beam file transfer by testing the value of |
| {@link android.os.Build.VERSION#SDK_INT}. If Android Beam file transfer is supported, get an |
| instance of the NFC controller, which allows you to communicate with the NFC hardware. |
| For example: |
| </p> |
| <pre> |
| public class MainActivity extends Activity { |
| ... |
| NfcAdapter mNfcAdapter; |
| // Flag to indicate that Android Beam is available |
| boolean mAndroidBeamAvailable = false; |
| ... |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| ... |
| // NFC isn't available on the device |
| if (!PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)) { |
| /* |
| * Disable NFC features here. |
| * For example, disable menu items or buttons that activate |
| * NFC-related features |
| */ |
| ... |
| // Android Beam file transfer isn't supported |
| } else if (Build.VERSION.SDK_INT < |
| Build.VERSION_CODES.JELLY_BEAN_MR1) { |
| // If Android Beam isn't available, don't continue. |
| mAndroidBeamAvailable = false; |
| /* |
| * Disable Android Beam file transfer features here. |
| */ |
| ... |
| // Android Beam file transfer is available, continue |
| } else { |
| mNfcAdapter = NfcAdapter.getDefaultAdapter(this); |
| ... |
| } |
| } |
| ... |
| }</pre> |
| |
| <h2 id="CreateCallback"> |
| Create a Callback Method that Provides Files |
| </h2> |
| <p> |
| Once you've verified that the device supports Android Beam file transfer, add a callback |
| method that the system invokes when Android Beam file transfer detects that the user wants |
| to send files to another NFC-enabled device. In this callback method, return an array of |
| {@link android.net.Uri} objects. Android Beam file transfer copies the files represented by |
| these URIs to the receiving device. |
| </p> |
| <p> |
| To add the callback method, implement the |
| {@link android.nfc.NfcAdapter.CreateBeamUrisCallback} interface and its method |
| {@link android.nfc.NfcAdapter.CreateBeamUrisCallback#createBeamUris createBeamUris()}. The |
| following snippet shows you how to do this: |
| </p> |
| <pre> |
| public class MainActivity extends Activity { |
| ... |
| // List of URIs to provide to Android Beam |
| private Uri[] mFileUris = new Uri[10]; |
| ... |
| /** |
| * Callback that Android Beam file transfer calls to get |
| * files to share |
| */ |
| private class FileUriCallback implements |
| NfcAdapter.CreateBeamUrisCallback { |
| public FileUriCallback() { |
| } |
| /** |
| * Create content URIs as needed to share with another device |
| */ |
| @Override |
| public Uri[] createBeamUris(NfcEvent event) { |
| return mFileUris; |
| } |
| } |
| ... |
| } |
| </pre> |
| <p> |
| Once you've implemented the interface, provide the callback to Android Beam file transfer by |
| calling {@link android.nfc.NfcAdapter#setBeamPushUrisCallback setBeamPushUrisCallback()}. The |
| following snippet shows you how to do this: |
| </p> |
| <pre> |
| public class MainActivity extends Activity { |
| ... |
| // Instance that returns available files from this app |
| private FileUriCallback mFileUriCallback; |
| ... |
| @Override |
| protected void onCreate(Bundle savedInstanceState) { |
| ... |
| // Android Beam file transfer is available, continue |
| ... |
| mNfcAdapter = NfcAdapter.getDefaultAdapter(this); |
| /* |
| * Instantiate a new FileUriCallback to handle requests for |
| * URIs |
| */ |
| mFileUriCallback = new FileUriCallback(); |
| // Set the dynamic callback for URI requests. |
| mNfcAdapter.setBeamPushUrisCallback(mFileUriCallback,this); |
| ... |
| } |
| ... |
| } |
| </pre> |
| <p class="note"> |
| <strong>Note:</strong> You can also provide the array of {@link android.net.Uri} objects |
| directly to the NFC framework through your app's {@link android.nfc.NfcAdapter} instance. Choose |
| this approach if you can define the URIs to transfer before the NFC touch event occurs. |
| To learn more about this approach, see {@link android.nfc.NfcAdapter#setBeamPushUris |
| NfcAdapter.setBeamPushUris()}. |
| </p> |
| <h2 id="ProvideUri">Specify the Files to Send</h2> |
| <p> |
| To transfer one or more files to another NFC-enabled device, get a file URI (a URI with a |
| <code>file</code> scheme) for each file and then add the URI to an array of |
| {@link android.net.Uri} objects. To transfer a file, you must also have permanent read access |
| for the file. For example, the following snippet shows you how to get a file URI from a file |
| name and then add the URI to the array: |
| </p> |
| <pre> |
| /* |
| * Create a list of URIs, get a File, |
| * and set its permissions |
| */ |
| private Uri[] mFileUris = new Uri[10]; |
| String transferFile = "transferimage.jpg"; |
| File extDir = getExternalFilesDir(null); |
| File requestFile = new File(extDir, transferFile); |
| requestFile.setReadable(true, false); |
| // Get a URI for the File and add it to the list of URIs |
| fileUri = Uri.fromFile(requestFile); |
| if (fileUri != null) { |
| mFileUris[0] = fileUri; |
| } else { |
| Log.e("My Activity", "No File URI available for file."); |
| } |
| </pre> |