Получение NFC TagID смарт-карты NTAG и MIFARE

Я новичок в технологии NFC и подумал начать с чтения и записи тега. Для чтения я использую смарт-карту MIRFARE 1K, а для записи использую NTAG203. Все, что я хочу, это получить TagID в процессе чтения и отправить TagID и отметку даты и времени на NTAG203.

Проблемы:

  1. Мое приложение испытывает трудности при компиляции. Он продолжает выдавать мне ошибку при создании окончательного архива: не удалось создать «C:\Android WS\TabletApp\bin\TabletApp.apks»: ошибка «Отказано в доступе». Я очищаю проект и перезапускаю Eclipse, но тщетно. Пропадает только после перезагрузки ноутбука. Любые предложения для этого?

  2. Когда приложение работает, оно все равно не дает мне идентификатор. Я сканирую свою карту/тег, и MainActivity (здесь ScanningActivity) загружается снова и снова. Дальше этого управление не идет. Любые предложения о том, как работать над ним?

<суп>

public class ScanningActivity extends Activity {
    private NfcAdapter sNfcAdapter;
    Locale locale = new Locale("en", "US");
    byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
    boolean encodeInUtf8 = false;
    Charset utfEncoding = encodeInUtf8 ? Charset.forName("UTF-8") : Charset.forName("UTF-16");
    int utfBit = encodeInUtf8 ? 0 : (1 << 7);
    char status = (char)(utfBit + langBytes.length);

    static String bin2hex(byte[] data) {
        return String.format("%0" + (data.length * 2) + "X", new BigInteger(1, data));
    }
    /* write to tag */

    boolean writeNdefMessageToTag(NdefMessage message, Tag detectedTag) throws FormatException {
        int size = message.toByteArray().length;
        try {
            Ndef ndef = Ndef.get(detectedTag);
            if (ndef != null) {
                ndef.connect();
                if (!ndef.isWritable()) {
                    Toast.makeText(this, "Tag is read-only.", Toast.LENGTH_SHORT).show();
                    return false;
                }
                if (ndef.getMaxSize() < size) {
                    Toast.makeText(this,
                                   "The data cannot be written since the tag capacity is" + ndef.getMaxSize() +
                                   " bytes and the data to be transferred is " + size + " bytes",
                                   Toast.LENGTH_LONG).show();
                    return false;
                }

                ndef.writeNdefMessage(message);
                ndef.close();
                Toast.makeText(this, "Data sent to the Tag", Toast.LENGTH_LONG).show();
                return true;

            } else {
                NdefFormatable ndefFormat = NdefFormatable.get(detectedTag);
                if (ndefFormat != null) {
                    try {
                        ndefFormat.connect();
                        ndefFormat.format(message);
                        ndefFormat.close();
                        Toast.makeText(this, "Data sent", Toast.LENGTH_LONG).show();
                        return true;
                    } catch (IOException e) {
                        Toast.makeText(this, "Unable to format tag", Toast.LENGTH_LONG).show();
                        return false;
                    }
                } else {
                    Toast.makeText(this, "Not supported tag", Toast.LENGTH_LONG).show();
                    return false;
                }

            }
        } catch (IOException e) {
            Toast.makeText(this, "Sending failed", Toast.LENGTH_LONG).show();
        }
        return false;

    }

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_scanning);

        TextView tg = (TextView)findViewById(R.id.tagid);
        final TextView tvtime = (TextView)findViewById(R.id.datetime);
        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss a");
        String currentTimeStamp = dateFormat.format(new Date()); // Find todays date
        tvtime.setText(currentTimeStamp);

        sNfcAdapter = NfcAdapter.getDefaultAdapter(this);

        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        tagDetected.addCategory(Intent.CATEGORY_DEFAULT);
        if (sNfcAdapter == null) {
            Toast.makeText(this, "This device does not support NFC or you have not scanned the card properly",
                           Toast.LENGTH_LONG).show();
            return;
        }

        if (!sNfcAdapter.isEnabled()) {
            Toast.makeText(this, "Looks like the NFC is not enabled on your device", Toast.LENGTH_LONG).show();
            new AlertDialog.Builder(this).setTitle("NFC disabled").setMessage(
                    "Looks like the NFC is not enabled on your device. Please enable it.").setPositiveButton(
                    "Ok", null).show();
        }
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(getIntent().getAction())) {
            Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
            try {
                String TagID = tag.getId().toString();
                tg.setText(bin2hex(tag.getId()));
                Toast.makeText(getApplicationContext(), bin2hex(tag.getId()), Toast.LENGTH_LONG).show();
                Toast.makeText(this, TagID, Toast.LENGTH_LONG).show();
            } catch (Exception ex) {
                new AlertDialog.Builder(this).setTitle("Error!").setPositiveButton("Ok",
                                                                                   new DialogInterface.OnClickListener() {
                    public void onClick(DialogInterface dialog, int which) {
                        Intent i = new Intent(ScanningActivity.this, ScanningActivity.class);
                        startActivity(i);
                    }
                }).setMessage(ex.getMessage() + "\n\nPlease click Ok. This will restart the application").create().show();

                new AlertDialog.Builder(this).setTitle("Transferring the data").setPositiveButton("Ok",
                                                                                                  new DialogInterface.OnClickListener() {
                    @Override
                    public void onClick(DialogInterface dialog, int which) {
                        // TODO Auto-generated method stub
                        TextView tvData = (TextView)findViewById(R.id.Data);
                        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
                            Tag tag1 = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
                            String DataToSend = tvtime.getText().toString() + tag1.getId().toString();
                            //String DataToSend = "Data";
                            //tvData.setText(tvtime.getText().toString()+tag.getId().toString());
                            byte[] textBytes = DataToSend.getBytes(utfEncoding);
                            byte[] dataa = new byte[1 + langBytes.length + textBytes.length];
                            dataa[0] = (byte)status;
                            System.arraycopy(langBytes, 0, dataa, 1, langBytes.length);
                            System.arraycopy(textBytes, 0, dataa, 1 + langBytes.length, textBytes.length);;
                            NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_WELL_KNOWN,
                                                                   NdefRecord.RTD_TEXT, new byte[0], dataa);
                            NdefMessage newMessage = new NdefMessage(new NdefRecord[] { textRecord });

                            try {
                                writeNdefMessageToTag(newMessage, tag1);
                            } catch (FormatException e) {

                                e.printStackTrace();
                            }
                        }
                    }
                }).setMessage(
                        "Place this tablet on the RFID Tag on the Microbiology Form. Keep it there until you get to the next screen").create().show();

            }
        }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        getMenuInflater().inflate(R.menu.scanning, menu);
        return true;
    }
}

