Pull to refresh
0

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

Reading time 7 min
Views 79K
Original author: Liang Zhang

NFC (near field communication) – стандартизированная технология обмена данными на короткие расстояния, позволяющая осуществлять взаимодействия между двумя электронными устройствами простым и интуитивно понятным способом. Например, с помощью оснащенного NFC смартфона вы можете делать покупки, раздавать визитные карты, скачивать купоны на скидки и так далее. Множество новых применений для NFC будет найдено в ближайшее время.
Эта статья описывает технологии, использующие NFC и способы их применения на сегодняшний день. Также показано, как использовать NFC в Android приложениях и, наконец, приведены два примера NFC приложений с исходными кодами.

Архитектура технологии NFC

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



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



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

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

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



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



Существует три варианта реализации ЭБ: можно встроить его в SIM-карту, SD-карту или в NFC чип.



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

Пиринговый режим

Два NFC устройства могут легко взаимодействовать друг с другом напрямую, обмениваясь небольшими файлами. Для установления Bluetooth/WiFi соединения необходимо обменяться XML файлом специального формата. В этом режиме ЭБ не используется.

Режим записи/чтения

В данном режиме NFC устройство может читать и записывать NFC метки. Хорошим примером применения является чтение информации с оснащенных NFC «умных» постеров.



Введение в разработку NFC под Android

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 и заканчивая ультра-короткими RTD-документами, такими как URL. NdefMessage и NdefRecord – два типа NDEF для определенных NFC форумом форматов данных, которые будут использоваться в коде-примере.
Tag: Когда устройство Android обнаруживает пассивный объект типа ярлыка, карты и т.д., он создает объект типа «метка», помещая его далее в целевой объект и в заключении пересылая в соответствующий процесс.
Пакет android.nfc.tech также содержит множество важных подклассов. Эти подклассы обеспечивают доступ к функциям работы с метками, включающими в себя операции чтения и записи. В зависимости от используемого типа технологий, эти классы разбиты на различные категории, такие как NfcA, NfcB, NfcF, MifareClassic и так далее.
Когда телефон со включенным NFC обнаруживает метку, система доставки автоматически создает пакет целевой информации. Если в телефоне имеется несколько приложений, способных работать с этой целевой информаций, пользователю будет показано окно с предложением выбрать одно из списка. Система доставки меток определяет три типа целевой информации, в порядке убывания приоритета: NDEF_DISCOVERED, TECH_DISCOVERED, TAG_DISCOVERED.
Здесь мы используем целевой фильтр для работы со всеми типами информации начиная с TECH_DISCOVERED до ACTION_TECH_DISCOVERED. Файл nfc_tech_filter.xml используется для всех типов, определенных в метке. Подробности можно найти в документации Android. Рисунок ниже показывает схему действий при обнаружении метки.



Пример 1. Разработка 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, вы должны убедиться, что метка определена и только потом вписать в нее свои данные.

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

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

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

В этом примере для чтения мы будем использовать карты MifareClassic и соответствующий им тип метки. Карты MifareClassic широко используются для различных нужд, таких как идентификация человека, автобусный билет и т.д. В традиционной карте MifareClassic область хранения разбита на 16 зон, в каждой зоне 4 блока, и каждый блок может хранить 16 байт данных.
Последний блок в зоне называется трейлером и используется обычно для хранения локального ключа чтения/записи. Он содержит два ключа, А и В, 6 байт длиной каждый, по умолчанию забитые 00 или FF, в зависимости от значения 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();   
	    }   
	}

Об авторах

Songyue Wang и Liang Zhang — инженеры в Intel Software and Service Group, разрабатывающие мобильные приложения, в том числе и для Android, и оптимизирующие их под платформу х86.
Tags:
Hubs:
+42
Comments 21
Comments Comments 21

Articles

Information

Website
www.intel.ru
Registered
Founded
Employees
5,001–10,000 employees
Location
США
Representative
Анастасия Казантаева