Android中NFC功能流程图解析及代码演示『轉』

来源:互联网 发布:群晖路由器端口转发 编辑:程序博客网 时间:2024/04/28 01:13

在Android4.0推出的时候,一个非常引人注目的功能就是NFC(Near Field Communication).

Near Field Communication (NFC) is a set of short-range wireless technologies, typically requiring a distance of 4cm or less to initiate a connection. NFC allows you to share small payloads of data between an NFC tag and an Android-powered device, or between two Android-powered devices.

翻译:
近场通讯(NFC)是一系列短距离无线技术,一般需要4cm或者更短去初始化连接。近场通讯(NFC)允许你在NFC tag和Android设备或者两个Android设备间共享小负载数据。

典型的应用为刷卡应用,如刷信用卡,公交车卡,吃饭的饭卡之类。腾讯2011年1月份文章“Android首款NFC近场通信应用推出”,说明了基于Android的NFC应用目前已经有了,得益于日本在手机刷卡的应用氛围。据2011年7月网易文章“PayPal推出Android系统NFC移动支付服务”报道,PayPal已经做了尝试了,相信这股风很快要刮到中国。

下面我们从技术的层面来分析一下这个技术。

官方的图片示例为:

这是NFC的开发流程,参考文章 “【NFC在android中的应用API】”。

相关的类代码有:NfcAdapter,NdefMessage, NdefRecord,ACTION_TAG_DISCOVERED.
在功能层面上,涉及到了NFC的读写功能。下面我们分别来做总结。
在代码层上面:

使用的时候,需要在AndroidManifest.xml里面加一些权限以及属性。

<uses-permission android:name="android.permission.NFC"/>
<uses-feature android:name="android.hardware.nfc"android:required="true"/>
<uses-sdk android:minSdkVersion="10"/>

这里注意,在Android Version 9的时候仅仅支持了ACTION_TAG_DISCOVERED,对于其他的需要10以上。

在上面的基础上,还需要增加intent-filter的支持。

<intent-filter>
    <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
    <category android:name="android.intent.category.DEFAULT"/>
    <data android:mimeType="text/plain"/>
</intent-filter>

获取NfcAdapter的代码为:

publicstatic String getStatusNfcDevice () {
    NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter();
    if(nfcAdapter.isEnabled()) {
         String status = "enabled";
         returnstatus;
    }
    else{
        String status = "disabled";
        returnstatus;
    }
}

处理函数为

publicvoid onResume() {
    super.onResume();
    if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        if(rawMsgs != null) {
            msgs = newNdefMessage[rawMsgs.length];
            for(inti = 0; i < rawMsgs.length; i++) {
                msgs[i] = (NdefMessage) rawMsgs[i];
            }
        }
    }
    //process the msgs array
}

完整的一个操作代码摘自Google Android NFC Guide代码(略加注释):

packagecom.example.android.beam;
 
importandroid.app.Activity;
importandroid.content.Intent;
importandroid.nfc.NdefMessage;
importandroid.nfc.NdefRecord;
importandroid.nfc.NfcAdapter;
importandroid.nfc.NfcAdapter.CreateNdefMessageCallback;
importandroid.nfc.NfcEvent;
importandroid.os.Bundle;
importandroid.os.Parcelable;
importandroid.widget.TextView;
importandroid.widget.Toast;
importjava.nio.charset.Charset;
 
