分享

Android下NFC的简单使用

 yyLibraty 2014-03-26

现在很多手机已经配备了NFC(Near Field Communication 近场通信)的功能,我就为此专门研究过,可以到本文末尾下载源代码。

Android官方资料:http://developer./guide/topics/connectivity/nfc/index.html

相关资料参考:http://blog.csdn.net/nicebooks/article/details/6223956

相关Android应用:https://play.google.com/store/apps/details?id=com.nxp.nfc.tagwriter

关于NFC的知识就不讲了,下面直接看代码,主要是读取、写入的功能。先自己新建一个Android工程,下面是用到的变量:

    private NfcAdapter mNfcAdapter;//NFC适配器,就是那个NFC读卡器    PendingIntent mNfcPendingIntent;//用于截获系统Intent,因为系统检测到NFC卡片时会选择程序去响应    IntentFilter[] mWriteTagFilters;//IntentFilter表示满足本程序响应的条件    private boolean mWriteMode = false;//控制读写模式切换

还是建议看看官方资料,这样才能明白某些函数的意思。接下来,在onCreate函数里检测NFC:

        //获取默认NFC设备        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);        if (mNfcAdapter == null) {            Toast.makeText(this, "该设备不支持NFC!", Toast.LENGTH_LONG).show();            finish();            return;        }                //查看NFC是否开启        if (!mNfcAdapter.isEnabled()){            Toast.makeText(this, "请在系统设置中先启用NFC功能", Toast.LENGTH_LONG).show();            finish();            return;        }              mNfcPendingIntent = PendingIntent.getActivity(this, 0,                 new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);        IntentFilter ndefDetected = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);        try {            ndefDetected.addDataType("text/plain");        } catch (MalformedMimeTypeException e) {            e.printStackTrace();        }        mWriteTagFilters = new IntentFilter[] { ndefDetected };

这里先检测手机是否支持NFC,finish()表示退出程序。最后,给上面变量赋值,添加截获的NFC数据类型为"text/plain",表示纯文本。

所以,如果NFC卡片存的是URL地址,我们的程序将无法截获,系统会用浏览器打开。当我们按下Home键,这时就无需截获系统Intent了,添加如下代码:

    @Override    protected void onResume()    {        super.onResume();        mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mWriteTagFilters, null);    }        @Override    protected void onPause()    {        super.onPause();        mNfcAdapter.disableForegroundNdefPush(this);    }

手机发现了NFC Tag,如果我们已经添加了PendingIntent,并且满足我们的IntentFilter条件,就会触发一个如下事件:

    //必须的函数,截获系统itent,然后触发读取和写入操作    @Override    protected void onNewIntent(Intent intent)    {        if (!mWriteMode && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))        {            NdefMessage[] msgs = getNdefMessages(intent);            String body = new String(msgs[0].getRecords()[0].getPayload());            System.out.println("***读取数据***" + body);            tagInfo.setText(body);        }        if (mWriteMode && NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction()))        {            Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);            boolean writesuccess = writeTag(getNoteAsNdef(), detectedTag);            System.out.println("***写入数据***");            if (writesuccess){                Toast.makeText(this, "写入成功", Toast.LENGTH_SHORT).show();            }            else{                Toast.makeText(this, "写入失败!", Toast.LENGTH_SHORT).show();            }        }    }

系统检测到Tag时,会将其所有信息封装到Intent中,我们截获了它就可以读取了。如果要写入,需要构造NdefMessage信息才行。

上面代码中的getNoteAsNdef用来根据输入构造NdefMessage:

    //从输入框获取信息,然后构造NdefMessage用于写入    private NdefMessage getNoteAsNdef()    {        byte[] textBytes = (inputText.getText().toString()).getBytes();        NdefRecord textRecord = new NdefRecord(NdefRecord.TNF_MIME_MEDIA, "text/plain".getBytes(), new byte[] {}, textBytes);        return new NdefMessage(new NdefRecord[] { textRecord });    }

实际读取数据部分如下:

    //实际读取数据部分    private NdefMessage[] getNdefMessages(Intent intent)    {        NdefMessage[] msgs = null;        String action = intent.getAction();        if (NfcAdapter.ACTION_TAG_DISCOVERED.equals(action) || NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action))        {            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];                }            } else            {                // Unknown tag type                byte[] empty = new byte[] {};                NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, empty, empty);                NdefMessage msg = new NdefMessage(new NdefRecord[] { record });                msgs = new NdefMessage[] { msg };            }        } else        {            // Log.d(TAG, "Unknown intent.");            finish();        }        return msgs;    }

实际写入部分如下:

    //实际写入数据部分    boolean writeTag(NdefMessage message, Tag tag)    {        int size = message.toByteArray().length;        try        {            Ndef ndef = Ndef.get(tag);            if (ndef != null)            {                ndef.connect();                if (!ndef.isWritable())                {                    System.out.println("Tag is read-only.");                    return false;                }                if (ndef.getMaxSize() < size)                {                    System.out.println("Tag capacity is " + ndef.getMaxSize() + " bytes, message is " + size + " bytes.");                    return false;                }                ndef.writeNdefMessage(message);                System.out.println("****写入数据成功***");                return true;            } else            {                NdefFormatable format = NdefFormatable.get(tag);                if (format != null)                {                    try                    {                        format.connect();                        format.format(message);                        System.out.println("**Formatted tag and wrote message**");                        return true;                    } catch (IOException e)                    {                        System.out.println("==Failed to format tag.==");                        return false;                    }                } else                {                    System.out.println("Tag doesn't support NDEF.");                    return false;                }            }        } catch (Exception e)        {            System.out.println("!!写入数据失败!!");        }        return false;    }

上面的写入、读取部分都不是很简洁,因为要兼容到android 2.3(API 10)的版本,Android 4.0以上提供了跟简单的读写方式,可以参考下面的文章:

http:///2012/12/writing-custom-data-to-nfc-tags-with-android-example/

如果你需要这样的功能,比如检测到文本时便启动你的程序,你可以在配置文件里设置,查看官方文档即可,我这里没有这样的需求。

最后,打开AndroidManifest.xml文件,添加如下代码用于开启NFC权限。注意,我的源代码。

    <uses-sdk android:minSdkVersion="10" android:targetSdkVersion="14" />    <uses-permission android:name="android.permission.NFC" />

 

    本站是提供个人知识管理的网络存储空间,所有内容均由用户发布,不代表本站观点。请注意甄别内容中的联系方式、诱导购买等信息,谨防诈骗。如发现有害或侵权内容,请点击一键举报。
    转藏 分享 献花(0

    0条评论

    发表

    请遵守用户 评论公约

    类似文章 更多