首页 > 解决方案 > 设置计时器以了解 NFC 读取标签的速度

问题描述

我是 android 新手,并且获得了我需要知道手机中的 NFC 标签读取带有计时器的标签的速度的项目。已经4天了,我仍然试图弄清楚。

所以这就是它在我心中的运作方式。TAG > 检测到(定时器启动)> 来自标签的信息显示 > 定时器停止。

可能吗 ?我知道它会得到大约 0.1 毫秒。我已经可以在检测到标签时启动计时器,但它不会停止。

这里的java代码:


public class Read extends Activity {


    NfcAdapter mAdapter;
    Tag mTag;
    PendingIntent mPI;
    IntentFilter mFilter[]; 
    String userData,yo;

    boolean writeMode;
    Context context;
    TextView tvNFCContent, Timer,Low;


    Button start, pause, reset, lap ;
    long MillisecondTime, StartTime, TimeBuff, UpdateTime = 0L ;
    Handler handler;
    int Seconds, Minutes, MilliSeconds ;
    ListView listView ;
    String[] ListElements = new String[] {  };
    List<String> ListElementsArrayList ;
    ArrayAdapter<String> adapter ;


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.read);


        tvNFCContent = (TextView) findViewById(R.id.data);
        Timer = (TextView)findViewById(R.id.timer);

        handler = new Handler() ;


        mAdapter = NfcAdapter.getDefaultAdapter(this);
        mPI = 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);
        mFilter = new IntentFilter[]{tagDetected,filter2};


    mAdapter = NfcAdapter.getDefaultAdapter(this);
    if (mAdapter == null) {
        // Stop here, we definitely need NFC
        Toast.makeText(this, "This device doesn't support NFC.", Toast.LENGTH_LONG).show();
        finish();
    }

    readFromIntent(getIntent());

    }


     /******************************************************************************
     **********************************Read From NFC Tag***************************
     ******************************************************************************/
    private void readFromIntent(Intent intent) {
        String action = intent.getAction();
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action)
                || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) 



        {
            Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
            NdefMessage[] msgs = null;
            if (rawMsgs != null) {
                msgs = new NdefMessage[rawMsgs.length];
                for (int i = 0; i < rawMsgs.length; i++) {
                    msgs[i] = (NdefMessage) rawMsgs[i];


                }
            }                               
            buildTagViews(msgs);
        }



}



    private void buildTagViews(NdefMessage[] msgs) {
        if (msgs == null || msgs.length == 0) return;

        String text = "";
//        String tagId = new String(msgs[0].getRecords()[0].getType());
        byte[] payload = msgs[0].getRecords()[0].getPayload();
        String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16"; // Get the Text Encoding
        int languageCodeLength = payload[0] & 0063; // Get the Language Code, e.g. "en"
        // String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");

        try {

            text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
            TimeBuff += MillisecondTime;
            handler.removeCallbacks(runnable);         

        } catch (UnsupportedEncodingException e) {
            Log.e("UnsupportedEncoding", e.toString());
        }


     tvNFCContent.setText("NFC Content: " + text);

    }  


    NdefMessage[] getNdefMessage(Intent intent)
    {
        NdefMessage[] msgs = null;

        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if(rawMsgs != null)
        {
            msgs = new NdefMessage[rawMsgs.length];
            for(int i=0; i<rawMsgs.length; i++)
            {
                msgs[i] = (NdefMessage)rawMsgs[i];
            }
        }

        return msgs;
    }


    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    protected void onNewIntent(Intent intent) {
        // TODO Auto-generated method stub


        setIntent(intent);
        readFromIntent(intent);
        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
            mTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            StartTime = SystemClock.uptimeMillis();
            handler.postDelayed(runnable, 0);
        }

        super.onNewIntent(intent);

        if(intent.getAction().equals(NfcAdapter.ACTION_NDEF_DISCOVERED))
        {           
            Toast.makeText(getApplicationContext(),"Ndefdiscovered",Toast.LENGTH_SHORT).show();

        }else if(intent.getAction().equals(NfcAdapter.ACTION_TAG_DISCOVERED))
        {
            mTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            Toast.makeText(getApplicationContext(),"Smartcard detected",Toast.LENGTH_SHORT).show();

            NdefMessage[] messages = getNdefMessage(intent);            
            if(messages == null)
            {
                Toast.makeText(getApplicationContext(),"There Is No Data",Toast.LENGTH_SHORT).show();
                return;
            }           
            byte[] payload = messages[0].getRecords()[0].getPayload();          
            userData = new String(payload);



        }else
        {
            Toast.makeText(getApplicationContext(),"Undefined smartcard",Toast.LENGTH_SHORT).show();
        }

    }   

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        mAdapter.disableForegroundDispatch(this);

    }

    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        mAdapter.enableForegroundDispatch(this, mPI, mFilter, null);

    }


    public Runnable runnable = new Runnable() {

        public void run() {

            MillisecondTime = SystemClock.uptimeMillis() - StartTime;

            UpdateTime = TimeBuff + MillisecondTime;

            Seconds = (int) (UpdateTime / 1000);

            Minutes = Seconds / 60;

            Seconds = Seconds % 60;

            MilliSeconds = (int) (UpdateTime % 1000);

            Timer.setText("" + Minutes + ":"
                    + String.format("%02d", Seconds) + ":"
                    + String.format("%03d", MilliSeconds));

            handler.postDelayed(this, 0);
        }

    };

}





