Статьи

Совместное использование файлов с NFC на Android

В этом руководстве вы познакомитесь с основами P2P (peer-to-peer) взаимодействия и создадите приложение для обмена большими файлами, такими как изображения и видео, с одного устройства на другое, используя NFC (ближняя связь) на Android.

NFC или Near Field Communication — это набор беспроводных технологий ближнего действия. Он обеспечивает обмен данными между тегом NFC и устройством с поддержкой NFC или между устройствами с поддержкой NFC на расстоянии не более 4 см.

Существует три режима работы NFC:

  • Чтение и запись бесконтактных меток. Эти метки, как правило, очень маленькие и не требуют заряда аккумулятора. Они могут быть встроены во все виды объектов, таких как постеры фильмов, продукты, наклейки и так далее.
  • Режим эмуляции карт: думайте об умных кредитных картах. Это позволяет устройству Android работать как смарт-карта. Очевидным преимуществом этого является то, что ваше устройство может действовать как одна карта, а затем действовать как другая при нажатии кнопки. Это один из способов, которым устройство Android может заменить ваш кошелек. Независимо от того, какую кредитную карту, проездной билет или билет вы используете, ваше устройство Android может олицетворять — конечно же, безопасно — этот элемент. Читатель на другой стороне транзакции считает, что он взаимодействует с этим элементом, хотя на самом деле он работает с устройством Android.
  • Одноранговая связь: каждая сторона признает, что общается с другим устройством, а не просто с тегом. Протокол был разработан Google и позволяет двум устройствам отправлять сообщения туда и обратно.

Функция обмена данными между равноправными узлами (P2P) была добавлена ​​в Android на уровне API 14 (Android 4.0, Ice Cream Sandwich) и называется Android Beam . Он обеспечивает быстрый обмен данными на коротких расстояниях между двумя устройствами Android с поддержкой NFC.

Функция обмена данными Android Beam имеет два API: API передачи NDEF и API передачи файлов .

Этот API был представлен на уровне API 14 (Android 4.0, Ice Cream Sandwich) и позволяет передавать небольшие объемы данных, такие как URL-адреса, контакты и т. Д. Данные для передачи должны быть отформатированы в NDEF (формат обмена данными NFC) и должны отправлено как сообщение NDEF.

API передачи файлов был представлен на уровне API 16 (Android 4.1, Jelly Bean) и позволяет передавать большие файлы, такие как изображения, видео и т. Д.

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

API передачи файлов Android Beam имеет два дополнительных требования:

  • Файлы, которые необходимо передать, должны находиться во внешнем хранилище.
  • Файлы, которые необходимо передать, должны быть доступны для чтения всем.

В этом руководстве мы будем использовать API передачи файлов Android Beam из Android SDK, чтобы создать приложение, позволяющее пользователям обмениваться файлами между устройствами.

Из-за ограничений эмулятора приложение необходимо протестировать на двух физических устройствах Android с поддержкой NFC под управлением Android 4.1 или выше.

Используя Eclipse, создайте новый проект приложения для Android и назовите его NFCDemo .

Настройки проекта

Поскольку передача файлов Android Beam доступна только на устройствах под управлением Android 4.1+, нам необходимо установить для Minimum Required SDK значение API 16: Android 4.1 (Jelly Bean) .

Чтобы использовать NFC в приложении Android, мы должны объявить разрешение NFC в файле манифеста, как показано ниже.

1
2
<uses-permission
   android:name=»android.permission.NFC» />

Кроме того, для чтения файлов из внешнего хранилища объявите разрешение READ_EXTERNAL_STORAGE как показано ниже.

1
2
<uses-permission
   android:name=»android.permission.READ_EXTERNAL_STORAGE» />

Не каждое устройство Android поддерживает NFC. Чтобы убедиться, что наше приложение отображается в Google Play только для тех устройств, которые поддерживают NFC, добавьте элемент <uses-feature> в файл манифеста.

1
2
3
<uses-feature
   android:name=»android.hardware.nfc»
   android:required=»true» />

Если NFC является необязательной функцией вашего приложения, вы можете пропустить элемент <uses-feature> из файла манифеста и установить минимальную версию SDK на более низкий уровень API. В этом случае вам необходимо проверить, поддерживает ли устройство NFC и API Android Beam, и соответствующим образом обновить пользовательский интерфейс.

