本文译自:http://developer.android.com/training/beam-files/send-files.html
本文介绍如何使用Android的Beam文件传输器来设计一个把大文件发送给另一个设备的应用程序。要发送这些文件,你需要申请使用NFC和外部存储器的权限,因此你要确保你的设备支持NFC,并且要给Android的Beam文件传输器提供URIs。
Android的Beam文件传输器有以下要求:
1. 把Android的Beam文件传输器用于大文件只在Android4.1(API Level16)以后的版本中有效;
2. 你要传输的文件必须位于外部存储器。要了解外部存储器的使用方法,请阅读“使用外部存储器”
3. 你要传输的每个文件必须具有可阅读权限。通过调用File.setReadable(true,false)方法可以设置这个权限;
4. 你必须提供要传输的文件的URIs。Android的Beam文件传输器不能够处理由FileProvider.getUriForFile生成的内容URIs。
在清单中声明功能
首先,要在你的应用程序的清单文件中声明应用程序所需要的权限和功能。
申请权限
要允许你的应用程序使用Android的Beam文件传输器来发送来自外部存储器中的文件,就必须在应用程序的清单中申请以下权限:
NFC
允许你的应用程序利用NFC来发送数据。给<manifest>元素添加以下子元素,来指定NFC权限:
<uses-permissionandroid:name="android.permission.NFC"/>
READ_EXTERNAL_STORAGE
允许你的应用程序读取外部存储器。给<manifest>元素添加以下子元素,来指定外部存储器的读取权限:
<uses-permission
android:name="android.permission.READ_EXTERNAL_STORAGE" />
注意:Android4.2.2(API Level 17),不强制要求这个权限。但是,未来的平台版本可能会对想要从外部存储器上读取文件的应用程序要求这个权限,所以为了确保兼容性,在它变成必须的要求之前,我们申请这个权限。
指定NFC功能
通过给<manifest>元素添加<uses-feature>子元素,来指定使用NFC功能。把它的android:required属性设置为true,以此来指定只有在NFC存在的情况下,你的应用程序才可用。
以下示例显示了如何指定<uses-feature>元素:
<uses-feature
android:name="android.hardware.nfc"
android:required="true" />
注意,如果你的应用程序只是把NFC作为一个可选项,而且NFC不存在时依然可用,就应该把android:required属性设置为false,并且要测试代码中NFC功能。
指定Android的Beam文件传输器
因为Android的Beam文件传输器只在Android4.1(API Level 16)以后才有效,因此如果你的应用的关键功能依赖Android的Beam文件传输器,就必须指定带有android:minSdkVersion=”16”的<uses-sdk>元素。否则,你可以把android:minSdkVersion属性指定其他必要的值,并且要像下面描述的那样,在代码中检查相关平台的版本。
检查Android的Beam文件传输器的
支持
在你的应用程序的清单文件中,使用下例元素指定NFC是可选的:
<uses-featureandroid:name="android.hardware.nfc"android:required="false"/>
如果你把android:required属性设置为“false”,就必须在代码中检查NFC和Android的Beam文件传输器的相关支持。
首先,通过调用带有FEATURE_NFC参数的PackageManager.hasSystemFeature()方法,启动对设备是否支持NFC的检查,从而在代码中检查Android的Beam文件传输器的相关支持。接下来,通过检查SDK_INT的值来判断支持Android的Beam文件传输器的Android版本。如果Android的Beam文件传输器被支持,就获得一个NFC控制器的实例,它允许你跟NFC的硬件来通信。例如:
publicclassMainActivityextendsActivity{
...
NfcAdapter mNfcAdapter;
// Flag to indicate thatAndroid Beam is available
boolean mAndroidBeamAvailable = false;
...
@Override
protected void onCreate(BundlesavedInstanceState) {
...
// NFC isn'tavailable on the device
if (!PackageManager.hasSystemFeature(PackageManager.FEATURE_NFC)) {
/*
* Disable NFCfeatures here.
* For example,disable menu items or buttons that activate
* NFC-relatedfeatures
*/
...
// Android Beamfile 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;
/*
* DisableAndroid Beam file transfer features here.
*/
...
// AndroidBeam file transfer is available, continue
} else {
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
...
}
}
...
}
创建提供文件的回调方法
一旦确定设备支持Android的Beam文件传输器,就要添加一个供系统调用的回调方法,以便在Android的Beam文件传输器检测到用户想要把文件发送给另一个启用NFC的设备。在这个回到方法中,会返回一个Uri对象的数组。Android的Beam文件传输器会把这些URIs所代表的文件复制给接收设备。
实现NfcAdapter.CreateBeamUrisCallback接口和它的createBeamUris()方法,来添加回调方法。实现方式如下:
publicclassMainActivityextendsActivity{
...
// List of URIs to provideto Android Beam
private Uri[] mFileUris = new Uri[10];
...
/**
* Callback that Android Beam file transfercalls to get
* files to share
*/
private class FileUriCallback implements
NfcAdapter.CreateBeamUrisCallback {
public FileUriCallback() {
}
/**
* Create content URIs asneeded to share with another device
*/
@Override
public Uri[] createBeamUris(NfcEvent event) {
return mFileUris;
}
}
...
}
实现这个接口,通过调用setBeamPushUrisCallback()方法,把该接口的回调方法提供给Android的Beam文件传输器。例如:
publicclassMainActivityextendsActivity{
...
// Instance that returnsavailable files from this app
private FileUriCallbackmFileUriCallback;
...
@Override
protected void onCreate(BundlesavedInstanceState) {
...
// AndroidBeam file transfer is available, continue
...
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
/*
* Instantiate a new FileUriCallbackto handle requests for
* URIs
*/
mFileUriCallback = new FileUriCallback();
// Set thedynamic callback for URI requests.
mNfcAdapter.setBeamPushUrisCallback(mFileUriCallback,this);
...
}
...
}
注意:你还可以通过你的应用程序的NfcAdapter实例,直接把一个Uri对象数组提供给NFC框架,如果你能够在NFC接触事件发生之前,给Beam文件传输器定义URIs,就可以选择这种方法。有关这个方法的更多信息,请看NfcAdapter.setBeamPushUris()方法。
指定要发送的文件
要把一个或多个文件传输给另一个启用NFC的设备,就要获取每个文件的URI(带有文件方案的URI),并把URI添加到一个Uri对象数组中。对于要传输的文件,还必须要让文件永久性可读。例如,下列代码示例展示了如何获取从一个文件名称中获取该文件的URI,并把该URI添加到数组中:
/*
* Create a list of URIs, geta 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 URIfor 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 URIavailable for file.");
}