NFC功能开发

NFC开发

1.关于NFCAPI分析

Nfc-Android官方API

file:///D:/Util/adtforandroid/adt-bundle-windows-x86-20130522/sdk/docs/reference/android/nfc/package-summary.html

    Near  Field Communication (NFC) 为一短距离无线通信技术,通常有效通讯距离为4厘米以内。NFC工作频率为13.65 兆赫兹,通信速率为106 kbit/秒到 848kbit/秒。

NFC通信总是由一个发起者(initiator)和一个接受者(target)组成。通常initiator 主动发送电磁场(RF)可以为被动式接受者(passive target)提供电源。其工作的基本原理和收音机类似。正是由于被动式接受者可以通过发起者提供电源,因此target 可以有非常简单的形式,比如标签,卡,sticker 的形式。

    NFC 也支持点到点的通信(peer to peer) 此时参与通信的双方都有电源支持。

和其它无线通信方式如Bluetooth相比,NFC 支持的通信带宽和距离要小的多,但是它成本低,如价格标签可能只有几分钱,也不需要配对,搜寻设备等,通信双方可以在靠近的瞬间完成交互。

    在Android NFC 应用中,Android手机通常是作为通信中的发起者,也就是作为NFC 的读写器。Android手机也可以模拟作为NFC通信的接受者且从Android 2.3.3起也支持P2P通信。

    Android对NFC的支持主要在 android.nfc 和android.nfc.tech 两个包中。

android.nfc 包中主要类如下:

 

· NfcManager 可以用来管理Android设备中指出的所有NFC Adapter,但由于大部分Android设备只支持一个NFC Adapter,可以直接使用getDefaultAapater 来获取系统支持的Adapter。

· NfcAdapter 为一NFC Adapter 对象,可以用来定义一个Intent使系统在检测到NFC Tag时通知你定义的Activity,并提供用来注册forground tag 消息发送的方法等。

· NdefMessage 和NdefRecord NDEF 为NFC forum 定义的数据格式。

 

· Tag 代表一个被动式Tag对象,可以代表一个标签,卡片,钥匙扣等。当Android设备检测到一个Tag时,会创建一个Tag对象,将其放在Intent对象,然后发送到相应的Activity。


     android.nfc.tech 中则定义了可以对Tag进行的读写操作的类,这些类按照其使用的技术类型可以分成不同的类如:NfcA, NfcB, NfcF,以及MifareClassic 等。
常见的Tag为Mifare ,后面的例子将以这种Tag 为例介绍NFC读写方法。 

2.开发NFC基本步骤(MifareClassic 类型的NFC Tag 

1.  Android manifest 文件中申明和NFC相关的权限和功能选项:
权限申明:
<uses-permission android:name=android.permission.NFC” />
最低版本要求,NFC是指Android2.3 Level 10) 才开始支持的,因此最低版本要求必须指定为10.
<uses-sdk android:minSdkVersion=10/>
如果需要在Android Market上发布,需要指定手机支持NFC 功能。
<uses-feature android:name=android.hardware.nfc” android:required=true” />
Activity申明它支持处理NFC Tag
比如我们的示例Activity Manifest 的申明如下:

[mw_shl_code=java,true]<activity android:name=.NFCDemoActivity
android:label=@string/app_name
android:launchMode=singleTop>
<intent-filter>
<action android:name=android.intent.action.MAIN” />
<category android:name=android.intent.category.LAUNCHER” />
</intent-filter>
<intent-filter>
<action android:name=android.nfc.action.NDEF_DISCOVERED/>
<data android:mimeType=text/plain” />
</intent-filter>
<intent-filter>
<action
android:name=android.nfc.action.TAG_DISCOVERED
>
</action>
<category
android:name=android.intent.category.DEFAULT
>
</category>
</intent-filter>
<!– Add a technology filter >
<intent-filter>
<action android:name=android.nfc.action.TECH_DISCOVERED” />
</intent-filter>

<meta-data android:name=android.nfc.action.TECH_DISCOVERED
android:resource=@xml/filter_nfc
/>

</activity>

[/mw_shl_code]