Откройте файл макета activity_main.xml и добавьте Button как показано ниже. Как вы можете видеть, мы добавили Button которую пользователь может нажать, чтобы начать передачу файла.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
<RelativeLayout
    xmlns:android=»http://schemas.android.com/apk/res/android»
    xmlns:tools=»http://schemas.android.com/tools»
    android:layout_width=»match_parent»
    android:layout_height=»match_parent»
    android:padding=»16dp» >
         
    <Button
        android:layout_width=»fill_parent»
        android:layout_height=»wrap_content»
        android:padding=»8dp»
        android:text=»Send File»
        android:onClick=»sendFile» />
 
</RelativeLayout>

Откройте класс MainActivity и замените текущую реализацию показанной ниже. Не беспокойтесь о реализации на данный момент. Я объясню каждый шаг в данный момент.

01
02
03
04
05
06
07
08
09
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
package com.tutsplus.nfcdemo;
 
import java.io.File;
 
import android.app.Activity;
import android.content.Intent;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.nfc.NfcAdapter;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.provider.Settings;
import android.view.View;
import android.widget.Toast;
 
public class MainActivity extends Activity {
     
    private NfcAdapter nfcAdapter;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
         
        PackageManager pm = this.getPackageManager();
        // Check whether NFC is available on device
        if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
            // NFC is not available on the device.
            Toast.makeText(this, «The device does not has NFC hardware.»,
                            Toast.LENGTH_SHORT).show();
        }
        // Check whether device is running Android 4.1 or higher
        else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
            // Android Beam feature is not supported.
            Toast.makeText(this, «Android Beam is not supported.»,
                            Toast.LENGTH_SHORT).show();
        }
        else {
            // NFC and Android Beam file transfer is supported.
            Toast.makeText(this, «Android Beam is supported on your device.»,
                            Toast.LENGTH_SHORT).show();
        }
    }
     
    public void sendFile(View view) {
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
         
        // Check whether NFC is enabled on device
        if(!nfcAdapter.isEnabled()){
            // NFC is disabled, show the settings UI
            // to enable NFC
            Toast.makeText(this, «Please enable NFC.»,
                            Toast.LENGTH_SHORT).show();
            startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));
        }
        // Check whether Android Beam feature is enabled on device
        else if(!nfcAdapter.isNdefPushEnabled()) {
            // Android Beam is disabled, show the settings UI
            // to enable Android Beam
            Toast.makeText(this, «Please enable Android Beam.»,
                            Toast.LENGTH_SHORT).show();
            startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
        }
        else {
            // NFC and Android Beam both are enabled
         
            // File to be transferred
            // For the sake of this tutorial I’ve placed an image
            // named ‘wallpaper.png’ in the ‘Pictures’ directory
            String fileName = «wallpaper.png»;
         
            // Retrieve the path to the user’s public pictures directory
            File fileDirectory = Environment
                                    .getExternalStoragePublicDirectory(
                                            Environment.DIRECTORY_PICTURES);
         
            // Create a new file using the specified directory and name
            File fileToTransfer = new File(fileDirectory, fileName);
            fileToTransfer.setReadable(true, false);
         
            nfcAdapter.setBeamPushUris(
                            new Uri[]{Uri.fromFile(fileToTransfer)}, this);
        }
    }
}

Прежде чем мы углубимся в код, давайте посмотрим, какие шаги нам нужно предпринять для передачи файла с одного устройства на другое.

Подключите одно из двух устройств Android к рабочей станции разработчика через USB с включенной отладкой USB . Давайте назовем это устройство отправителем .

Включить NFC и Android Beam на отправителя. Нажмите F11 для отладки приложения. Это установит и запустит NFCDemo на отправителе.

Включите NFC на втором устройстве, приемнике .

Нажмите кнопку « Отправить файл» и расположите устройства близко друг к другу, чтобы позволить NFC выполнять свою работу. На отправителе должно появиться сообщение Touch to ray. Нажмите на экран, чтобы начать передачу.

Интерфейс Touch to ray, отображаемый на отправителе

Получатель должен отобразить уведомление в строке состояния, чтобы указать ход передачи файла.

Уведомление о входящем луче, отображаемое на приемнике

Если передача файла завершена успешно, пользователю отображается сообщение завершения луча .

Уведомление о завершении луча, отображаемое на приемнике

Давайте посмотрим на код, который делает все это возможным.

