Напишите сообщение NDEF внутри цикла

Я хочу писать разные сообщения NDEF внутри цикла while().

ПОСЛЕДНЕЕ РЕДАКТИРОВАНИЕ: похоже, что микроконтроллер не может так быстро обрабатывать данные, поэтому мою проблему нельзя решить.

//ndef.connect();
ndef.writeNdefMessage(message);
//ndef.close();

Мой метод write(), упрощенный, без всех попыток/поймать

Итак, первый цикл работает правильно, а следующие нет. Но после нескольких циклов он снова работает еще раз. Это повторяется.

stop = 0;    
while(stop < 1000)
    {
        write();
        stop++
    } 

write() работает правильно для одного цикла.

РЕДАКТИРОВАТЬ: я заменил while() на таймер:

    new Timer().schedule(new TimerTask() {
        @Override
        public void run() {
               write();
                }
}, 2000);

Но это слишком медленно... Мне нужно писать не менее 5 раз в секунду. Если я устанавливаю период таймера меньше 2000, он не работает, работает так же, как и while()

EDIT2: я измерил скорость передачи и получения сообщения. Кажется, для отправки сообщения требуется около 55 мс, а для получения - около 7 мс. Это то, что я хочу, но если я установлю таймер на повторение, например, через 100 мс, у меня будет эта ошибка от writeNDEFmessage() : java.io.IOException: Tag is not ndef . Итак, если я зацикливаюсь 10 раз writeNDEFmessage(), он отлично работает в первом цикле, но я получаю исключение в следующих 9.

РЕДАКТИРОВАТЬ3:

onNewIntent() :

@Override
    protected void onNewIntent(Intent intent)
    {
        try {
            if(intent.getAction().equals(NfcAdapter.ACTION_TAG_DISCOVERED) ||
                    intent.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED)||
                    intent.getAction().equals(NfcAdapter.ACTION_TECH_DISCOVERED))
            {
                detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

                if(detectedTag != lastDetectedTag)
                {

                    lastDetectedTag = detectedTag;
                    setIntent(intent);
                }


            }
        } catch (Exception e)
        {
            Log.e("", "onIntent >>> "+e.getMessage());

        }

    }

Это назначено на кнопку:

 public void testWrite()
    {

        final Timer timer = new Timer();

        try {
            ndef = Ndef.get(detectedTag);
            ndef.connect();
        } catch (IOException e) {
            Log.e("", "Cannot connect");
            e.printStackTrace();
        }
        timer.schedule(new TimerTask() {

            @Override
            public void run() {

                transmit.writeTag(message), ndef) 

        }, 0, 200);

    }

и writeTag():

public boolean writeTag(String str, Ndef ndef) {


        try {
            message = getNdefMessage(str);
        }
        catch (Exception e)
        {
           toast("Message error");
        }

        int size = message.toByteArray().length;

        try {


            if (ndef != null) {

                if(!ndef.isConnected())
                {
                    ndef.connect();
                    Log.e("", ""+ndef.toString());
                }

                if (!ndef.isWritable()) {
                    return false;
                }
                if (ndef.getMaxSize() < size) {
                    toast("Tag capacity is " + ndef.getMaxSize() + " bytes, message is " + size + " bytes.");
                    return false;
                }
                try{

                    ndef.writeNdefMessage(message);
                }
                catch(IOException e){
                    toast("error send");
                    Log.e("IOException", e + "-+-");
                    return false;
                }


                return true;
            } 
        }
        catch (Exception e) {
            toast("Failed to write tag");
        }
        return false;
    }

transmit — это объект класса Transmit, в котором определен writeTag()

onCreate():

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

        textView = (TextView) findViewById(R.id.textView);
        transmit = new Transmit(this);
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        textView.setText("");
        detectedTag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
        lastDetectedTag = detectedTag;
        pendingIntent = PendingIntent.getActivity(getApplicationContext(), 0,
                new Intent(this, getClass()).
                        addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        IntentFilter filter2     = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        readTagFilters = new IntentFilter[]{tagDetected,filter2};
        techListsArray = new String[][] { new String[] { NfcF.class.getName() } };


        if (mNfcAdapter == null) {
            // Stop here, we definitely need NFC

            finish();
            return;

        }

        if (!mNfcAdapter.isEnabled()) {

        }


        buttonListener(testButton);

    }

