【问题标题】:Why always TECH_DISCOVERED or TAG_DISCOVERED but not NDEF_DISCOVERED?为什么总是 TECH_DISCOVERED 或 TAG_DISCOVERED 而不是 NDEF_DISCOVERED?
【发布时间】:2014-11-03 04:57:45
【问题描述】:

我刚接触 Android 中的 NFC。我有几个问题。首先,让我介绍一下代码。在我的程序中,它只是简单地从记录中检索有效负载并将它们记录为字符串。

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

    adapter = NfcAdapter.getDefaultAdapter(this);
    nfcPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_SINGLE_TOP),  0);
    nfcFilter = new IntentFilter[]{
                new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED),
                new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED),
                new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
            };
    techList = new String[][]{{Ndef.class.getName()}};
}

@Override
public void onResume(){
    super.onResume();

    if (adapter != null){
        adapter.enableForegroundDispatch(this, nfcPendingIntent, nfcFilter, techList);
        if (!adapter.isEnabled()){
            Toast.makeText(this, "please enable your nfc", Toast.LENGTH_SHORT).show();
        }
    } else {
        Toast.makeText(this, "your device do not have nfc.", Toast.LENGTH_SHORT).show();
    }
}

@Override
public void onPause(){
    super.onPause();
    if (adapter != null){
        adapter.disableForegroundDispatch(this);
    }
}

@Override
protected void onNewIntent(Intent intent){
    String TAG = "onNewIntent";
    super.onNewIntent(intent);

    Log.d(TAG, "action: "+intent.getAction());
    //Log.d(TAG, "type: "+intent.getType());
    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())){
        Parcelable[] rawMsg = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMsg != null){
            for (int i=0; i<rawMsg.length; i++){
                NdefMessage msg = (NdefMessage)rawMsg[i];
                NdefRecord[] records = msg.getRecords();
                for (int j=0; j<records.length; j++){
                    Log.d(TAG, records[j].toMimeType()+"");
                    byte [] payload = records[j].getPayload();
                    if (payload != null && payload.length > 0){
                        Log.d(TAG, new String(payload, 1, payload.length-1));
                    }
                }
            }
        }
    } else if (NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())){

    } else if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())){
        Parcelable[] rawMsg = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if (rawMsg != null){
            for (int i=0; i<rawMsg.length; i++){
                NdefMessage msg = (NdefMessage)rawMsg[i];
                NdefRecord[] records = msg.getRecords();
                for (int j=0; j<records.length; j++){
                    Log.d(TAG, records[j].toMimeType()+"");
                    byte [] payload = records[j].getPayload();
                    if (payload != null && payload.length > 0){
                        Log.d(TAG, new String(payload, 1, payload.length-1)+"("+j+")");
                    }
                }
            }
        }
    }
}

这里有两个问题:

  1. 结果告诉前台调度程序仅捕获 TECH_DISCOVERED(带有 techList)和 TAG_DISCOVERED(不带 techList)但错过了 NDEF_DISCOVERED。

  2. 当我离开应用程序并扫描 NFC 标签时,它会自动将我带到网站(我将 url 作为记录)。它如何告诉该记录包括打开浏览器或拨打电话的操作?

【问题讨论】:

  • 为什么我不能触发 NDEF_DISCOVERED 动作???

标签: android nfc intentfilter ndef


【解决方案1】:

NDEF_DISCOVERED 意图过滤器通常(似乎存在一些例外)只有在它具有与标签上的 NDEF 消息匹配的关联数据类型时才会匹配。例如,数据类型规范 */* 将匹配任何 MIME 类型:

IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try {
    ndef.addDataType("*/*");
} catch (MalformedMimeTypeException e) {}
nfcFilter = new IntentFilter[]{
        ndef,
        new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED),
        new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)
};

同样,如果您只想触发特定 URL http://www.example.com/,您可以使用:

IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
ndef.addDataScheme("http");
ndef.addDataAuthority("www.example.com", null);

注意——使用前台调度系统——您通常只会注册您想要匹配的最通用的意图过滤器。因此,如果您的前台调度意图过滤器已经包含操作TAG_DISCOVERED,则无需添加任何更具体的过滤器(如TECH_DISCOVEREDNDEF_DISCOVERED),因为您的活动已经收到任何发现的标签。这同样适用于TECH_DISCOVEREDNdef 标签技术的结合:这已经包含任何会触发NDEF_DISCOVERED 的标签。但是,请注意,TAG_DISCOVERED 意图过滤器的特殊之处在于它在与前台调度一起使用时表示“catch-all”,而它表示“仅回退”(即仅在没有与任何其他应用程序更好匹配时才匹配)在基于清单的意图过滤器中使用时。

【讨论】:

  • 我添加了数据类型,但它仍然不是 NDEF_DISCOVERED 操作。如果我改用 TAG_DISCOVERED,可以类似地检索消息吗?是否所有消息都遵循 NDEF 格式?
  • @Simon 您的标签上有什么 NDEF 消息?如果您收到所有三个意图过滤器组合的TAG_DISCOVERED 意图操作(如上),则您的标记不包含任何 NDEF 消息/未被检测为 NDEF 标记。
  • 我有 2 条 text/plain 记录,并且标签支持 ndef、nfca、ultralight 技术......如何知道标签是否有 NDEF 消息?或检测为 NDEF?该结构确实遵循 NDEF 消息,因为我在代码中所做的运行良好
  • 您可以使用一些可用的标签检查工具进行检查(例如我的NFC TagInfo app)。
猜你喜欢
  • 2017-09-07
  • 2013-12-07
  • 1970-01-01
  • 2010-12-16
  • 1970-01-01
  • 1970-01-01
  • 2014-07-23
  • 1970-01-01
相关资源
最近更新 更多