Как упоминалось ранее, если NFC является дополнительной функцией нашего приложения, мы должны проверить поддержку NFC и Android Beam. Эта проверка может быть выполнена в любом месте нашего приложения. В этом примере я поместил код в метод MainActivity класса MainActivity .

Получите ссылку на PackageManager .

1
PackageManager pm = this.getPackageManager();

Класс PackageManager содержит информацию обо всех пакетах, установленных на устройстве.

Вызовите метод hasSystemFeature для объекта hasSystemFeature чтобы определить, поддерживает ли устройство NFC. Этот метод возвращает true если требуемая функция поддерживается устройством.

1
2
3
4
5
6
if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
  // NFC is not available on the device.
}
else {
  // NFC is available on the device.
}

Если устройство поддерживает NFC, то мы должны проверить версию Android устройства. Версия Android (уровень API), работающая на устройстве, доступна через android.os.Build.VERSION.SDK_INT . Если версия больше или равна 16, Build.VERSION_CODES.JELLY_BEAN , то устройство поддерживает передачу файлов Android Beam.

01
02
03
04
05
06
07
08
09
10
if (!pm.hasSystemFeature(PackageManager.FEATURE_NFC)) {
  // NFC is not available on the device.
}
// Check whether device is running Android 4.1 or higher
else if (Build.VERSION.SDK_INT < Build.VERSION_CODES.JELLY_BEAN) {
    // Android Beam feature is not supported.
}
else {
  // NFC and Android Beam file transfer is supported.
}

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

Получите ссылку на NfcAdapter .

1
nfcAdapter = NfcAdapter.getDefaultAdapter(this);

Задача NfcAdapter — управлять обменом данными между тегом NFC и устройством с поддержкой NFC или между двумя устройствами с поддержкой NFC.

Адаптер можно включить или отключить. Чтобы определить, включен ли адаптер, вызовите метод NfcAdapter объекта NfcAdapter .

1
2
3
4
5
6
7
// Check whether NFC is enabled on device
if (!nfcAdapter.isEnabled()) {
  // NFC is disabled, show the settings UI to enable NFC
}
else {
  // NFC is enabled
}

Этот метод возвращает true   если NFC включен на устройстве. Если NFC отключен, мы предлагаем пользователю включить его и показать пользовательский интерфейс настроек NFC.

1
startActivity(new Intent(Settings.ACTION_NFC_SETTINGS));

Аналогично, функция Android Beam также может быть включена или отключена. Чтобы проверить его состояние, вызовите метод NfcAdapter объекта NfcAdapter .

01
02
03
04
05
06
07
08
09
10
11
// Check whether NFC is enabled on device
if (!nfcAdapter.isEnabled()) {
  // NFC is disabled, show the settings UI to enable NFC
}
// Check whether Android Beam feature is enabled on device
else if (!nfcAdapter.isNdefPushEnabled()) {
  // Android Beam is disabled, show the settings UI to enable Android Beam
}
else {
  // NFC and Android Beam both are enabled
}

Если этот метод возвращает false , мы предлагаем пользователю включить его и показать пользовательский интерфейс настроек Android Beam.

1
startActivity(new Intent(Settings.ACTION_NFCSHARING_SETTINGS));
Пользовательский интерфейс настроек NFC

Если включены и NFC, и Android Beam, мы можем продолжить передачу файла.

Создайте новый File используя каталог, в котором расположен файл на устройстве, и имя файла. Чтобы проверить передачу файлов, я добавил изображение с именем wallpaper.png в каталог Pictures во внешнем хранилище.

1
2
// Create a new file using the specified directory and name
File fileToTransfer = new File(fileDirectory, fileName);

Вызовите метод NfcAdapter объекта NfcAdapter и передайте URI файла для передачи.

1
2
nfcAdapter.setBeamPushUris(new Uri[]{Uri.fromFile(fileToTransfer)},
                           this);

Метод setBeamPushUris принимает массив объектов Uri . Если вы хотите отправить более одного файла, вы можете передать несколько URI адаптеру.

URI, переданные методу setBeamPushUris помещаются в очередь адаптером и передаются на принимающее устройство, как только оно оказывается в непосредственной близости от отправляющего устройства.

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

Хотя я попытался осветить основы работы с API-интерфейсом передачи файлов Android Beam, чтобы помочь вам начать работу, еще многое предстоит изучить. Если вы хотите узнать больше, я советую вам посетить портал разработчиков Android для получения дополнительной информации.