Отправка файлов на другое устройство

Этот урок покажет вам, как создать своё приложение для отправки больших файлов на другое устройство с помощью передачи файлов Android Beam. Для отправки файлов, вы запрашиваете разрешение на использование NFC и внешних накопителей, проверяете, что устройство поддерживает NFC, а также предоставляет URI для передачи файлов Android Beam.

Функция передачи файлов Android Beam имеет следующие требования:

  1. Передача файлов Android Beam для больших файлов доступна только в Android 4.1 (API уровень 16) и выше.
  2. Файлы, которые вы хотите передать, должны находиться на внешнем накопителе. Чтобы узнать больше об использовании внешних накопителей, читайте Использование внешних накопителей.
  3. Каждый файл, который вы хотите передать должен быть доступен для чтения. Вы можете установить это разрешение с помощью метода File.setReadable(true,false).
  4. Вы должны предоставить URI для файлов, которые вы хотите передать. Передача файлов Android Beam не в состоянии справиться URI контента, генерируемыми FileProvider.getUriForFile.

Объявление функциональных возможностей в манифесте

Во-первых, отредактируйте манифест вашего приложение, объявив разрешения и функциональные возможности, обходимые вашему приложению.

Запросите разрешения

Чтобы разрешить вашему приложению использовать передачу файлов Android Beam для отправки файлов с внешних накопителей с помощью NFC, необходимо запросить следующие разрешения в манифесте вашего приложения:

NFC
Позволяет вашему приложению передавать данные по NFC. Чтобы указать это разрешение, добавьте следующий элемент в качестве дочернего <manifest> элемента:
    <uses-permission android:name="android.permission.NFC" />
READ_EXTERNAL_STORAGE
Позволяет вашему приложению чтение из внешнего хранилища. Чтобы указать это разрешение, добавьте следующий элемент в качестве дочернего <manifest> элемента:
    <uses-permission
            android:name="android.permission.READ_EXTERNAL_STORAGE" />

Примечание: По состоянию на Android 4.2.2 (уровень API 17), это разрешение не соблюдаются. Будущие версии платформы могут потребовать его у приложений, которые хотят читать из внешних накопителей. Для обеспечения прямой совместимости, запросите разрешения сейчас, прежде чем оно станет необходимым.

Укажите функцию NFC

Укажите, что ваше приложение использует NFC, добавив <uses-feature> элемент как дочерний <manifest> элемента. Установите 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 доступна только начиная с Android 4.1 (API уровень 16) и выше, если ключевая функциональность вашего приложения зависит от передачи файлов Android Beam, то необходимо указать <uses-sdk> элемент с android:minSdkVersion="16" атрибутом. В противном случае, вы можете установить android:minSdkVersion в другое значение по необходимости, и проверить версию платформы в коде, как описано в следующем разделе.

Проверить поддержку передачи файлов Android Beam

Чтобы указать в манифесте вашего приложения, что NFC не является обязательным для работы, вы можете использовать следующий элемент:

<uses-feature android:name="android.hardware.nfc" android:required="false" />

Если вы устанавливаете атрибут android:required="false", вы должны в коде проверить поддерживается ли NFC и передача файлов Android Beam.

Чтобы проверить поддержку передачи файлов Android Beam в коде, начните с проверки, что устройство поддерживает NFC, вызвав PackageManager.hasSystemFeature() с аргументом FEATURE_NFC. Затем проверьте, что версия Android поддерживает передачу файлов Android Beam, используя значение SDK_INT. Если передача файлов Android Beam поддерживается, получите экземпляр контроллера NFC, который позволяет взаимодействовать с оборудованием NFC. Например:

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);
        ...
        }
    }
    ...
}

Создание метода обратного вызова, предоставляющий файлы

После того, как вы убедились, что устройство поддерживает передачу файлов Android Beam, добавьте метод обратного вызова, который система вызовет, когда передача файлов Android Beam обнаружит, что пользователь хочет отправить файлы на другое NFC устройство. В этом методе обратного вызова, верните массив Uri объектов. Передача файлов Android Beam скопирует файлы, представленные этими URI, на принимающее устройство.

Чтобы добавить метод обратного вызова, реализуйте NfcAdapter.CreateBeamUrisCallback интерфейс и его метод createBeamUris(). Следующий фрагмент показывает, как это сделать:

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;
        }
    }
    ...
}

После того, как вы реализовали интерфейс, предоставьте метод обратного вызова для передачи файлов Android Beam, вызвав setBeamPushUrisCallback(). Следующий фрагмент показывает, как это сделать:

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);
        ...
    }
    ...
}

Примечание: Вы также можете предоставить массив Uri объектов непосредственно в библиотеку NFC через полученный экземпляр NfcAdapter . Выберите этот подход, если вы можете определить URI, которые необходимо передать, до возникновения сенсорного события NFC. Чтобы узнать больше об этом подходе, см. NfcAdapter.setBeamPushUris().

Укажите файлы для отправки

Для передачи одного или нескольких файлов на другое NFC устройство, получите URI файла (URI с file схемой) для каждого файла, а затем добавьте URI в массив Uri объектов. Чтобы передать файл, вы также должны иметь постоянный доступ на чтение файла. Например, следующий фрагмент показывает, как получить URI файла по имени файла, а затем добавить URI в массив:

        /*
         * 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.");
        }