基于Android平台的NFC技术的应用实现 (转)

转自http://1679554191.iteye.com/blog/1738256

  近距离无线通信(NFC)是一种简单的,非触控式的互联技术,可以让消费者简单直观的交换信息,访问内容和服务,在电子消费领域有着广泛的应用。NFC整合非接触式读卡器、非接触式智能卡和点对点(Peer-to-Peer)通信功能,为消费者开创全新便捷生活方式。

1.NFC技术

     NFC终端有三种工作模式:

1)主动模式,NFC终端作为一个读卡器,主动发出自己的射频场去识别和读/写别的NFC设备;

2)被动模式,NFC终端可以模拟成一个智能卡被读写,它只能在其它设备发出的射频场中被动响应;

3)双向模式,双方都主动发出射频场来建立点对点的通信。

2.Android NFC架构

    android系统为了支持NFC功能,允许应用程序读取标签中的数据,并以NDEF(NFC Data Exchange Format)消息格式进行交互。标签还可以是另外一个设备,即NFC设备工作在卡模拟模式。

    NFC软件架构中定义的数据结构:

1)NFC管理器(NFC Manager),提供给应用程序编程接口,作为应用程序访问NFC功能的入口,为了获取NFC适配器实例。

2)NFC适配器(NFC Adapter),提供一切NFC操作,包括NFC设备开关、标签读取、NDEF数据交互、NFC安全访问、点对点通信等。

3)NDEF消息(NDEF Message),是设备和标签之间传递的数据标准封装格式,是由一个或多个NDEF数据记录组成,在应用程序中通过接受ACTION_TAG_DISCOVERED Intent来读取NDEF消息。

4)NDEF记录(NDEF Record),是NDEF数据包的基本组成单元。一个NDEF数据包可以有一个或者多个NDEF记录。

      NFC 在android架构中采用Service和Manager基本结构模型,通过Binder和Service通信,如图一所示android基于Binder的IPC的基本模型是基于会话的客户/服务器(C/S)架构的。Android使用内核模块Binder来中转各个进程之间的会话数据,它是一个字符驱动程序,主要通过IOCTL与用户空间的进程交换数据。一次会话是在一个代理Binder对象和服务Binder对象之间进行,可以在同一进程也可以在不同进程。会话是一个同步操作,由代理Binder对象发起请求,一直要等到服务Binder对象将回复传递给代理Binder对象才算完成。


3.NFC Adapter的实现

      NFC Adapter主要实现的功能如下:

1)设备初始化以及开关,相关函数方法:

private static synchronized INfcAdapter setupService()

public boolean enable()

public boolean disable()

2)NDEF消息的读写和安全管理链接,相关函数方法:

public void setLocalNdefMessage(NdefMessage message)

public NdefMessage getLocalNdefMessage()

public NdefSecureElement createNdefSecureElementConnection()

3)P2P的后台通信 ,相关函数方法:

public void enableForegroundNdefPush(Activity activity,NdefMessage message)

public void disableForegroundNdefPush(Activity activity)

       这些基本函数都是NFC Binder客户端函数,通过Binder IPC调用Service 对应的函数进行通信处理。

4.NFC Server的实现

      NFC Service主要实现以下功能:

1)Adapter中的Binder客户端对应Service函数实现,包括INfcTag.Stub,INfcAdapter.Stub等;

2)Service状态管理的消息处理;

3)Java本地接口(JNI)的Native代码的访问接口。



5. NFC HAL实现

      NFC HAL(Hardware Abstract Layer)层,包括以下功能:

1)底层RF控制;

  2)NFC标签读写处理以及标签模拟;

3)点对点通信;

4)同单总线的SIM卡或者其它安全设施通信;

5)对基于Felica,Mifare和ISO14443的RFID标签做兼容处理。


6.标签识别

      在标签识别开始前,确认NFC设备使用正常,可获取NDEF设备。NFC HAL探测到有效距离范围内有标签存在,则读取数据,向NFC Service发送标签识别事件,NFC Service 广播NfcAdapter.ACTION_TAG_DISCOVERED Intent消息,应用程序通过接受该消息即可获取标签数据。


 

