написать тег NFC в Android

Я работаю над приложением для Android, в котором вы пишете теги NFC. Вот код:

public class MainActivity extends Activity {
NfcAdapter adapter;
PendingIntent pendingIntent;
IntentFilter writeTagFilters[];
boolean writeMode;
Tag myTag;
Context context;

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Definimos el layout a usar
    setContentView(R.layout.activity_main);
    context = this;
    //Los elementos que vamos a usar en el layout
    Button btnWrite = (Button)findViewById(R.id.button);
    final TextView message = (TextView)findViewById(R.id.edit_message);
    //setOnCLickListener hará la acción que necesitamos
    btnWrite.setOnClickListener(new OnClickListener() {
@Override
public void onClick(View v) {
  try{
          //Si no existe tag al que escribir, mostramos un mensaje de que no existe.
          if(myTag == null){
              Toast.makeText(context, context.getString(R.string.error_notag), Toast.LENGTH_LONG).show();
          }else{
              //Llamamos al método write que definimos más adelante donde le pasamos por
              //parámetro el tag que hemos detectado y el mensaje a escribir.
              write(message.getText().toString(), myTag);
              Toast.makeText(context, context.getString(R.string.ok_write), Toast.LENGTH_LONG).show();
          }
   }catch(IOException e){
       Toast.makeText(context, context.getString(R.string.error_write),Toast.LENGTH_LONG).show();
       e.printStackTrace();
   }catch(FormatException e){
       Toast.makeText(context, context.getString(R.string.error_write), Toast.LENGTH_LONG).show();
       e.printStackTrace();
   }
 }

});

    adapter = NfcAdapter.getDefaultAdapter(this);
    pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
    IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
    tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
    writeTagFilters = new IntentFilter[]{tagDetected};
}
//El método write es el más importante, será el que se encargue de crear el mensaje 
//y escribirlo en nuestro tag.
private void write(String text, Tag tag) throws IOException, FormatException{
  //Creamos un array de elementos NdefRecord. Este Objeto representa un registro del mensaje NDEF   
  //Para crear el objeto NdefRecord usamos el método createRecord(String s)
  NdefRecord[] records = {createRecord(text)};
  //NdefMessage encapsula un mensaje Ndef(NFC Data Exchange Format). Estos mensajes están 
  //compuestos por varios registros encapsulados por la clase NdefRecord  
  NdefMessage message = new NdefMessage(records);
  //Obtenemos una instancia de Ndef del Tag
  Ndef ndef = Ndef.get(tag);
  ndef.connect();
  ndef.writeNdefMessage(message);
  ndef.close();
}
//Método createRecord será el que nos codifique el mensaje para crear un NdefRecord
private NdefRecord createRecord(String text) throws UnsupportedEncodingException{
    String lang = "us";
    byte[] textBytes = text.getBytes();
    byte[] langBytes = lang.getBytes("US-ASCII");
    int langLength = langBytes.length;
    int textLength = textBytes.length;
    byte[] payLoad = new byte[1 + langLength + textLength];

    payLoad[0] = (byte) langLength;

    System.arraycopy(langBytes, 0, payLoad, 1, langLength);
    System.arraycopy(textBytes, 0, payLoad, 1+langLength, textLength);

    NdefRecord recordNFC = new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_TEXT, new byte[0], payLoad);

    return recordNFC;

}
//en onnewIntent manejamos el intent para encontrar el Tag
protected void onNewIntent(Intent intent){
    if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
        myTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        Toast.makeText(this, this.getString(R.string.ok_detected) + myTag.toString(), Toast.LENGTH_LONG).show();

    }
}

public void onPause(){
    super.onPause();
    WriteModeOff();
}
public void onResume(){
    super.onResume();
    WriteModeOn();
}

private void WriteModeOn(){
    writeMode = true;
    adapter.enableForegroundDispatch(this, pendingIntent, writeTagFilters, null);
}

private void WriteModeOff(){
    writeMode = false;
    adapter.disableForegroundDispatch(this);
}

}

Тег определяется отлично, но если я пытаюсь в него записать, выдает следующую ошибку:

java.io.IOException
at android.nfc.tech.Ndef.writeNdefMessage(Ndef.java:313)
at com.example.nfc_prueba.MainActivity.write(MainActivity.java:91)
at com.example.nfc_prueba.MainActivity.access$0(MainActivity.java:76)

Тип тега: Mifare Classic 1K

Я не знаю, почему не пишет в нем. Есть идеи?

Большое спасибо!


person Enzo    schedule 29.10.2013    source источник
comment
Вы объявили android.permission.NFC в манифесте?   -  person Devrim    schedule 29.10.2013
comment
Вы должны пересмотреть свой подход к проектированию: в настоящее время вы получаете дескриптор тега при обнаружении тега, а позже (при щелчке где-либо) вы пытаетесь записать данные в тег. Однако NFC предназначен для очень коротких взаимодействий. Таким образом, ваш пользователь должен сначала указать, что при следующем касании тега должны быть записаны некоторые данные, затем приложение должно дождаться, пока пользователь коснется тега (отправка переднего плана), а затем, сразу после получения намерения обнаружения тега, данные должны быть записаны. быть записаны в тег.   -  person Michael Roland    schedule 29.10.2013


Ответы (1)


Большое спасибо за Вашу помощь. Наконец-то я нашел причину, по которой не записываются данные в тег. Мне пришлось переформатировать карту в NDEF с помощью этой функции:

NdefFormatable formatable = NdefFormatable.get(tag);

    if (formatable != null) {
      try {
        formatable.connect();

        try {
          formatable.format(message);
        }
        catch (Exception e) {
          // let the user know the tag refused to format
        }
      }
      catch (Exception e) {
        // let the user know the tag refused to connect
      }
      finally {
        formatable.close();
      }
    }
    else {
      // let the user know the tag cannot be formatted
    }

еще раз большое спасибо!

С уважением.

person Enzo    schedule 30.10.2013