这里是停止计时器的代码,但我不知道在哪里可以按时停止计时器:


TimeBuff += MillisecondTime;
handler.removeCallbacks(runnable);

标签: androidtimernfc

解决方案


使用这种读取方法,您无需计算应用程序实际读取 NFC 标签的时间,因为时间总是完全为零。

这是因为 Android 操作系统在将结果传递给您的 App 之前,已经从标签中完全读取了数据。

如果您真的想花时间阅读标签,有一些方法可以自己实际阅读标签。

更新: 由于您没有告诉我您使用的卡类型,因此无法编写代码来测量您想要的时间。

一些背景:

所有低级别的 NFC 卡操作都会执行 1 到 N 次transceive操作,每个transceive操作发送一个 1 到 N 字节的字节数组,并返回一个 0 到 N 字节的字节数组。

对于原始读取时间,您将计算运行正确数量的transeive命令以读取数据所花费的时间。

更高级别操作的时间还包括将 N 个字节数组解析为 aNdefMessage以及transceive命令所花费的时间

编码:

因此,由于我不知道卡的类型,我能做的最好的就是花时间连接到卡并读取数据并将其解析为NdefMessage

这是可能导致 RF 活动并阻止代码进一步执行的任何操作的时序。

该代码忽略了 Android 操作系统已经读取卡并在您的应用程序中以零时间向您传递卡数据的事实,该应用程序花费在读取卡上,它重新读取卡以获取时间。请注意,如果您将卡带走以进行快速,它可能会产生异常并且无法计时读取卡。

我本可以编写要使用的代码,enableReaderMode尤其是在写入卡时更可靠,并且还有许多其他好处。但相反,我使用ForegroundDispatch的示例代码正在使用ForegroundDispatch,所以我也照做了。

PS我不建议使用ForegroundDispatch

package com.test.foregrounddispatch;

import androidx.appcompat.app.AppCompatActivity;

import android.app.PendingIntent;
import android.content.Intent;
import android.content.IntentFilter;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.nfc.tech.Ndef;
import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AppCompatActivity {

    NfcAdapter mAdapter;

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

        mAdapter = NfcAdapter.getDefaultAdapter(this);
    }

    @Override
    protected void onPause() {
        // TODO Auto-generated method stub
        super.onPause();
        mAdapter.disableForegroundDispatch(this);

    }


    @Override
    protected void onResume() {
        // TODO Auto-generated method stub
        super.onResume();
        IntentFilter tagDetected = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
        IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
        try {
            ndefDetected.addDataType("*/*");
        } catch (IntentFilter.MalformedMimeTypeException e) {}
        IntentFilter techDetected = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
        IntentFilter[] nfcIntentFilter = new IntentFilter[]{ndefDetected,techDetected,tagDetected};

        PendingIntent pendingIntent = PendingIntent.getActivity(
                this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        if(mAdapter!= null)
            mAdapter.enableForegroundDispatch(this, pendingIntent, nfcIntentFilter, null);

    }

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);

        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
            // While with ForegroundDispatch the NDEF message has already been read
            // And passed to us in the intent and thus the time the App spends "read" the NFC card is Zero
            // We want to time time the read, so now we have been notified that a NDEF card is in range
            // Try and read from it

            // Get the Tag from the intent
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

            long startTime = 0;
            long endTime = 0;

            try {
                // Create an NDEF tag object
                Ndef ndefTag = Ndef.get(tag);

                // This is the I/O operation to read the card and format the result to an NDEF message
                // Nothing is done with the result to not add any time to it, as we are timing this
                startTime = System.currentTimeMillis();
                ndefTag.connect();
                ndefTag.getNdefMessage();
                endTime = System.currentTimeMillis();
                ndefTag.close();
            } catch (Exception e) {
                Log.e("NFC", e.toString());
            }
            Log.v("NFC", "Time to read in milliseconds is: " + (endTime - startTime));
        }

    }
}

对于我手机上的简短“Hello”纯文本 NDEF 记录,它会生成日志:-

V/NFC:读取时间(毫秒)为:18


推荐阅读