You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Android NFC标签读取耗时统计:计时器启停位置咨询

Hey there! Let's work through your NFC timing issue step by step. I see you've got the timer starting when a tag is detected, but you're stuck on where to stop it accurately. Let's fix that.

First, let's clarify the core problem: your current stop logic is tucked inside a try block in buildTagViews()—so if an encoding exception gets thrown, the timer never stops. Plus, we need to make sure the timer stops every time after we finish reading (or fail to read) the tag, and avoid duplicate timer runs.

Here's the revised plan and code changes:

1. First, create a dedicated stopTimer() method

This lets us reuse the stop logic everywhere, keeping things clean:

private void stopTimer() {
    if (handler != null) {
        handler.removeCallbacks(runnable);
        // Calculate the final elapsed time
        long totalElapsed = TimeBuff + (SystemClock.uptimeMillis() - StartTime);
        // Update the Timer TextView with the exact read time
        int minutes = (int) (totalElapsed / 60000);
        int seconds = (int) ((totalElapsed % 60000) / 1000);
        int millis = (int) (totalElapsed % 1000);
        Timer.setText(String.format("读取耗时: %d:%02d:%03d", minutes, seconds, millis));
        // Reset timing variables for the next read
        TimeBuff = 0;
        MillisecondTime = 0;
        UpdateTime = 0;
    }
}

2. Fix the buildTagViews() method

We'll call stopTimer() in a finally block to ensure it runs whether the read succeeds or fails:

private void buildTagViews(NdefMessage[] msgs) {
    if (msgs == null || msgs.length == 0) {
        stopTimer();
        tvNFCContent.setText("NFC Content: 无数据");
        return;
    }
    String text = "";
    byte[] payload = msgs[0].getRecords()[0].getPayload();
    String textEncoding = ((payload[0] & 128) == 0) ? "UTF-8" : "UTF-16";
    int languageCodeLength = payload[0] & 0063;
    try {
        text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding);
    } catch (UnsupportedEncodingException e) {
        Log.e("UnsupportedEncoding", e.toString());
        text = "读取失败: " + e.getMessage();
    } finally {
        // Stop timer no matter if read succeeds or fails
        stopTimer();
    }
    tvNFCContent.setText("NFC Content: " + text);
}

3. Clean up the onNewIntent() method

Right now, you have duplicate NFC handling logic here. Let's streamline it and make sure we only start the timer once per tag detection, and stop it if we get an unknown action:

@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    setIntent(intent);
    
    String action = intent.getAction();
    if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || 
        NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || 
        NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
        // Stop any existing timer before starting a new one
        handler.removeCallbacks(runnable);
        TimeBuff = 0;
        // Start the timer
        StartTime = SystemClock.uptimeMillis();
        handler.postDelayed(runnable, 0);
        
        // Read the tag content
        readFromIntent(intent);
        
        // Show appropriate toasts
        if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
            Toast.makeText(getApplicationContext(),"Ndefdiscovered",Toast.LENGTH_SHORT).show();
        } else if(NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
            mTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            Toast.makeText(getApplicationContext(),"Smartcard detected",Toast.LENGTH_SHORT).show();
        }
    } else {
        Toast.makeText(getApplicationContext(),"Undefined smartcard",Toast.LENGTH_SHORT).show();
        // Stop timer for unknown actions
        stopTimer();
    }
}

A bonus optimization for your use case

Since your expected read time is only ~0.1ms, the repeating handler.postDelayed(runnable, 0) is overkill—it's updating the TextView way faster than needed, and might even skew your timing. Instead, you could skip the runnable entirely and just track start/end timestamps directly:

  1. Remove the runnable, MillisecondTime, UpdateTime, Seconds, Minutes, MilliSeconds variables
  2. Replace the start logic with:
    startTime = SystemClock.uptimeMillis();
    
  3. Replace the stop logic with:
    long elapsedTime = SystemClock.uptimeMillis() - startTime;
    Timer.setText(String.format("读取耗时: %.3f毫秒", elapsedTime));
    

This is simpler and more accurate for ultra-fast operations like NFC reads.

Why this works

  • The stopTimer() method ensures we always clean up the handler callbacks and reset timing variables
  • Using finally guarantees the timer stops even if an error occurs during reading
  • We prevent duplicate timer runs by stopping any existing timer before starting a new one

Give these changes a try, and your timing should now accurately reflect how long it takes to detect and read the NFC tag!

内容的提问来源于stack exchange,提问作者Muhammad Haries

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.06 11:08:15