и Манифест

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

<uses-sdk
    android:minSdkVersion="13"
    android:targetSdkVersion="17" />

<application
    android:allowBackup="true"
    android:icon="@drawable/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name="com.example.tabletapp.ScanningActivity"
        android:label="@string/app_name" >
        <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.NDEF_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT"/>
            <data android:mimeType="text/plain" />
        </intent-filter>
    </activity>
</application>

Обновление:

  1. Приложение не показывает никаких тостов. Когда я кладу карту/метку на устройство, меня спрашивают, какое приложение мне нравится использовать. Я выбираю тот, о котором мы говорим, и «ScanningActivity» (MainActivity) снова загружается. Не показывает мне идентификатор и не проходит сканирование.

  2. Я хочу прочитать идентификатор с карты, а затем записать его вместе с отметкой времени в другой тег.


person CSA    schedule 21.04.2015    source источник
comment
Я не понимаю, почему кто-то проголосовал за этот вопрос. Если вы считаете, что это неуместный вопрос или в нем чего-то не хватает, пожалуйста, прокомментируйте.   -  person CSA    schedule 22.04.2015
comment
Какова на самом деле проблема, которая у вас есть? Показывает ли ваше приложение какие-либо всплывающие уведомления (один с идентификатором тега или сообщением об ошибке)? Вы хотите прочитать идентификатор из тега, а затем записать его в тот же тег или в другой тег? Считывает ли ваше приложение идентификатор в R.id.tagid, и ваша проблема в том, что вы не можете записать во второй тег или оно вообще не может этого сделать?   -  person Michael Roland    schedule 23.04.2015
comment
@MichaelRoland Вот ответы. Извиняюсь за неясность ранее. 1. Приложение не показывает никаких тостов. Когда я кладу карту/метку на устройство, меня спрашивают, какое приложение мне нравится использовать. Я выбираю тот, о котором мы говорим, и «ScanningActivity» (MainActivity) снова загружается. Не показывает мне идентификатор и не проходит сканирование. 2. Я хочу прочитать идентификатор с карты, а затем записать его вместе с меткой времени в другой тег.   -  person CSA    schedule 23.04.2015


Ответы (1)


В вашем коде довольно много проблем, поэтому я сосредоточусь только на самых очевидных:

  1. Вы зарегистрировались для NDEF_DISCOVERED в своем AndroidManifest.xml. Однако в onCreate() вы будете читать идентификатор только тогда, когда получите намерение TAG_DISCOVERED. Вы должны изменить это, чтобы соответствовать намерению NDEF_DISCOVERED. (Настоящим я предполагаю, что ваш тег содержит текстовую запись, которая соответствует вашему фильтру намерений.)

  2. tag.getId().toString() не даст вам много полезной информации, так как tag.getId() возвращает массив байтов. Вы всегда можете использовать свой метод bin2hex() для преобразования идентификатора в удобочитаемую строку.

  3. Вам следует избегать любого взаимодействия с метками NFC при нажатии кнопки. (То есть то, что вы сейчас делаете в onClick(DialogInterface dialog, int which).) И нажатие кнопки, и взаимодействие с NFC следует рассматривать как действия человека, и вам следует избегать одновременного требования двух действий человека. (Более того, боты основаны на событиях, и вы не можете напрямую их комбинировать.) Вместо этого вы можете установить флаг в методе onClick(), который указывает, что данные должны быть записаны в тег при следующем событии обнаружения NFC.

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

person Michael Roland    schedule 24.04.2015