NFC framework
Posted OracleLoyal
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了NFC framework相关的知识,希望对你有一定的参考价值。
NFC framework introduce
1 NFC简介
对于NFC,是google在android4.0上推出来的,简单介绍下。近场通讯(NFC)是一系列短距离无线技术,一般需要4cm或者更短去初始化连接。近场通讯(NFC)允许你在NFC tag和Android设备或者两个Android设备间共享小负载数据。优酷上有其应用的视频:http://v.youku.com/v_show/id_XMjM3ODE5ODMy.html。
http://v.youku.com/v_show/id_XMzM1MTUyMzI4.html
2 总体框架
对于NFC框架的设计,同样是android的标准的c/s架构,其框架图如下:
n 客户端:android提供了两个API包给apk,分别是android.nfc.tech、android.nfc,实现了NFC的应用接口,代码路径frameworks/base/core/java/android/nfc/tech、frameworks/base/core/java/android/nfc。
n 服务端:packages/apps/Nfc是一个类似电话本的应用,这个程序在启动后自动运行,并一直运行,作为NFC的服务进程存在,是NFC的核心。
在这个程序代码中,有个JNI库,供NfcService调用,代码路径是packages/apps/Nfc/jni/
n 库文件:代码路径是external/libnfc-nxp,用C编写的库文件,有两个库,分别是libnfc.so和libnfc_ndef.so。libnfc.so是一个主要的库,实现了NFC stack的大部分功能,主要提供NFC的服务进程调用。libnfc_ndef是一个很小的库,主要是实现NDEF消息的解析,供framework调用
2.1 总体类图关系
2.2 数据分类
NFC按照发展,分为两种,NFC basics和Advanced NFC。从字面上理解,第一种是最先设计的,第二种是在原来基础上扩展的。
2.2.1 NFC basics
是一种点对点(P2P)数据交换的功能,传送的数据格式是NDEF,是Nfc Data Exchange Format的缩写,这个数据格式用于设备之间点对点数据的交换,例如网页地址、联系人、邮件、图片等。对于除图片以外的数据,数据量比较小,直接封装在类NdefMessage中,通过NFC将NdefMessage类型数据发送到另一台设备,而对于图片这样数据量比较大的数据,需要构建一个标准的NdefMessage数据,发送给另外一台设备,等有回应之后,再通过蓝牙传送数据。
NdefMessage类是用于数据的封装,其包含有一个或多个NdefRecord类,NdefRecord才是存储数据的实体,将联系人、邮件、网页地址等转换才byte类型的数据存储在NdefRecord当中,并且包含了数据类型。举个例子吧:
NdefRecord uriRecord = new NdefRecord( NdefRecord.TNF_ABSOLUTE_URI , "http://developer.android.com/index.html".getBytes(Charset.forName("US-ASCII")), new byte[0], new byte[0]); new NdefMessage(uriRecord);
|
以上是用NdefMessage对一个NdefRecord数据进行分装。
为了更好理解数据的传送方式,需要更细的分为三种:
n 在一个Apk中,用NdefMessage封装Apk的数据,在设置NdefRecord的数据类型,然后发送给其他设备。在接收设备的同样的APK的AndroidManifest文件中设置接收数据的类型,这样通过Intent消息就能找到对应的Activity启动。
n 直接将当前运行(除home程序外)的Apk的包名封装到NdefMessage中,发送给其他设备。接收设备收到NdefMessage数据,转换才成包名,根据包名构造Intent,启动指定的Activity。如果包名不存在,那么会启动google play去下载安装该Apk。
n 图片为数据量比较大的数据。需要封装一个标准的NdefMessage数据发送给其他设备,当有回应的时候,在将图片数据通过蓝牙发送给其他设备。
按照上面的分析,还可以将数据传送,分为小数据量的传送和大数据量的传送。小数据量是指联系人、邮件、网页地址、包名等,而大数据量是指图片等,需要通过蓝牙传送的。那么为什么NFC的功能还要蓝牙传送呢?原因是NFC的设计本来就是为了传送小的数据量,同我们通过NFC启动蓝牙传图片,更方便的不需要手动进行蓝牙的匹配,只需要将手机贴在一起就可以完成了蓝牙的匹配动作。
2.2.2 Advanced NFC
对于该类型的NFC,也是在点对点数据交换功能上的一个扩充,我们日常接触的有公交卡、饭卡,手机设备可以通过NFC功能读取该卡内的数据,也有支持NFC设备往这类卡里面写数据。所以,我们将这些卡类称为Tag。
需要直接通过Byte格式进行数据封装,对TAG数据进行读写。市面上有很多的卡,估计没个城市用的公交卡都不一样,就是使用的标准不一样,所以在 android.nfc.tech 包下支持了多种technologies,如下图:
当tag设备与手机足够近的时候,手机设备首先收到了Tag信息,里面包含了当前Tag设备所支持的technology,然后将Tag信息发送到指定的Activity中。在Activity中,将读取Tag里面的数据,构造相应的technology,然后再以该technology的标准,对tag设备进行读写。
3初始化流程
3.1 时序图
3.2 代码分析
初始化分两部分,第一是服务端的初始化,并将服务添加到ServiceManager中,第二是初始化NFC适配器NfcAdapter。
3.2.1 Server端初始化
NFC的服务端代码在packages/apps/Nfc中,并且还包含了JNI代码,前面也介绍过,NFC的服务端是一个应用程序,跟随系统启动并一直存在的一个服务进程。
NfcService继承于Application,当程序启动的时候,调用onCreate()方法,代码如下:
public void onCreate() { super.onCreate(); mNfcTagService = new TagService(); mNfcAdapter = new NfcAdapterService(); mExtrasService = new NfcAdapterExtrasService(); …… mDeviceHost = new NativeNfcManager(this, this); mNfcDispatcher = new NfcDispatcher(this, handoverManager); mP2pLinkManager = new P2pLinkManager(mContext, handoverManager); …… ServiceManager.addService(SERVICE_NAME, mNfcAdapter);//将mNfcAdapter添加到系统服务列表中。 ……. new EnableDisableTask().execute(TASK_BOOT); // do blocking boot tasks } |
TagService是NfcService的内部类,并继承于INfcTag.stub,因此客户端可以通过Binder通信获取到TagService的实例mNfcTagService。其主要的功能是完成tag的读写。
NfcAdapterService也是NfcService的内部类,并继承于INfcAdapter.stub,同样客户端可以通过Binder通信获取到NfcAdapterService的实例mNfcAdapter。NfcAdapterService也是暴露给客户端的主要接口,主要完成对NFC的使能初始化,扫面读写tag,派发tag消息等。
NativeNfcManager类就像其名字一样,主要负责native JNI的管理。
NfcDispatcher主要负责tag消息处理,并派发Intent消息,启动Activity。
3.2.2 NfcAdapter客户端初始化
在ContextImpl类中,有一个静态模块,在这里创建了NfcManager的实例,并注册到服务中,代码如下:
Static{ registerService(NFC_SERVICE, new ServiceFetcher() { public Object createService(ContextImpl ctx) { return new NfcManager(ctx); }}); } |
在NfcManager的构造函数中,调用了NfcAdapter.getNfcAdapter(context),创建NFC Adapter。
public static synchronized NfcAdapter getNfcAdapter(Context context) { …… sService = getServiceInterface();//获取NFC服务接口 …… try { sTagService = sService.getNfcTagInterface();//获取NFC tag服务接口 } catch (RemoteException e) { } …… NfcAdapter adapter = sNfcAdapters.get(context); if (adapter == null) { adapter = new NfcAdapter(context); sNfcAdapters.put(context, adapter); } return adapter; } private static INfcAdapter getServiceInterface() {//获取NFC服务接口 IBinder b = ServiceManager.getService("nfc"); if (b == null) { return null; } return INfcAdapter.Stub.asInterface(b); } |
我们看看getServiceInterface()方法,在3.2.1我们也看到了,调用ServiceManager.addService()将NfcAdapterService的实例添加到系统的服务列表中,这里我们调用了ServiceManager.getService(“nfc”)获取到了服务端的NfcAdapterService对象的实例。
在NfcAdapterService类中提供了getNfcTagInterface接口,用于获取远程服务端的TagService对象的实例。
如果一切正常,那么将创建NfcAdapter的实例,在其构造函数中,创建了NfcActivityManager的实例。
4 启动NFC流程
4.1 时序图
4.2 代码分析
如果android设备有NFC硬件支持,那么将在设置应用的出现“无线和网络à更多
以上是关于NFC framework的主要内容,如果未能解决你的问题,请参考以下文章