person user3623498    schedule 13.08.2015    source источник
comment
С какой версией Android и телефоном вы тестируете?   -  person Nils Pipenbrinck    schedule 13.08.2015
comment
Android 4.4.2, API19, Motorola RAZR HD   -  person user3623498    schedule 13.08.2015
comment
Нужны ли части ndef.connect{} и ndef.close()? Это может быть сделано вне цикла. Интересно, зачем вы проводите такие стресс-тесты? Возможно, есть другой способ достичь цели.   -  person vlp    schedule 13.08.2015
comment
Удалены ndef.connect() и ndef.close() из цикла. Такой же...   -  person user3623498    schedule 13.08.2015
comment
Добавлено больше информации @vlp   -  person user3623498    schedule 14.08.2015
comment
Согласно документам класса NDEF, writeNdefMessage() нельзя вызывать из основного потока приложения. поэтому обязательно отбросьте runOnUiThread. Вы пишете в AsyncTask? И самый главный вопрос: какой тип тега вы используете?   -  person griffinjm    schedule 14.08.2015
comment
Как насчет синхронизированного (ndef) {ndef.writeNdefMessage (сообщение); } внутри write()? Дополнительный ndef.isWritable() может что-то раскрыть. Где запись перепланирована? Ваш код настраивает только одно выполнение. Удаление runOnUiThread() — хороший совет. Какова цель многократной перезаписи ndef на тег? Ориентир?   -  person vlp    schedule 15.08.2015
comment
@vlp Я удалил его из runOnUiThread(). В отладчике я добавил точку останова в onNewIntent, и она достигает ее каждые 4-5 циклов, также isConnected() возвращает false для 4-5 циклов   -  person user3623498    schedule 17.08.2015
comment
@jgriffin не подумал об этом, detectedtag.toString() возвращает TAG: Tech [android.nfc.tech.IsoDep, android.nfc.tech.NfcA, android.nfc.tech.Ndef]   -  person user3623498    schedule 17.08.2015
comment
@jgriffin OP отредактирован, чтобы добавить больше деталей, надеюсь, это поможет   -  person user3623498    schedule 17.08.2015
comment
Вы пытались использовать NfcAdapter.enableForegroundDispatch()/disableForegroundDispatch()? Это может помочь. Получаете ли вы упомянутые ложные вызовы onNewIntent(), даже если вы вообще не вызываете testWriteTag()? Иногда очень помогает просмотр logcat - особенно ищите Nfc, Tag, Ndef... У меня больше нет идей :(   -  person vlp    schedule 17.08.2015
comment
да, я использую NfcAdapter.enableForegroundDispatch()/disableForegroundDispatch() я получаю onNewIntent после каждого цикла...   -  person user3623498    schedule 17.08.2015
comment
Но вы не должны получать новое намерение после каждого цикла? Вы должны получить новое намерение только тогда, когда тег попадет в поле телефона. Я думал, ты оставляешь телефон на бирке и пишешь в цикле, чтобы убедиться в работоспособности? Пожалуйста, объясните, как вы проводите тест и что именно вы пытаетесь измерить.   -  person griffinjm    schedule 17.08.2015
comment
Я кладу свой телефон на микроконтроллер и нажимаю кнопку, которая начинает писать мои сообщения. После каждой записи микроконтроллер отправляет мне ответ. И отправка, и получение работают правильно без цикла. Телефон все это время не отходит от микроконтроллера, поэтому метка всегда в зоне действия. Но после каждой записи я слышу небольшой звук от микроконтроллера. @jgriffin   -  person user3623498    schedule 18.08.2015
comment
Какой тег вы используете?   -  person griffinjm    schedule 18.08.2015
comment
@jgriffin Тег типа 4 ISO/IEC 14443   -  person user3623498    schedule 19.08.2015


Ответы (1)


Из документации Ndef для метода close(): «Отключите операции ввода-вывода для тега из этого объекта TagTechnology и освободите ресурсы».

Поэтому я думаю, что когда вы вызываете close(), внутренний TagTechnology освобождается. Если вы вызываете соединение с тем же ndef, это «устаревший» объект. Попробуйте каждый раз создавать новый объект Ndef, передавая ему объект Tag.

Редактировать: Или просто не звоните close(), пока вы не закончите. Вам все равно нужно будет позвонить connect() в первый раз. Кроме того, я всегда сначала вызывал isConnected(), чтобы убедиться, что тег присутствует и подключен.

person griffinjm    schedule 14.08.2015
comment
удалил ndef.connect() и ndef.close() из write() и добавил проверку ndef.isConnected(). В отладчике он достигает этого каждые 4-5 циклов с разными значениями для ndef Ndef@4219b850 Ndef@42151838 Ndef@4210a068 etc - person user3623498; 17.08.2015
comment
Что ж, из вашего комментария выше вы упомянули, что у вас есть точка останова в onNewIntent(). Это сработает только тогда, когда тег покинет поле и снова войдет в него. Таким образом, попытка зациклить запись в другом потоке и ожидание точки останова в onNewIntent() не имеет смысла. Пожалуйста, опубликуйте свой полный класс активности со всей неповрежденной логикой NFC, чтобы мы могли увидеть, в чем может быть проблема. - person griffinjm; 17.08.2015