Разработка приложений с поддержкой NFC для Android*

Введение

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

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

Архитектура NFC

Технология NFC основана на технологии радиометок RFID с использованием частоты 13,56 МГц. Типовое рабочее расстояние составляет до 10 см, а скорость передачи данных может достигать 424 кбит/с. Основным преимуществом NFC по сравнению с другими технологиями передачи данных является быстрота и простота использования. На следующем рисунке показано сравнение NFC с другими технологиями обмена данными.

Рисунок 1. Сравнение технологий передачи данных ближнего действия.

 

Технология NFC поддерживает три режима работы: режим эмуляции карт, режим обмена данными и режим считывания и записи, показанные на следующем рисунке.

Рисунок 2. Семейства протоколов NFC

 

В режиме эмуляции карт NFC работает как бесконтактная смарт-карта с радиометкой RFID и с модулем безопасности, что позволяет пользователям безопасно осуществлять покупки. В режиме обмена данными можно передавать данные между двумя находящимися рядом устройствами, поддерживающими NFC. Можно очень быстро и удобно создавать подключения WiFi* или Bluetooth* с помощью NFC, а затем передавать крупные файлы по подключению WiFi или Bluetooth. В режиме считывания и записи можно использовать устройства, поддерживающие NFC, для считывания меток NFC и запуска различных задач.

Все режимы более подробно описаны ниже.

Режим эмуляции карт NFC

Модуль NFC обычно состоит из двух компонентов: контроллера NFC и элемента безопасности (ЭБ). Контроллер NFC отвечает за обмен информацией. ЭБ отвечает за шифрование и расшифрование конфиденциальных данных.

Рисунок 3. Аппаратные компоненты NFC

 

ЭБ подключается к контроллеру NFC по протоколу SWP (Single Wire Protocol) или по шине DCLB (Digital Contactless Bridge). Стандарты NFC описывают логический интерфейс между устройством и контроллером, позволяя им обмениваться информацией по радио. ЭБ реализуется с помощью встроенного приложения или небольшой ОС.

ЭБ можно реализовать тремя способами:

  • встроить в SIM-карту
  • встроить в SD-карту
  • встроить в микросхему NFC

Рисунок 4. Три способа реализации элемента безопасности NFC

Операторы сотовой связи, такие как CMCC (China Mobile Communication Corporation), Vodafone и AT&T, обычно предпочитают решения с использованием SIM-карт и поощряют в этом пользователей, предлагая им бесплатную замену старых SIM-карт на новые, поддерживающие NFC.

Режим обмена данными NFC

Два устройства, поддерживающие NFC, могут подключиться друг к другу и обмениваться небольшими файлами, например визитными карточками. Кроме того, два устройства, поддерживающие NFC, могут обмениваться заранее настроенными XML-файлами и устанавливать подключение Bluetooth или Wi-Fi для передачи крупных файлов. В этом случае модуль ЭБ не требуется.

Режим считывания и записи NFC

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

Рисунок 5. Режим считывания и записи NFC

Введение в разработку приложений для Android, поддерживающих NFC

Android поддерживает NFC в двух пакетах: android.nfc и android.nfc.tech.

Основные классы в пакете android.nfc:

NfcManager: Можно использовать устройства Android для управления всеми указанными адаптерами NFC, но, поскольку в большинстве случаев устройства Android поддерживают только один адаптер NFC, вызов NfcManager обычно осуществляется непосредственно с getDefaultAdapter для получения определенного адаптера.

NfcAdapter: Работает в качестве агента NFC (наподобие сетевого адаптера в компьютере), с помощью которого сотовые телефоны получают доступ к оборудованию NFC для запуска обмена данными NFC.

NDEF: Стандарты NFC определяют общий формат данных. Он называется NFC Data Exchange Format (NDEF) и используется для хранения и передачи различной информации — от объектов с типом MIME до сверхкратких документов, передаваемых по радио, например URL-адресов. NdefMessage и NdefRecord являются двумя видами NDEF для форматов данных, определенных форумом NFC. Они используются в нашем образце кода.

Tag: Согласно определению Android, этот класс представляет пассивные объекты, такие как радиометки, карточки и т. п. Когда устройство обнаруживает метку, Android создает объект tag и помещает его в объект Intent, который отправляется соответствующему действию.