三种Activity NDEF_DISCOVERED ,TECH_DISCOVERED,TAG_DISCOVERED 指明的先后顺序非常重要, 当Android设备检测到有NFC Tag靠近时,会根据Action申明的顺序给对应的Activity 发送含NFC消息的 Intent.

 

2. Android NFC 消息发送机制
Android设备检测到有NFC Tag时,理想的行为是触发最合适的Activity来处理检测到的Tag,这是因为NFC通常是在非常近的距离才起作用(<4m) ,如果此时需要用户来选择合适的应用来处理Tag,很容易断开与Tag之间的通信。因此你需要选择合适的Intent filter 只处理你想读写的Tag类型。

Android系统支持两种NFC消息发送机制:Intent 发送机制和前台Activity 消息发送机制。

 

Intent 发送机制 当系统检测到Tag时,Android系统提供manifest 中定义的Intent filter 来选择合适的Activity来处理对应的Tag,当有多个Activity可以处理对应的Tag类型时,则会显示Activity选择窗口由用户选择:

 

前台Activity 消息发送机制 允许一个在前台运行的Activity在读写NFC Tag 具有优先权,此时如果Android检测到有NFC  Tag ,如果前台允许的Activity可以处理该种类型的Tag则该Activity具有优先权,而不出现Activity 选择窗口。

       这两种方法基本上都是使用Intent-filter 来指明Activity可以处理的Tag类型,一个是使用Android的Manifest 来说明,一个是通过代码来申明。
下图显示当Android检测到Tag,消息发送的优先级:

 


          本例 NFCDemoActivity 支持两种NFC消息发送机制,上面的XML指明了Intent这两种方法基本上都是使用Intent-filter 来指明Activity可以处理的Tag类型,一个是使用Android的Manifest 来说明,一个是通过代码来申明。
下图显示当Android检测到Tag,消息发送的优先级:

 


本例 NFCDemoActivity 支持两种NFC消息发送机制,上面的XML指明了Intent 消息发送机制,其中

<meta-data android:name=”android.nfc.action.TECH_DISCOVERED”
android:resource=”@xml/filter_nfc”

/>
的filter_nfc 指明了支持处理的NFC Tag类型,filter_nfc.xml 定义如下:
[mw_shl_code=java,true]<resources 

xmlns:xliff=”urn:oasis:names:tc:xliff:document:1.2″

>
<!– capture anything using NfcF –

>
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
[/mw_shl_code]

因为我只有MifareClassic 类型的Tag,所以只定义了MifareClassic相关的Tag类型,如果你可以处理所有Android支持的NFC类型,可以定义为:
[mw_shl_code=java,true]<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>[/mw_shl_code]


有了这个Manifest中的申明,当Android检测到有Tag时,会显示Activity选择窗口,如上图中的Reading Example。
当NFCDemoActiviy在前台运行时,我们希望只有它来处理Mifare 类型的Tag,此时可以使用前台消息发送机制,下面的代码基本和ApiDemos中的NFC示例类似:

