2013-08-30 15:30:54 -07:00
|
|
|
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
|
2013-11-04 18:33:43 -08:00
|
|
|
<code><a href="{@docRoot}guide/topics/manifest/uses-feature-element.html#required"
|
2013-08-30 15:30:54 -07:00
|
|
|
>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>
|