Пакет android.nfc.tech также содержит множество важных подклассов. Эти подклассы обеспечиваю доступ к функциям технологии радиометок, в том числе к операциям чтения и записи. В зависимости от типа используемой технологии эти классы разделяются на различные категории, например NfcA, NfcB, NfcF, MifareClassic и пр.

Если в телефоне включен модуль NFC, то после обнаружения метки система распределения автоматически создаст пакет с информацией класса переходов. Если телефон содержит несколько приложений, способных работать с этим классом переходов, появится всплывающее окно, в котором пользователю будет предложено выбрать нужное действие с меткой. Система распределения определяет три типа классов переходов. Вот они (в порядке убывания важности):

NDEF_DISCOVERED, TECH_DISCOVERED, TAG_DISCOVERED

Мы используем здесь тип intent-filter для обработки всех типов от TECH_DISCOVERED до ACTION_TECH_DISCOVERED. Файл nfc_tech_filter.xml используется для всех типов, определенных в файле TAG. Подробные сведения см. в документации Android. На приведенном ниже рисунке показано действие соответствующего процесса при обнаружении телефоном радиометки.

Рисунок 6. Процесс работы при обнаружении метки NFC

Пример: Разработка приложения для чтения и записи информации на базе NFC

Ниже показано, как работает чтение и запись меток NFC. Перед доступом к модулю NFC устройства и к обработке классов переходов NFC нужно объявить следующие элементы в файле AndroidManifest.xml:

<uses-permission android:name="android.permission.NFC" />

Наименьшей версией SDK, которую должно поддерживать ваше приложение, является уровень 10, поэтому объявляем эти элементы в файле AndroidManifest.xml:

<uses-sdk android:minSdkVersion="10"/>

In the onCreate function,you can apply the NfcAdapter:

public void onCreate(Bundle savedInstanceState) {
……
adapter = NfcAdapter.getDefaultAdapter(this);
……
}  

Следующий обратный вызов класса переходов показывает функцию считывания. Если класс переходов вещания системы равен NfcAdapter.ACTION_TAG_DISCOVERED, то можно прочитать информацию в радиометке и отобразить ее.

@Override
	protected void onNewIntent(Intent intent){
		if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
		mytag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);  // get the detected tag
		Parcelable[] msgs =
intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
			NdefRecord firstRecord = ((NdefMessage)msgs[0]).getRecords()[0];
			byte[] payload = firstRecord.getPayload();
			int payloadLength = payload.length;
			int langLength = payload[0];
			int textLength = payloadLength - langLength - 1;
			byte[] text = new byte[textLength];
			System.arraycopy(payload, 1+langLength, text, 0, textLength);
			Toast.makeText(this, this.getString(R.string.ok_detection)+new String(text), Toast.LENGTH_LONG).show();
					}
	}

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

If (mytag==Null){
	……
}
else{
……
write(message.getText().toString(),mytag);
……
}
	private void write(String text, Tag tag) throws IOException, FormatException {
		NdefRecord[] records = { createRecord(text) };
		NdefMessage  message = new NdefMessage(records);
// Get an instance of Ndef for the tag.
		Ndef ndef = Ndef.get(tag); // Enable I/O
		ndef.connect(); // Write the message
		ndef.writeNdefMessage(message); // Close the connection
		ndef.close();
	}

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

Пример: Разработка приложения на базе NFC, использующего карту MifareClassic

Мы используем карту Mifare для теста считывания карты и используем тип TAG карты MifareClassic. Карта MifareClassic широко используется в самых различных целях: как удостоверение личности,для оплаты проезда на общественном транспорте и т. п. Память традиционной карты MifareClassic разделяется на 16 секторов, каждый сектор включает 4 блока, а каждый блок может содержать 16 байт данных.

Последний блок в каждой области называется трейлером, он используется главным образом для сохранения локального ключа блока для чтения и записи данных. Он содержит два ключа, A и B, длиной по 6 байт каждый, значение по умолчанию обычно равно FF или 0 для всего ключа согласно определению MifareClassic.KEY_DEFAULT.

При записи на карту Mifare нужно сначала получить правильное значение ключа (для защиты). Перед тем как пользователь получит возможность чтения и записи данных в эту область, нужно пройти проверку подлинности.