[mw_shl_code=java,true]public class NFCDemoActivity extends Activity { 
private NfcAdapter mAdapter; 

private PendingIntent mPendingIntent; 

private IntentFilter[] mFilters; 

private String[][] mTechLists; 

private TextView mText; 

private int mCount = 0; 

@Override
public void onCreate(Bundle savedState) { 

super.onCreate(savedState); 
setContentView(R.layout.foreground_dispatch); 
mText = (TextView) findViewById(R.id.text); 

mText.setText("Scan a tag"); 

mAdapter = NfcAdapter.getDefaultAdapter(this); 

// Create a generic PendingIntent that will be deliver 

// to this activity. The NFC stack 

// will fill in the intent with the details of the 

//discovered tag before delivering to 

// this activity. 

mPendingIntent = PendingIntent.getActivity(this, 0, 

new Intent(this, 

getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); 

// Setup an intent filter for all MIME based dispatches 

IntentFilter ndef 

= new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED); 

try { 

ndef.addDataType("*/*"); 

} catch (MalformedMimeTypeException e) { 

throw new RuntimeException("fail", e); 


mFilters = new IntentFilter[] { 

ndef, 
}; 
// Setup a tech list for all MifareClassic tags 

mTechLists 
= new String[][] { new String[] { MifareClassic.class.getName() } }; 


@Override
public void onResume() { 

super.onResume(); 
mAdapter.enableForegroundDispatch(this, 
mPendingIntent, mFilters, mTechLists); 


@Override
public void onNewIntent(Intent intent) { 

Log.i("Foreground dispatch", 

"Discovered tag with intent: " + intent); 

mText.setText("Discovered tag " + 

++mCount + " with intent: " + intent); 


@Override
public void onPause() { 

super.onPause(); 
mAdapter.disableForegroundDispatch(this); 

}
[/mw_shl_code]


只改了一行,将处理NfcF类型的Tag 改为处理MifareClassic 类型的NFC Tag。
mTechLists = new String[][] { new String[] { MifareClassic.class.getName() } };
运行该示例,每靠近一次Tag,计数加1。


,其中
<meta-data android:name=”android.nfc.action.TECH_DISCOVERED”

android:resource=”@xml/filter_nfc”

/>
的filter_nfc 指明了支持处理的NFC Tag类型,filter_nfc.xml 定义如下:

[mw_shl_code=java,true]<resources xmlns:xliff=”

urn:oasis:names:tc:xliff:document:1.2″>

<!– capture anything using NfcF –>

<tech-list>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>
[/mw_shl_code]
因为我只有MifareClassic 类型的Tag,所以只定义了MifareClassic相关的Tag类型,如

果你可以处理所有Android支持的NFC类型,可以定义为:

[mw_shl_code=java,true]<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.IsoDep</tech>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.NfcF</tech>
<tech>android.nfc.tech.NfcV</tech>
<tech>android.nfc.tech.Ndef</tech>
<tech>android.nfc.tech.NdefFormatable</tech>
<tech>android.nfc.tech.MifareClassic</tech>
<tech>android.nfc.tech.MifareUltralight</tech>
</tech-list>
</resources>[/mw_shl_code]
有了这个Manifest中的申明,当Android检测到有Tag时,会显示Activity选择窗口,

如上图中的Reading Example。

当NFCDemoActiviy在前台运行时,我们希望只有它来处理Mifare 类型的Tag,此时可

以使用前台消息发送机制,下面的代码基本和ApiDemos中的NFC示例类似:

[mw_shl_code=java,true]public class NFCDemoActivity extends Activity { 

private NfcAdapter mAdapter; 

private PendingIntent mPendingIntent; 

private IntentFilter[] mFilters; 

private String[][] mTechLists; 

private TextView mText; 

private int mCount = 0; 

@Override

public void onCreate(Bundle savedState) { 

super.onCreate(savedState); 
setContentView(R.layout.foreground_dispatch); 

mText = (TextView) findViewById(R.id.text); 

mText.setText("Scan a tag"); 

mAdapter = NfcAdapter.getDefaultAdapter(this); 

// Create a generic PendingIntent that will be deliver 

// to this activity. The NFC stack 

// will fill in the intent with the details of the 

//discovered tag before delivering to 

// this activity. 

mPendingIntent = PendingIntent.getActivity(this, 0, 

new Intent(this, 

getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); 

// Setup an intent filter for all MIME based dispatches 

IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED); 

try { 

ndef.addDataType("*/*"); 

} catch (MalformedMimeTypeException e) { 

throw new RuntimeException("fail", e); 

mFilters = new IntentFilter[] { 

ndef, 
}; 
// Setup a tech list for all MifareClassic tags 

mTechLists = new String[][] { new String[] { MifareClassic.class.getName() } }; 


@Override

public void onResume() { 

super.onResume(); 
mAdapter.enableForegroundDispatch(this, 
mPendingIntent, mFilters, mTechLists); 


@Override

public void onNewIntent(Intent intent) { 

Log.i("Foreground dispatch", 

"Discovered tag with intent: " + intent); 

mText.setText("Discovered tag " + 

++mCount + " with intent: " + intent); 

@Override

public void onPause() { 

super.onPause(); 

mAdapter.disableForegroundDispatch(this); 


}
[/mw_shl_code]
只改了一行,将处理NfcF类型的Tag 改为处理MifareClassic 类型的NFC Tag。

mTechLists = new String[][] { new String[] { MifareClassic.class.getName() } };

运行该示例,每靠近一次Tag,计数加1。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值