//继承并实现接口CreateNdefMessageCallback方法createNdefMessage
publicclass Beam extendsActivity implementsCreateNdefMessageCallback {
    NfcAdapter mNfcAdapter;
    TextView textView;
 
    @Override
    publicvoid onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);
        TextView textView = (TextView) findViewById(R.id.textView);
        // Check for available NFC Adapter
        //检测是否有NFC适配器
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        if(mNfcAdapter == null) {
            Toast.makeText(this,"NFC is not available", Toast.LENGTH_LONG).show();
            finish();
            return;
        }
        // Register callback
        //注册回调函数
        mNfcAdapter.setNdefPushMessageCallback(this,this);
    }
 
    @Override
    publicNdefMessage createNdefMessage(NfcEvent event) {
        String text = ("Beam me up, Android!\n\n" +
                "Beam Time: " + System.currentTimeMillis());
        //回调函数,构造NdefMessage格式
        NdefMessage msg = newNdefMessage(
                newNdefRecord[] { createMimeRecord(
                        "application/com.example.android.beam", text.getBytes())
         /**
          * The Android Application Record (AAR) is commented out. When a device
          * receives a push with an AAR in it, the application specified in the AAR
          * is guaranteed to run. The AAR overrides the tag dispatch system.
          * You can add it back in to guarantee that this
          * activity starts when receiving a beamed message. For now, this code
          * uses the tag dispatch system.
          */
          //,NdefRecord.createApplicationRecord("com.example.android.beam")
        });
        returnmsg;
    }
 
    @Override
    publicvoid onResume() {
        super.onResume();
        // Check to see that the Activity started due to an Android Beam
        //得到是否检测到ACTION_NDEF_DISCOVERED触发
        if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
            processIntent(getIntent());
        }
    }
 
    //重载Activity类方法处理当新Intent到来事件
    @Override
    publicvoid onNewIntent(Intent intent) {
        // onResume gets called after this to handle the intent
        setIntent(intent);
    }
 
    /**
     * Parses the NDEF Message from the intent and prints to the TextView
     */
    //关键处理函数,处理扫描到的NdefMessage
    voidprocessIntent(Intent intent) {
        textView = (TextView) findViewById(R.id.textView);
        Parcelable[] rawMsgs = intent.getParcelableArrayExtra(
                NfcAdapter.EXTRA_NDEF_MESSAGES);
        // only one message sent during the beam
        NdefMessage msg = (NdefMessage) rawMsgs[0];
        // record 0 contains the MIME type, record 1 is the AAR, if present
        textView.setText(newString(msg.getRecords()[0].getPayload()));
    }
 
    /**
     * Creates a custom MIME type encapsulated in an NDEF record
     */
    publicNdefRecord createMimeRecord(String mimeType, byte[] payload) {
        byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII"));
        NdefRecord mimeRecord = newNdefRecord(
                NdefRecord.TNF_MIME_MEDIA, mimeBytes, newbyte[0], payload);
        returnmimeRecord;
    }
}

上面代码还需要在AndroidManifest.xml文件里面添加

<intent-filter>
  <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
  <category android:name="android.intent.category.DEFAULT"/>
  <data android:mimeType="application/com.example.android.beam"/>
</intent-filter>

在对NFC设备进行写操作的时候,相关代码:

privatevoid enableTagWriteMode() {
    mWriteMode = true;
    IntentFilter tagDetected = newIntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
    mWriteTagFilters = newIntentFilter[] { tagDetected };
    mNfcAdapter.enableForegroundDispatch(this, mNfcPendingIntent, mWriteTagFilters, null);
}

 

@Override
protectedvoid onNewIntent(Intent intent) {
    // Tag writing mode
    if(mWriteMode && NfcAdapter.ACTION_TAG_DISCOVERED.equals(intent.getAction())) {
        Tag detectedTag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if(NfcUtils.writeTag(NfcUtils.getPlaceidAsNdef(placeidToWrite), detectedTag)) {
            Toast.makeText(this,"Success: Wrote placeid to nfc tag", Toast.LENGTH_LONG)
                .show();
            NfcUtils.soundNotify(this);
        }else{
            Toast.makeText(this,"Write failed", Toast.LENGTH_LONG).show();
        }
    }
}

 

/*
* Writes an NdefMessage to a NFC tag
*/
publicstatic boolean writeTag(NdefMessage message, Tag tag) {
    intsize = message.toByteArray().length;
    try{
        Ndef ndef = Ndef.get(tag);
        if(ndef != null) {
            ndef.connect();
            if(!ndef.isWritable()) {
                returnfalse;
            }
            if(ndef.getMaxSize() < size) {
                returnfalse;
            }
            ndef.writeNdefMessage(message);
            returntrue;
        }else{
            NdefFormatable format = NdefFormatable.get(tag);
            if(format != null) {
                try{
                    format.connect();
                    format.format(message);
                    returntrue;
                }catch(IOException e) {
                    returnfalse;
                }
            }else{
                returnfalse;
            }
        }
    }catch(Exception e) {
        returnfalse;
    }
}

相关的AndroidManifest.xml文件配置如下:

<activity android:name=".CheckInActivity">
    <intent-filter>
      <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
      <data android:mimeType="application/vnd.facebook.places"/>
      <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>
</activity>

参考文章:

http://developer.android.com/guide/topics/nfc/nfc.html

http://stackoverflow.com/questions/5078649/android-nfc-sample-demo-reads-only-fake-information-from-the-tag

http://developer.android.com/guide/topics/nfc/index.html

http://money.163.com/11/0714/09/78TPVJOL00253CVK.html

http://www.cnblogs.com/jfttcjl/archive/2011/11/09/2242045.html

http://www.jessechen.net/blog/how-to-nfc-on-the-android-platform/

另外有几个专门推动NFC技术的联盟:

http://open-nfc.org/wp/nfchal/

http://www.classic.nxp.com/theme/nfc/

http://www.nfc-forum.org/home/

官方关于NFC的翻译文档见:

http://blog.csdn.net/nicebooks/article/details/6223956

参考库:

http://code.google.com/p/guava-libraries/

原创粉丝点击