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

hgl 2012-12-04

  近距离无线通信(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对象才算完成。

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

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标签做兼容处理。

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

6.标签识别

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

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

7.NFC简单代码实现

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);    
  
        }   
  
    }   
  
}  
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文件的权限配置:

<uses-permission android:name="android.permission.NFC" />    
  

<uses-feature android:name="android.hardware.nfc"     

android:required="true" />  
<uses-permission android:name="android.permission.NFC" /> 

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

 

相关推荐