现在的位置: 首页 > 综合 > 正文

NFC 学习总结(下)

2018年09月06日 ⁄ 综合 ⁄ 共 5385字 ⁄ 字号 评论关闭

       上一篇文章已经给大家普及了一些基础知识。这次讲解一下Android系统下的nfc编程。本文依旧采用问答式的形式给大家讲解。

学习Android系统下的nfc编程,很自然的学习方法就是到官网下载NFC的Demo代码下来研究研究。看到AndroidMainfest.xml文件

 <activity android:name="TagViewer"
            android:theme="@android:style/Theme.NoTitleBar"
        >
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED"/>
                <category android:name="android.intent.category.DEFAULT"/>
            </intent-filter>
        </activity>

红色部分这个和nfc有关系,那它究竟是什么呢?

答:NDEF_DISCOVERED、TECH_DISCOVERED、TAG_DISCOVERED是三种类型的action,优先级依次递减。如果在AndroidMainfest.xml文件中定义了

       <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />

                <category android:name="android.intent.category.DEFAULT" />

                <data android:mimeType="*/*" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED" />
            </intent-filter>

            <meta-data
                android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech_filter" />

        <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED" />
                <data android:mimeType="*/*" />
            </intent-filter>

则系统会先匹配NDEF_DISCOVERED、TECH_DISCOVERED、TAG_DISCOVERED,有匹配,系统发出清脆的声音,表示匹配成功。系统发出沉闷的声音,表示匹配失败。如果都匹配,系统不发出任何声音。这样的过程叫做Tag 分发,也叫NFC三重过滤机制。

NFC Demo中的com.example.android.nfc.record包下的TextRecord.java

public static TextRecord parse(NdefRecord record) {
        Preconditions.checkArgument(record.getTnf() == NdefRecord.TNF_WELL_KNOWN);
        Preconditions.checkArgument(Arrays.equals(record.getType(), NdefRecord.RTD_TEXT));
        try {
            byte[] payload = record.getPayload();
            /*
             * payload[0] contains the "Status Byte Encodings" field, per the
             * NFC Forum "Text Record Type Definition" section 3.2.1.
             *
             * bit7 is the Text Encoding Field.
             *
             * if (Bit_7 == 0): The text is encoded in UTF-8 if (Bit_7 == 1):
             * The text is encoded in UTF16
             *
             * Bit_6 is reserved for future use and must be set to zero.
             *
             * Bits 5 to 0 are the length of the IANA language code.
             */
            String textEncoding = ((payload[0] & 0200) == 0) ? "UTF-8" : "UTF-16";
            int languageCodeLength = payload[0] & 0077;
            String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII");
            String text =
                new String(payload, languageCodeLength + 1,
                    payload.length - languageCodeLength - 1, textEncoding);
            return new TextRecord(languageCode, text);

        } catch (UnsupportedEncodingException e) {
            // should never happen unless we get a malformed tag.
            throw new IllegalArgumentException(e);
        }
    }

红色部分代码为什么这么写?

答:这是nfc论坛的文本规范,具体标准的内容可以到http://members.nfc-forum.org/specs/spec_dashboard 链接下载你想要的规范文件。此代码的含义是从返回NdefRecord对象中获取字符编码格式和语言类型和文本内容。文件有规范,uri也有它的规范,具体参见uri的规范文件。

很可惜,系统提供的NFC Demo没有提供一个nfc标签很重要的知识点,nfc标签前台发布系统。在此我贴出来部分代码。

publc String[][] TECHLISTS = new String[][] {
                    { IsoDep.class.getName() },
                    { NfcV.class.getName() }, { NfcF.class.getName() }, };

public IntentFilers   FILTERS = new IntentFilter[] { new IntentFilter(
                    NfcAdapter.ACTION_TECH_DISCOVERED, "*/*") };

public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.nfcard);
       。

       。

       。     

        //前台调度系统 第一步
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);

     
    }

protected void onPause() {
        super.onPause();

        //前台调度系统 第三步
        if (nfcAdapter != null)
            nfcAdapter.disableForegroundDispatch(this);

    }

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

        //前台调度系统 第二步
        if (nfcAdapter != null)
            nfcAdapter.enableForegroundDispatch(this, pendingIntent,
                   FILTERS, TECHLISTS);

       
    }

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

        final Parcelable p = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (p!=null){
        Tag tag = (Tag)p;
        for (int i=0; i<tag.getTechList().length; i++) {
            Log.d("NFCTAG", tag.getTechList()[i] );
        }
        }
       
      
    }

这些红色的代码添加的就是nfc标签的前台发布系统。

nfc的前台调度系统有什么作用,在程序中不使用行不行?

答:前台调度系统允许activity 截取intent并声明自己比其他处理相同的intent的activity优先级更高。
nfc标签前台调度系统分两种情况:
第一种情况:activity没有启动的时候,拿手机去扫描tag,那么系统中所有的intent filter都将一起参与过滤。
第二种情况:actiity启动后,拿手机去扫描tag时,那么将直接使用在foreground dispatch中代码写入的过滤标准。如果这个标准没有命中任何intent,那么系统将使用所activity声明的intent filter xml来过滤。网上下载的支付源码NFCard和z自己写的XXXXDemo两个程序都在配置文件里面有Intent的过滤,也都使用前台调度,如果前台调度中的TechList参数中并没有要刷的nfc卡的数据格式过滤,则会调用自己写的规则过滤文件,如果两个应用中的规则文件都有适配nfc卡的数据格式组,则会弹出activity列表。如果NFCard代码中增加了ISODep这种数据格式的前台调度系统过滤,则直接用这个应用读写nfc卡。否则即使NFCard的activity已经启动,接触nfc卡时,还是会弹出activity给用户选择。

总之前台调度系统就是为了再加一层过滤,避免弹出activity列表给用户选择。

NfcAdaper: nfc适配器,Android系统默认只有一个nfc适配器,所以用nfcAdapter = NfcAdapter.getDefaultAdapter(this);

Tag: 描述nfc标签的类,Tag tag =(Tag) intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

深圳通的tag.getTechList()返回的是ISODep和NfcA,说明深圳通支持这个芯片支持这两种格式。如果前台调度系统都没有这两种格式会怎么样,要是intent调度系统也没有对其进行过滤,会怎样?
答:没有前台调度系统也照样能够读写nfc的tag。intent调度系统中没有过滤这两种格式,也可以读写tag。带nfc模块的手机或者平板接触nfc模块时,如果系统中存在好几种nfc的应用,那么会弹出过滤nfc模块的activity,如果你的activity中没有过滤,则连读写nfc的机会都没有。如果使用了前台调度系统或者进行了过滤,则优先级会较高,此时即使你处在当前没有进行任何过滤的但具备nfc读写功能的界面,也会因为优先级不够,而被其他优先级更高的界面抢占。

好了,了解了上述的知识,你就可以很容易地看懂nfc的代码,进而编写自己的nfc应用了。

抱歉!评论已关闭.