КАК НАПИСАТЬ МЕТКУ NFC ИЗ ПРИЛОЖЕНИЯ ДЛЯ ANDROID

Lord777

Professional
Messages
2,583
Reputation
15
Reaction score
1,254
Points
113
ВСТУПЛЕНИЕ
Запись данных в теги NFC часто неправильно понимается и поэтому может показаться более трудным, чем есть на самом деле. Android, Windows 8 и Windows Phone 8 сделали этот процесс проще, чем когда-либо, абстрагировав многие мельчайшие детали в несколько сжатых API. Базовый процесс очень похож: обнаружение тега, подключение к нему, написание сообщения и закрытие соединения.

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

ОБНАРУЖИТЬ ТЕГ
Прошли те времена, когда запись в теги NFC была разной в зависимости от того, какая технология тегов использовалась. MIFARE Ultralight, DESFire, Felica и Topaz - это разные типы тегов, которые ведут себя по-разному на низком уровне. Раньше это означало, что для обработки каждого типа тегов нужно было писать другой код, но теперь это не так.

Если вы пишете данные NFC (более известные как сообщения NDEF), как правило, вам все равно, с каким тегом вы работаете, поскольку все они будут вести себя одинаково с вашей точки зрения. ОС делает это за нас. Мы начинаем с того, что получаем уведомление о том, что пользователь только что разместил метку на своем устройстве.

Добавьте эти строки в каждый документ, чтобы начать:
Code:
AndroidManifest.xml
<uses-feature android:name="android.hardware.nfc" />
<uses-permission android:name="android.permission.NFC" />
<application
  ..
  <activity
    ..
    <intent-filter>
      <action android:name="android.nfc.action.NDEF_DISCOVERED" />
      <category android:name="android.intent.category.DEFAULT" />
    </intent-filter>
  </activity>
</application>
 
MainActivity.java
@Override
protected void onNewIntent(Intent intent){
  // If the intent caught is a NFC tag, handle it
  if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
    Tag myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
    if (mytag != null) {
      // If you want to, here is where you can read information off of the tag
      // ie, myTag.getId() or intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
      WriteTextTag(“hello world”, myTag);
    }
  }
}

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

ПОДКЛЮЧИТЬСЯ, НАПИСАТЬ И ЗАКРЫТЬ
Теперь, когда у нас есть тег, мы хотим получить из него объект NDEF, так как это уровень, на котором мы работаем с NFC. Нам также необходимо создать сообщение NDEF с текстовой записью NDEF в нем. Способ разделения данных NFC на уровни заключается в том, что тег обычно содержит ноль или одно сообщение NDEF, а сообщение NDEF может содержать одну или несколько записей NDEF.

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

Code:
MainActivity.java
private void WriteTextTag(String text, Tag tag) {
  try {
    // Create a text record according to the NFC Forum Text Record Type Definition
    NdefRecord[] records = { createTextRecord(text) };
    // Add that record to a message
    NdefMessage message = new NdefMessage(records);
    // Get an instance of Ndef for the tag
    Ndef ndef = Ndef.get(tag);
    // Do the connect and write in different thread
    new AsyncConnectWrite().execute(message, ndef);
  } catch (UnsupportedEncodingException e) {
    // US-ASCII character set should always be supported, but if not this will run
    e.printStackTrace();
  }
}
private NdefRecord createTextRecord(String text) throws UnsupportedEncodingException {
  // Convert the text to hex (with the default UTF-8) and get the length
  byte[] textBytes  = text.getBytes();
  int textLength = textBytes.length;
  // Convert to the text language to hex (ensuring US-ASCII) and get the length
  String lang       = “en”;
  byte[] langBytes  = lang.getBytes(“US-ASCII”);
  int langLength = langBytes.length;
  // Make an array of the proper size to hold the status byte, language, and text
  byte[] payload    = new byte[1 + langLength + textLength];
  // Set the status byte (which is only the length in our case of using UTF-8)
  payload[0] = (byte) langLength;
  // Copy langbytes and textbytes into the payload
  System.arraycopy(langBytes, 0, payload, 1, langLength);
 System.arraycopy(textBytes, 0, payload, 1 + langLength, textLength);
 // Create an Android NdefRecord with TNF=well known and RTD=text with the payload we created
// There is a single record, so no ID is needed
 return new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payload);
}
private class AsyncConnectWrite extends AsyncTask<Object, Void, String> {
        @Override
        protected String doInBackground(Object… params) {
            String result = “”;
            final String className = MainActivity.class.getSimpleName();
 
            NdefMessage message = (NdefMessage) params[0];
            Ndef ndef = (Ndef) params[1];
            try {
                if (ndef != null) {
                    // Try to connect to the tag
                    ndef.connect();
                    if (ndef.isConnected()) {
                        // Write the message
                        ndef.writeNdefMessage(message);
                    }
                }
            } catch (FormatException e) {
                Log.e(className, “FormatException while writing…”, e);
                result = “FormatException while writing”;
            } catch (TagLostException e) {
                Log.e(className, “TagLostException while writing…”, e);
                result = “TagLostException while writing”;
            } catch (IOException e) {
                Log.e(className, “IOException while writing…”, e);
                result = “IOException while writing”;
            }finally {
                try {
                    if (ndef != null) {
                        ndef.close();
                        result = “Message written!”;
                    }
                } catch (IOException e) {
                    Log.e(className, “IOException while closing…”, e);
                    result = “IOException while closing”;
                }
            }
            return result;
        }
        @Override
        protected void onPostExecute(String result) {
            if (!result.isEmpty()) {
                Toast.makeText(ctx, result, Toast.LENGTH_LONG).show();
 
            }
        }
    }

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

4 ВАЖНЕЙШИХ ЭЛЕМЕНТА, О КОТОРЫХ СЛЕДУЕТ ПОМНИТЬ
Обнаружение тега - включите NFC и зарегистрируйте свое приложение для получения намерения
Подключиться к тегу - используйте ndef.connect () вне основного потока в случае возникновения проблемы или задержки.
Запишите в тег - создайте сообщение NDEF с записями. по вашему выбору, и напишите их после подключения
Закройте соединение - если соединение было открыто, убедитесь, что закрыли его независимо от того, была ли запись успешной
 
Top