7.NFC简单代码实现

 

Java代码 复制代码  收藏代码
  1. import java.nio.charset.Charset;   
  2.   
  3. import android.app.Activity;   
  4. import android.content.Intent;   
  5. import android.nfc.NdefMessage;   
  6. import android.nfc.NdefRecord;   
  7. import android.nfc.NfcAdapter;   
  8. import android.nfc.NfcAdapter.CreateNdefMessageCallback;   
  9. import android.nfc.NfcAdapter.OnNdefPushCompleteCallback;   
  10. import android.nfc.NfcEvent;   
  11. import android.os.Bundle;   
  12. import android.os.Handler;   
  13. import android.os.Message;   
  14. import android.os.Parcelable;   
  15. import android.provider.Settings;   
  16. import android.text.format.Time;   
  17. import android.view.Menu;   
  18. import android.view.MenuInflater;   
  19. import android.view.MenuItem;   
  20. import android.widget.TextView;   
  21. import android.widget.Toast;   
  22.   
  23. public class BeamActivity extends Activity implements  
  24.         CreateNdefMessageCallback,   
  25.   
  26.         OnNdefPushCompleteCallback {   
  27.   
  28.     NfcAdapter mNfcAdapter;   
  29.   
  30.     TextView mInfoText;   
  31.   
  32.     private static final int MESSAGE_SENT = 1;   
  33.   
  34.     @Override  
  35.     public void onCreate(Bundle savedInstanceState) {   
  36.   
  37.         super.onCreate(savedInstanceState);   
  38.   
  39.         setContentView(R.layout.layout_beam);   
  40.   
  41.         mInfoText = (TextView) findViewById(R.id.txtBeam);   
  42.   
  43.         mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // 实例化NFC设备   
  44.   
  45.         if (mNfcAdapter == null) {   
  46.   
  47.             mInfoText.setText("NFC is not available on this device.");   
  48.             return;   
  49.   
  50.         } else if (mNfcAdapter != null){   
  51.             if(!mNfcAdapter.isEnabled()) {   
  52.                 mInfoText.setText("请在系统设置中先启用NFC功能!");   
  53.                 return;   
  54.             }else{   
  55.                    
  56.                 Toast.makeText(this"启动NFC注册成功...", Toast.LENGTH_SHORT).show();   
  57.                    
  58.                 mNfcAdapter.setNdefPushMessageCallback(thisthis); // 注册NDEF回调消息   
  59.   
  60.                 mNfcAdapter.setOnNdefPushCompleteCallback(thisthis);   
  61.   
  62.             }   
  63.         }    
  64.   
  65.            
  66.     }   
  67.   
  68.     @Override  
  69.     public NdefMessage createNdefMessage(NfcEvent event) {   
  70.   
  71.         Time time = new Time();   
  72.   
  73.         time.setToNow();   
  74.   
  75.         String text = ("Beam me up!nn" +   
  76.   
  77.         "Beam Time: " + time.format("%H:%M:%S"));   
  78.   
  79.         NdefMessage msg = new NdefMessage(   
  80.   
  81.         new NdefRecord[] { createMimeRecord(   
  82.   
  83.         "application/com.example.android.beam", text.getBytes())   
  84.   
  85.         });   
  86.   
  87.         return msg;   
  88.   
  89.     }   
  90.   
  91.     @Override  
  92.     public void onNdefPushComplete(NfcEvent arg0) {   
  93.   
  94.         // A handler is needed to send messages to the activity when this   
  95.   
  96.         // callback occurs, because it happens from a binder thread   
  97.   
  98.         mHandler.obtainMessage(MESSAGE_SENT).sendToTarget();   
  99.   
  100.     }   
  101.   
  102.     private final Handler mHandler = new Handler() {   
  103.   
  104.         @Override  
  105.         public void handleMessage(Message msg) {   
  106.   
  107.             switch (msg.what) {   
  108.   
  109.             case MESSAGE_SENT:   
  110.   
  111.                 Toast.makeText(getApplicationContext(), "Message sent!",   
  112.                         Toast.LENGTH_LONG).show();   
  113.   
  114.                 break;   
  115.   
  116.             }   
  117.   
  118.         }   
  119.   
  120.     };   
  121.   
  122.     @Override  
  123.     public void onResume() {   
  124.   
  125.         super.onResume();   
  126.            
  127.         Toast.makeText(this"等待接受action信息...", Toast.LENGTH_SHORT).show();   
  128.         String action = this.getIntent().getAction();   
  129.         if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {   
  130.   
  131.             processIntent(getIntent());   
  132.   
  133.         }   
  134.   
  135.     }   
  136.   
  137.     @Override  
  138.     public void onNewIntent(Intent intent) {   
  139.   
  140.         // onResume gets called after this to handle the intent   
  141.   
  142.         setIntent(intent);   
  143.   
  144.     }   
  145.   
  146.     /**  
  147.      *   
  148.      * Parses the NDEF Message from the intent and prints to the TextView  
  149.      */  
  150.   
  151.     void processIntent(Intent intent) {   
  152.   
  153.         Parcelable[] rawMsgs = intent.getParcelableArrayExtra(   
  154.   
  155.         NfcAdapter.EXTRA_NDEF_MESSAGES);   
  156.   
  157.         // only one message sent during the beam   
  158.   
  159.         NdefMessage msg = (NdefMessage) rawMsgs[0];   
  160.   
  161.         // NDEF:NFC Data Exchange Format,即NFC数据交换格式   
  162.   
  163.         // record 0 contains the MIME type, record 1 is the AAR, if present   
  164.   
  165.         mInfoText.setText(new String(msg.getRecords()[0].getPayload()));   
  166.   
  167.     }   
  168.   
  169.     /**  
  170.      *   
  171.      * Creates a custom MIME type encapsulated in an NDEF record  
  172.      *   
  173.      *   
  174.      *   
  175.      * @param mimeType  
  176.      */  
  177.   
  178.     public NdefRecord createMimeRecord(String mimeType, byte[] payload) {   
  179.   
  180.         byte[] mimeBytes = mimeType.getBytes(Charset.forName("US-ASCII"));   
  181.   
  182.         NdefRecord mimeRecord = new NdefRecord(   
  183.   
  184.         NdefRecord.TNF_MIME_MEDIA, mimeBytes, new byte[0], payload);   
  185.   
  186.         return mimeRecord;   
  187.   
  188.     }   
  189.   
  190.     @Override  
  191.     public boolean onCreateOptionsMenu(Menu menu) {   
  192.   
  193.         // If NFC is not available, we won't be needing this menu   
  194.   
  195.         if (mNfcAdapter == null) {   
  196.   
  197.             return super.onCreateOptionsMenu(menu);   
  198.   
  199.         }   
  200.   
  201. //      MenuInflater inflater = getMenuInflater();   
  202. //   
  203. //      inflater.inflate(menu.CATEGORY_SYSTEM, menu);   
  204.   
  205.         return true;   
  206.   
  207.     }   
  208.   
  209.     @Override  
  210.     public boolean onOptionsItemSelected(MenuItem item) {   
  211.   
  212.         switch (item.getItemId()) {   
  213.   
  214. //      case R.id.menu_settings:   
  215.         case 0:   
  216.   
  217.             Intent intent = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);   
  218.   
  219.             startActivity(intent);   
  220.   
  221.             return true;   
  222.   
  223.         default:   
  224.   
  225.             return super.onOptionsItemSelected(item);   
  226.   
  227.         }   
  228.   
  229.     }   
  230.   
  231. }  
