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

在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的代码为:

public static String getStatusNfcDevice () {
     NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter();
     if (nfcAdapter.isEnabled()) {
          String status = "enabled" ;
          return status;
     }
     else {
         String status = "disabled" ;
         return status;
     }
}

处理函数为

public void onResume() {
     super .onResume();
     if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())) {
         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];
             }
         }
     }
     //process the msgs array
}

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

package com.example.android.beam;
 
import android.app.Activity;
import android.content.Intent;
import android.nfc.NdefMessage;
import android.nfc.NdefRecord;
import android.nfc.NfcAdapter;
import android.nfc.NfcAdapter.CreateNdefMessageCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Parcelable;
import android.widget.TextView;
import android.widget.Toast;
import java.nio.charset.Charset;
 
//继承并实现接口CreateNdefMessageCallback方法createNdefMessage
public class Beam extends Activity implements CreateNdefMessageCallback {
     NfcAdapter mNfcAdapter;
     TextView textView;
 
     @Override
     public void 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
     public NdefMessage createNdefMessage(NfcEvent event) {
         String text = ( "Beam me up, Android!\n\n" +
                 "Beam Time: " + System.currentTimeMillis());
         //回调函数,构造NdefMessage格式
         NdefMessage msg = new NdefMessage(
                 new NdefRecord[] { 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")
         });
         return msg;
     }
 
     @Override
     public void 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
     public void 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
     void processIntent(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( new String(msg.getRecords()[ 0 ].getPayload()));
     }
 
     /**
      * Creates a custom MIME type encapsulated in an NDEF record
      */
     public NdefRecord createMimeRecord(String mimeType, byte [] payload) {
         byte [] mimeBytes = mimeType.getBytes(Charset.forName( "US-ASCII" ));
         NdefRecord mimeRecord = new NdefRecord(
                 NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte [ 0 ], payload);
         return mimeRecord;
     }
}

上面代码还需要在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设备进行写操作的时候,相关代码:

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

 

@Override
protected void 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
*/
public static 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()) {
                 return false ;
             }
             if (ndef.getMaxSize() < size) {
                 return false ;
             }
             ndef.writeNdefMessage(message);
             return true ;
         } else {
             NdefFormatable format = NdefFormatable.get(tag);
             if (format != null ) {
                 try {
                     format.connect();
                     format.format(message);
                     return true ;
                 } catch (IOException e) {
                     return false ;
                 }
             } else {
                 return false ;
             }
         }
     } catch (Exception e) {
         return false ;
     }
}

相关的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/

  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值