<manifest xmlns:android="http://schemas.android.com/apk/res/android"   
    package="org.reno"   
    android:versionCode="1"   
    android:versionName="1.0" >   
    <uses-permission android:name="android.permission.NFC" />   
    <uses-sdk android:minSdkVersion="14" />   
    <uses-feature android:name="android.hardware.nfc" android:required="true" />   
    <application   
        android:icon="@drawable/ic_launcher"   
        android:label="@string/app_name" >   
        <activity   
            android:name="org.reno.Beam"   
            android:label="@string/app_name"   
            android:launchMode="singleTop" >   
            <intent-filter>   
                <action android:name="android.intent.action.MAIN" />   
   
                <category android:name="android.intent.category.LAUNCHER" />   
            </intent-filter>   
            <intent-filter>   
                <action android:name="android.nfc.action.TECH_DISCOVERED" />   
            </intent-filter>   
            <meta-data   
                android:name="android.nfc.action.TECH_DISCOVERED"   
                android:resource="@xml/nfc_tech_filter" />   
        </activity>  
    </application>   
</manifest>   

res/xml/nfc_tech_filter.xml:

<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> 
    <tech-list> 
       <tech>android.nfc.tech.MifareClassic</tech> 
    </tech-list> 
</resources> 

Вот пример чтения данных с карты MifareClassic:


     private void processIntent(Intent intent) {    
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);   
        for (String tech : tagFromIntent.getTechList()) {   
            System.out.println(tech);   
        }   
        boolean auth = false;   
        MifareClassic mfc = MifareClassic.get(tagFromIntent);   
        try {   
            String metaInfo = "";   
            //Enable I/O operations to the tag from this TagTechnology object.   
            mfc.connect();   
            int type = mfc.getType(); 
            int sectorCount = mfc.getSectorCount();   
            String typeS = "";   
            switch (type) {   
            case MifareClassic.TYPE_CLASSIC:   
                typeS = "TYPE_CLASSIC";   
                break;   
            case MifareClassic.TYPE_PLUS:   
                typeS = "TYPE_PLUS";   
                break;   
            case MifareClassic.TYPE_PRO:   
                typeS = "TYPE_PRO";   
                break;   
            case MifareClassic.TYPE_UNKNOWN:   
                typeS = "TYPE_UNKNOWN";   
                break;   
            }   
            metaInfo += "Card type:" + typeS + "n with" + sectorCount + " Sectorsn, "   
                    + mfc.getBlockCount() + " BlocksnStorage Space: " + mfc.getSize() + "Bn";   
            for (int j = 0; j < sectorCount; j++) {   
                //Authenticate a sector with key A.   
                auth = mfc.authenticateSectorWithKeyA(j,   
                        MifareClassic.KEY_DEFAULT);   
                int bCount;   
                int bIndex;   
                if (auth) {   
                    metaInfo += "Sector " + j + ": Verified successfullyn";   
                    bCount = mfc.getBlockCountInSector(j);   
                    bIndex = mfc.sectorToBlock(j);   
                    for (int i = 0; i < bCount; i++) {   
                        byte[] data = mfc.readBlock(bIndex);   
                        metaInfo += "Block " + bIndex + " : "   
                                + bytesToHexString(data) + "n";   
                        bIndex++;   
                    }   
                } else {   
                    metaInfo += "Sector " + j + ": Verified failuren";   
                }   
            }   
            promt.setText(metaInfo);   
        } catch (Exception e) {   
            e.printStackTrace();   
        }   
    }   

Заключение

Смартфоны, оборудованные модулем NFC, позволяют пользователям легко и удобно выполнять различные полезные задачи, а не искать по карманам корешки билетов и пропуски на парковку. Эта технология также дает возможность подключаться к друзьям для обмена информацией, игр и передачи данных. Технология NFC удобна и для работы, и для развлечений. Она сыграет важнейшую роль для того, чтобы сделать нашу жизнь удобнее в самом ближайшем будущем.

Об авторах

Songyue Wang и Liang Zhang работают инженерами по разработке приложений в отделе Intel Software and Service Group. Они занимаются поддержкой мобильных приложений, включая разработку приложений для Android и их оптимизацию для платформы x86, а также разработкой веб-приложений HTML5.

Для получения подробной информации о возможностях оптимизации компилятора обратитесь к нашему Уведомлению об оптимизации.