import java.nio.charset.Charset;

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.NfcAdapter.OnNdefPushCompleteCallback;
import android.nfc.NfcEvent;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.os.Parcelable;
import android.provider.Settings;
import android.text.format.Time;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

public class BeamActivity extends Activity implements
		CreateNdefMessageCallback,

		OnNdefPushCompleteCallback {

	NfcAdapter mNfcAdapter;

	TextView mInfoText;

	private static final int MESSAGE_SENT = 1;

	@Override
	public void onCreate(Bundle savedInstanceState) {

		super.onCreate(savedInstanceState);

		setContentView(R.layout.layout_beam);

		mInfoText = (TextView) findViewById(R.id.txtBeam);

		mNfcAdapter = NfcAdapter.getDefaultAdapter(this); // 实例化NFC设备

		if (mNfcAdapter == null) {

			mInfoText.setText("NFC is not available on this device.");
			return;

		} else if (mNfcAdapter != null){
			if(!mNfcAdapter.isEnabled()) {
				mInfoText.setText("请在系统设置中先启用NFC功能!");
				return;
			}else{
				
				Toast.makeText(this, "启动NFC注册成功...", Toast.LENGTH_SHORT).show();
				
				mNfcAdapter.setNdefPushMessageCallback(this, this); // 注册NDEF回调消息

				mNfcAdapter.setOnNdefPushCompleteCallback(this, this);

			}
		} 

		
	}

	@Override
	public NdefMessage createNdefMessage(NfcEvent event) {

		Time time = new Time();

		time.setToNow();

		String text = ("Beam me up!nn" +

		"Beam Time: " + time.format("%H:%M:%S"));

		NdefMessage msg = new NdefMessage(

		new NdefRecord[] { createMimeRecord(

		"application/com.example.android.beam", text.getBytes())

		});

		return msg;

	}

	@Override
	public void onNdefPushComplete(NfcEvent arg0) {

		// A handler is needed to send messages to the activity when this

		// callback occurs, because it happens from a binder thread

		mHandler.obtainMessage(MESSAGE_SENT).sendToTarget();

	}

	private final Handler mHandler = new Handler() {

		@Override
		public void handleMessage(Message msg) {

			switch (msg.what) {

			case MESSAGE_SENT:

				Toast.makeText(getApplicationContext(), "Message sent!",
						Toast.LENGTH_LONG).show();

				break;

			}

		}

	};

	@Override
	public void onResume() {

		super.onResume();
		
		Toast.makeText(this, "等待接受action信息...", Toast.LENGTH_SHORT).show();
		String action = this.getIntent().getAction();
		if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {

			processIntent(getIntent());

		}

	}

	@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
	 */

	void processIntent(Intent intent) {

		Parcelable[] rawMsgs = intent.getParcelableArrayExtra(

		NfcAdapter.EXTRA_NDEF_MESSAGES);

		// only one message sent during the beam

		NdefMessage msg = (NdefMessage) rawMsgs[0];

		// NDEF:NFC Data Exchange Format,即NFC数据交换格式

		// record 0 contains the MIME type, record 1 is the AAR, if present

		mInfoText.setText(new String(msg.getRecords()[0].getPayload()));

	}

	/**
	 * 
	 * Creates a custom MIME type encapsulated in an NDEF record
	 * 
	 * 
	 * 
	 * @param mimeType
	 */

	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;

	}

	@Override
	public boolean onCreateOptionsMenu(Menu menu) {

		// If NFC is not available, we won't be needing this menu

		if (mNfcAdapter == null) {

			return super.onCreateOptionsMenu(menu);

		}

//		MenuInflater inflater = getMenuInflater();
//
//		inflater.inflate(menu.CATEGORY_SYSTEM, menu);

		return true;

	}

	@Override
	public boolean onOptionsItemSelected(MenuItem item) {

		switch (item.getItemId()) {

//		case R.id.menu_settings:
		case 0:

			Intent intent = new Intent(Settings.ACTION_NFCSHARING_SETTINGS);

			startActivity(intent);

			return true;

		default:

			return super.onOptionsItemSelected(item);

		}

	}

}

 

Manifest文件的权限配置:

Java代码 复制代码  收藏代码
  1. <uses-permission android:name="android.permission.NFC" />    
  2.   
  3. <uses-feature android:name="android.hardware.nfc"    
  4. android:required="true" />  
<uses-permission android:name="android.permission.NFC" /> 

<uses-feature android:name="android.hardware.nfc" 
android:required="true" />

 

猜你喜欢

转载自xun005.iteye.com/blog/1738688