Android_NFC_开发介绍
API概览
Android.nfc 和android.nfc.tech 为android 处理nfc的java 包.
1.Android.nfc package包含顶层类用来与本地NFC适配器交互. 这些类可以表示被检测到的tags和用NDEF数据格式。
类 |
描述 |
一个NFC adapter的管理器,可以列出所有此android设备支持的NFC adapter. 只不过大部分android 设备只有一个NFC adapter,所以你大部分情况下可以直接用静态方法 getDefaultAdapter(context)来取适配器。 |
|
表示本设备的NFC adapter,可以定义Intent来请求将系统检测到tags的提醒发送到你的Activity.并提供方法去注册前台tag提醒发布和前台NDEF推送。 前台NDEF推送是当前android版本唯一支持的p2p NFC通信方式。 |
|
And |
NDEF是NFC论坛定义的数据结构,用来有效的存数据到NFC tags.比如文本,URL,和其他MIME类型。 一个NdefMessage扮演一个容器,这个容器存哪些发送和读到的数据。一个NdefMessage对象包含0或多个NdefRecord,每个NdefRecord有一个类型,比如文本,URL,智慧型海报/广告,或其他MIME数据。 在NdefMessage里的第一个NfcRecord的类型用来发送tag到一个android设备上的activity. |
标示一个被动的NFC目标,比如tag,card,钥匙挂扣,甚至是一个电话模拟的的NFC卡. 当一个tag被检测到,一个tag对象将被创建并且封装到一个Intent里,然后NFC 发布系统将这个Intent用startActivity发送到注册了接受这种Intent的activity里。你可以用getTechList()方法来得到这个tag支持的技术细节和创建一个android.nfc.tech提供的相应的TagTechnology对象。 |
2.android.nfc.tech package 包含那些对tag查询属性和进行I/O操作的类。这些类分别标示一个tag支持的不同的NFC技术标准。
类 |
描述 |
这个接口是下面所有tag technology类必须实现的。 |
|
支持ISO 14443-3A 标准的操作。Provides access to NFC-A (ISO 14443-3A) properties and I/O operations. |
|
Provides access to NFC-B (ISO 14443-3B) properties and I/O operations. |
|
Provides access to NFC-F (JIS 6319-4) properties and I/O operations. |
|
Provides access to NFC-V (ISO 15693) properties and I/O operations. |
|
Provides access to ISO-DEP (ISO 14443-4) properties and I/O operations. |
|
提供对那些被格式化为NDEF的tag的数据的访问和其他操作。 Provides access to NDEF data and operations on NFC tags that have been formatted as NDEF. |
|
对那些可以被格式化成NDEF格式的tag提供一个格式化的操作 |
|
如果android设备支持MIFARE,提供对MIFARE Classic目标的属性和I/O操作。 |
|
如果android设备支持MIFARE,提供对MIFARE Ultralight目标的属性和I/O操作。 |
API版本区别
1.API level 9以前不支持NFC
2.API level 9只包含有限的tag(标签)支持,包括:
1).通过ACTION_TAG_DISCOVERED来发布Tag信息
3).只有通过EXTRA_NDEF_MESSAGES扩展来访问NDEF消息
3).其他的tag属性和I/O操作都不支持
API level 10实现对tag的广泛的读写支持。
Android NFC API Reference
NFC简洁
近场通信(NFC)是一个短范围无线技术集合,通常需要4厘米或更短的距离才能初始化连接。NFC允许在NFC标签和Android设备之间或两个Android设备之间共享小的数据的负载。
NFC标签具有复杂的分类。简单的NFC标签只提供读写语法,某些时候一次只能以只读的方式读取卡片的可编程区域。复杂一点的NFC标签提供了数学运算能力,而且有加密的硬件来认证对一个扇区的访问。最复杂的NFC标签包含了运算环境,允许在标签上执行复杂的交互代码。存储在标签中的数据也可以用各种格式来编写,但是大多数的Android框架API都使用基于NDEF(NFC Data Exchange Format)的标准。
1.NFC基础
本文介绍在Android系通过你所能执行的基本任务。它解释了如何用NDEF消息格式来发送和接收NFC数据,并且介绍了支持这些功能的Android框架API。有关更高级的话题,包括对非NDEF格式数据的讨论,情况“高级 NFC” NDEF数据和Android一起工作的场景主要有两个:
1.从NFC标签中读取NDEF数据;
【读数据】
2.把NDEF消息从一个设备发送给另一个设备。【数据传递】
从NFC标签中读取NDEF数据是用标签调度系统来处理的,它会分析被发现的NFC标签,对数据进行适当的分类,并启动对该类数据感兴趣的应用程序。想要处理被扫描到NFC标签的应用程序会声明一个Intent过滤器,并请求处理数据。
Android
Beam™ 功能允许设备把一个NDEF消息推送到物理/硬件上相互监听的另一个设备上。这种交互提供了比其他无线技术(如蓝牙)更容易的发送数据的方法。因为NFC不需要手动的设备发现或配对要求,两个设备在接近到一定范围时会自动的连接。Android Beam通过一组NFC API来使用,以便应用程序能够在设备之间来传输信息。例如,通信录、浏览器以及YouTube等应用程序都使用Android Beam来跟其他设备共享通信录、网页和视频。
1.1 NFC标签调度系统 (The Tag Dispatch System)
通常,除非是在设备的设置菜单中NFC被禁用,否则Android设备会在非锁屏的状态下搜索NFC。当Android设备发现NFC标签时,期望的行为是用最合适的Activity来处理该Intent,而不是询问用户使用什么应用程序。因为设备只能在很短的范围内扫描到NFC标签,强制的让用户手动的选择一个Activity,会导致设备离开NFC标签,从而中断该连接。你应该开发你自己的Activity来处理你所关心的NFC标签,从而阻止 选择器的操作。
为了帮助你达到这个目标,Android提供了特殊的标签调度系统,来分析扫描到的NFC标签,通过解析数据,在被扫描到的数据中尝试找到感兴趣的应用程序,具体做法如下:
1.解析NFC标签并搞清楚标签中标识数据负载的MIME类型或URI;
2.把MIME类型或URI以及数据负载封装到一个Intent中。
3.基于Intent来启动Activity。
1.1.1 怎样把NFC标签映射到MIME类型和URI
开始编写NFC应用程序之前,重要的是要理解不同类型的NFC标签、标签调度系统是如何解析NFC标签的、以及在检测到NDEF消息时,标签调度系统所做的特定的工作等。NFC标签涉及到广泛的技术,并且有很多不同的方法向标签中写入数据。Android支持由NFC Forum所定义的NDEF标准。
NDEF数据被封装在一个消息(NdefMessage)中,该消息中包含了一条或多条记录(NdefRecord)。每个NDEF记录必须具有良好的你想要创建的记录类型的规范的格式。Android也支持其他的不包含NDEF数据类型的标签,你能够使用android.nfc.tech包中的类来工作。要使用其他类型标签来工作,涉及到编写自己的跟该标签通信的协议栈,因此我们建议你尽可能的使用NDEF,以便减少开发难度,并且最大化的支持Android设备。
注意:要下载完整的NDEF规范,请去“NFC论坛规范下载”网址来下载。
现在,你已经具备了一些NFC标签的背景知识,接下来要详细的介绍Android是如何处理NDEF格式的标签的。当Android设备扫描到包含NDEF格式数据的NFC标签时,它会解析该消息,并尝试搞清楚数据的MIME类型或URI标识。首先系统会读取消息(NdefMessage)中的第一条NdefRecord,来判断如何解释整个NDEF消息(一个NDEF消息能够有多条NDEF记录)。 在格式良好的NDEF消息中,第一条NdefRecord包含以下字段信息:
1)3-bit
TNF(类型名称格式) 指示如何解释可变长度类型字段,在下表1中介绍有效值。
2)可变长度类型 说明记录的类型,如果使用TNF_WELL_KNOWN,那么则使用这个字段来指定记录的类型定义(RTD)。在下表2中定义了有效的RTD值。
3)可变长度ID 唯一标识该记录。这个字段不经常使用,但是,如果需要唯一的标识一个标记,那么就可以为该字段创建一个ID。
4)可变长度负载 你想读/写的实际的数据负载。一个NDEF消息能够包含多个NDEF记录,因此不要以为在NDEF消息的第一条NDEF记录中包含了所有的负载。
标签调度系统使用TNF和类型字段来尝试把MIME类型或URI映射到NDEF消息中。如果成功,它会把信息跟实际的负载一起封装到ACTION_NEDF_DISCOVERED类型的Intent中。但是,会有标签调度系统不能根据第一条NDEF记录来判断数据类型的情况,这样就会有NDEF数据不能被映射到MIME类型或URI,或者是NFC标签没有包含NDEF开始数据的情况发生。在这种情况下,就会用一个标签技术信息相关的Tag对象和封装在ACTION_TECH_DISCOVERED类型Intent对象内部的负载来代替。
表1.介绍标签调度系统映射如何把TNF和类型字段映射到MIME型或URI上。同时也介绍了那种类型的TNF不能被映射到MIME类型或URI上。这种情况下,标签调度系统会退化到ACTION_TECH_DISCOVERED类型的Intent对象。
例如,如果标签调度系统遇到一个TNF_ABSOLUTE_URI类型的记录,它会把这个记录的可变长度类型字段映射到一个URI中。标签调度系统会把这个URI跟其他相关的标签的信息(如数据负载)一起封装到ACTION_NDEF_DISCOVERED的Intent对象中。在另一方面,如果遇到了TNF_UNKNOWN类型,它会创建一个封装了标签技术信息的Intent对象来代替。
表1. 所支持的TNF和它们的映射
类型名称格式(TNF) |
映射 |
TNF_ABSOLUTE_URI |
基于类型字段的URI |
TNF_EMPTY |
退化到ACTION_TECH_DISCOVERED类型的Intent对象 |
TNF_EXTERNAL_TYPE |
基于类型字段中URN的URI。URN是缩短的格式(<domain_name>:<service_name)被编码到NDEF类型中。 Android会把这个URN映射成以下格式的URI:vnd.android.nfc://ext/<domain_name>:<service_name> |
TNF_MIME_MEDIA |
基于类型字段的MIME类型 |
TNF_UNCHANGED |
退化到ACTION_TECH_DISCOVERED类型的Intent对象 |
TNF_UNKNOWN |
退化到ACTION_TECH_DISCOVERED类型的Intent对象 |
TNF_WELL_KNOWN |
依赖你在类型字段中设置的记录类型定义(RTD)的MIME类型或URI |
表2. TNF_WELL_KNOWN所支持的RTD和它们的映射
记录类型定义(RTD) |
映射 |
RTD_ALTERNATIVE_CARRIER |
退化到ACTION_TECH_DISCOVERED类型的Intent对象 |
RTD_HANDOVER_CARRIER |
退化到ACTION_TECH_DISCOVERED类型的Intent对象 |
RTD_HANDOVER_REQUEST |
退化到ACTION_TECH_DISCOVERED类型的Intent对象 |
RTD_HANDOVER_SELECT |
退化到ACTION_TECH_DISCOVERED类型的Intent对象 |
RTD_SMART_POSTER |
基于负载解析的URI |
RTD_TEXT |
text/plain类型的MIME |
RTD_URI |
基于有效负载的URI |
1.1.2 应用程序如何调度NFC标签
当标签调度系统完成对NFC标签和它的标识信息封装的Intent对象的创建时,它会把该Intent对象发送给感兴趣的应用程序。如果有多个应用程序能够处理该Intent对象,就会显示Activity选择器,让用户选择Activity。标签调度系统定义了三种Intent对象,以下按照由高到低的优先级列出这三种Intent对象:
1. ACTION_NDEF_DISCOVERED: 这种Intent用于启动包含NDEF负载和已知类型的标签的Activity。这是最高优先级的Intent,并且标签调度系统在任何其他Intent之前,都会尽可能的尝试使用这种类型的Intent来启动Activity。
2. ACTION_TECH_DISCOVERED: 如果没有注册处理ACTION_NDEF_DISCOVERED类型的Intent的Activity,那么标签调度系统会尝试使用这种类型的Intent来启动应用程序。如果被扫描到的标签包含了不能被映射到MIME类型或URI的NDEF数据,或者没有包含NDEF数据,但是是已知的标签技术,那么也会直接启动这种类型的Intent对象(而不是先启动ACTION_NDEF_DISCOVERED类型的Intent)
3. ACTION_TAB_DISCOVERED: 如果没有处理ACTION_NDEF_DISCOVERED或ACTION_TECH_DISCOVERED类型Intent的Activity,就会启动这种类型的Intent。
标签调度系统的基本工作方法如下:
1.用解析NFC标签时由标签调度系统创建的Intent对象(ACTION_NDEF_DISCOVERED或ACTION_TECH_DISCOVERED)来尝试启动Activity;
2.如果没有对应的处理Intent的Activity,那么就会尝试使用下一个优先级的Intent(ACTION_TECH_DISCOVERED或ACTION_TAG_DISCOVERED)来启动Activity,直到有对应的应用程序来处理这个Intent,或者是直到标签调度系统尝试了所有可能的Intent。
3. 如果没有应用程序来处理任何类型的Intent,那么就不做任何事情。
在可能的情况下,都会使用NDEF消息和ACTION_NDEF_DISCOVERED类型的Intent来工作,因为它是这三种Intent中最标准的。这种Intent与其他两种Intent相比,它会允许你在更加合适的时机来启动你的应用程序,从而给用户带来更好的体验。
图1. 标签调度系统
1.2 在Android的Manifest中申请NFC访问
在访问设备的NFC硬件和正确的处理NFC的Intent之前,要在AndroidManifest.xml文件中进行以下声明:
1. 在<uses-permission>元素中声明访问NFC硬件:
<uses-permission android:name="android.permission.NFC"
/>
2. 你的应用程序所支持的最小的SDK版本。API Level 9只通过ACTION_TAG_DISCOVERED来支持有限的标签调度,并且只能通过EXTRA_NDEF_MESSAGES来访问NDEF消息。没有其他的标签属性或I/O操作可用。API Level 10中包含了广泛的读写支持,从而更好的推动了NDEF的应用前景,并且API Leve 14用Android Beam和额外的方便的创建NDEF记录的方法,向外提供了更容易的把NDEF消息推送给其他设备的方法。
<uses-sdk android:minSdkVersion="10"/>
3. 使用uses-feature元素,在Google Play中,以便你的应用程序能够只针对有NFC硬件的设备来显示。
<uses-feature android:name="android.hardware.nfc"
android:required="true"/>
如果你的应用程序使用了NFC功能,但是相关的功能又不是你的应用程序的关键功能,你可以忽略uses-feature元素,并且要在运行时通过调用getDefaultAdapter()方法来检查NFC是否有效。
1.3 过滤NFC的Intent
要在你想要处理被扫描到的NFC标签时启动你的应用程序,可以在你的应用程序的Android清单中针对一种、两种或全部三种类型的NFC的Intent来过滤。
1.但是,通常想要在应用程序启动时控制最常用的ACTION_NDEF_DISCOVERED类型的Intent。
2.在没有过滤ACTION_NDEF_DISCOVERED类型的Intent的应用程序,或数据负载不是NDEF时,才会从ACTION_NDEF_DISCOVERED类型的Intent回退到ACTION_TECH_DISCOVERED类型的Intent。
3.通常ACTION_TAB_DISCOVERED是最一般化的过滤分类。很多应用程序都会在过滤ACTION_TAG_DISCOVERED之前,过滤ACTION_NDEF_DISCOVERED或ACTION_TECH_DISCOVERED,这样就会降低你的应用程序被启动的可能性。ACTION_TAG_DISCOVERED只是在没有应用程序处理ACTION_NDEF_DISCOVERED或ACTION_TECH_DISCOVERED类型的Intent的情况下,才使用的最后手段。
因为NFC标签的多样性,并且很多时候不在你的控制之下,因此在必要的时候你要回退到其他两种类型的Intent。在你能够控制标签的类型和写入的数据时,我们建议你使用NDEF格式。下文将介绍如何过滤每种类型的Intent对象。
1.3.1 ACTION_NDEF_DISCOVERED
要过滤ACTION_NDEF_DISCOVERED类型的Intent,就要在清单中跟你想要过滤的数据一起来声明该类型的Intent过滤器。
以下是过滤text/plain类型的MIME的ACTION_NDEF_DISCOVERED类型过滤器的声明:
<intent-filter>
<action
android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:mimeType="text/plain" />
</intent-filter>
以下示例使用http://developer.android.com/index.html格式的URI来过滤:
<intent-filter>
<action
android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:scheme="http"
android:host="developer.android.com"
android:pathPrefix="/index.html"
/>
</intent-filter>
1.3.2
ACTION_TECH_DISCOVERED
如果你的Activity要过滤ACTION_TECH_DISCOVERED类型的Intent,你必须创建一个XML资源文件,该文件在tech-list集合中指定你的Activity所支持的技术。如果tech-list集合是标签所支持的技术的一个子集,那么你的Activity被认为是匹配的。通过调用getTechList()方法来获得标签所支持的技术集合。
例如,如果扫描到的标签支持MifareClassic、NdefFormatable和NfcA,那么为了跟它们匹配,tech-list集合就必须指定所有这三种技术,或者指定其中的两种或一种。
以下示例定义了所有的相关的技术。你可以根据需要删除其中一些设置。然后把这个文件保存到<project-root>/res/xml文件夹中(你能够把命名为任何你希望的名字):
<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>
你也能够指定多个tech-list集合,每个tech-list集合被认为是独立的,并且如果任何一个tech-list集合是由getTechList()返回的技术的子集,那么你的Activity就被认为是匹配的。
下列示例能够跟支持NfcA和Ndef技术NFC标签或者跟支持NfcB和Ndef技术的标签相匹配:
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.NfcA</tech>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</resources>
<resources
xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
<tech-list>
<tech>android.nfc.tech.NfcB</tech>
<tech>android.nfc.tech.Ndef</tech>
</tech-list>
</resources>
在你的AndroidManifest.xml文件中,要像向下列示例那样,在<activity>元素内的<meta-data>元素中指定你创建的资源文件:
<activity>
...
<intent-filter>
<action
android:name="android.nfc.action.TECH_DISCOVERED"/>
</intent-filter>
<meta-data
android:name="android.nfc.action.TECH_DISCOVERED"
android:resource="@xml/nfc_tech_filter"
/>
...
</activity>
1.3.3
ACTION_TAG_DISCOVERED
使用下列Intent过滤器来过滤ACTION_TAG_DISCOVERED类型的Intent:
<intent-filter>
<action
android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
1.3.4 从Intent中获取信息
如果因为NFC的Intent而启动一个Activity,那么你就能够从Intent中获取被扫描到的NFC标签的相关信息。根据被扫描到的标签,Intent对象能够以下额外的信息:
1. EXTRA_TAG(必须的):它是一个代表了被扫描到的标签的Tag对象;
2. EXTRA_NDEF_MESSAGES(可选):它是一个解析来自标签中的NDEF消息的数组。这个附加信息是强制在Intent对象上的;
3. EXTRA_ID(可选):标签的低级ID。(注:这个id是一个低级别的编号,用于防碰撞和鉴定, 大多数标签都有一个稳定的唯一标识符(UID),但有一些标签在每次发现他们时将生成一个随机的ID(RID),还有一些根本就没有ID的标签(字节数组将是零大小)。这个值不可能为NULL。)
要获取这些附加信息,就要确保你的Activity是被扫描到的NFC的Intent对象启动的,然后才能获得Intent之外的附加信息。
下例检查ACTION_NDEF_DISCOVERED类型的Intent,并从Intent对象的附加信息中获取NDEF消息。
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
}
此外,你还能够从Intent对象中获得一个Tag对象,该对象包含了数据负载,并允许你列举标签的技术:
Tag tag=
intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
1.4 创建通用的NDEF记录类型
本节介绍如何创建通用的NDEF记录类型,以便帮助你向NFC标签写入或用Android
Beam发送数据。
从Android4.0(API Level14)开始,可以用createUri()方法来帮助你自动的创建URI记录。
从Android4.1(API Level 16)开始,可以用createExternal()和createMime()方法来帮助你创建MIME和外部类型的NDEF记录。
使用这些辅助方法会尽可能的避免手动创建NDEF记录的错误。
本节还要介绍如何创建NDEF记录对应的Intent过滤器。所有的这些写入或发送到NFC标签的NDEF记录例子都应该是NDEF消息的第一条记录。
1.4.1 TNF_ABSOLUTE_URI
注意:我们推荐你使用RTD_URI类型,而不是TNF_ABSOLUTE_URI,
因为它更高效。
用下列方法创建一个TNF_ABSOLUTE_URI类型的NDEF记录:
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]);
对应的Intent过滤器如下:
<intent-filter>
<action
android:name="android.nfc.action.NDEF_DISCOVERED" />
<category
android:name="android.intent.category.DEFAULT" />
<data
android:scheme="http"
android:host="developer.android.com"
android:pathPrefix="/index.html"
/>
</intent-filter>
1.4.2 TNF_MIME_MEDIA
使用下列方法创建TNF_MIME_MEDIA类型的NDEF记录。
使用createMime()方法:
NdefRecord mimeRecord = NdefRecord.createMime("application/vnd.com.example.android.beam","Beam
me up, Android".getBytes(Charset.forName("US-ASCII")));
手动的创建NdefRecord:
NdefRecord mimeRecord = new
NdefRecord(NdefRecord.TNF_MIME_MEDIA
,"application/vnd.com.example.android.beam".getBytes(Charset.forName("US-ASCII")),
new byte[0], "Beam me up,
Android!".getBytes(Charset.forName("US-ASCII")));
对应的Intent过滤器如下:
<intent-filter>
<action
android:name="android.nfc.action.NDEF_DISCOVERED" />
<category android:name="android.intent.category.DEFAULT"
/>
<data
android:mimeType="application/vnd.com.example.android.beam" />
</intent-filter>
1.4.3 TNF_WELL_KNOWN和RTD_TEXT
用下列方法创建TNF_WELL_KNOWN类型的NDEF记录:
public
NdefRecord createTextRecord(String payload, Locale locale, boolean
encodeInUtf8) {
byte[] langBytes = locale.getLanguage().getBytes(Charset.forName("US-ASCII"));
Charset utfEncoding = encodeInUtf8 ?
Charset.forName("UTF-8") : Charset.forName("UTF-16");
byte[] textBytes = payload.getBytes(utfEncoding);
int utfBit = encodeInUtf8 ? 0 : (1 << 7);
char status = (char) (utfBit + langBytes.length);
byte[] data = new byte[1 + langBytes.length +
textBytes.length];
data[0] = (byte) status;
System.arraycopy(langBytes, 0, data, 1, langBytes.length);
System.arraycopy(textBytes, 0, data, 1 +
langBytes.length, textBytes.length);
NdefRecord record = new
NdefRecord(NdefRecord.TNF_WELL_KNOWN,
NdefRecord.RTD_TEXT, new byte[0], data);
return record;
}
对应的Intent过滤器如下:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"
/>
<category
android:name="android.intent.category.DEFAULT" />
<data android:mimeType="text/plain" />
</intent-filter>
1.4.4 TNF_WELL_KNOW和RTD_URI
用下列方法创建TNF_WELL_KNOWN类型的NDEF记录。
使用createUri(String)方法:
NdefRecord rtdUriRecord1=NdefRecord.createUri("http://example.com");
使用createUri(Uri)方法:
Uri uri =
new Uri("http://example.com");
NdefRecord rtdUriRecord2
= NdefRecord.createUri(uri);
手动的创建NdefRecord:
byte[]
uriField = "example.com".getBytes(Charset.forName("US-ASCII"));
byte[]
payload = new byte[uriField.length + 1]; //add 1 for the URI Prefix
byte
payload[0] = 0x01; //prefixes http://www. to the URI
System.arraycopy(uriField,
0, payload, 1, uriField.length); //appends URI to payload
NdefRecord rtdUriRecord
= new NdefRecord(NdefRecord.TNF_WELL_KNOWN, NdefRecord.RTD_URI, new byte[0],
payload);
对应的Intent过滤器如下:
<intent-filter>
<action
android:name="android.nfc.action.NDEF_DISCOVERED" />
<category
android:name="android.intent.category.DEFAULT" />
<data android:scheme="http"
android:host="example.com"
android:pathPrefix="" />
</intent-filter>
使用下列方法创建TNF_EXTERNAL_TYPE类型的记录。
使用createExternal()方法:
byte[]
payload; //assign to your data
String
domain = "com.example"; //usually your app's package name
String type
= "externalType";
NdefRecord
extRecord = NdefRecord.createExternal(domain, type, payload);
手动的创建NdefRecord:
byte[]
payload;
...
NdefRecord
extRecord = new NdefRecord(
NdefRecord.TNF_EXTERNAL_TYPE,
"com.example:externalType", new byte[0], payload);
对应的Intent过滤器如下:
<intent-filter>
<action
android:name="android.nfc.action.NDEF_DISCOVERED" />
<category
android:name="android.intent.category.DEFAULT" />
<data android:scheme="vnd.android.nfc"
android:host="ext"
android:pathPrefix="/com.example:externalType"/>
</intent-filter>
使用更加一般化的TNF_EXTERNAL_TYPE类型NFC部署,以便更好的支持Android设备和非Android设备。
注意:TNF_EXTERNAL_TYPE类型的URN包含以下格式:
urn:nfc:ext:example.com.externalType,但是,NFC论坛的RTD规范声明,URN的urn:nfc:ext:部分在NDEF记录中必须忽略。因此你需要提供的所有信息是用“:”号把域名(示例中的example.com)和类型(示例中的externalType)分离开。在调度TNF_EXTERNAL_TYPE类型的记录时,Android会把urn:nfc:ext:example.com:externalType的URN转换成vnd.android.nfc://ext/example.com:externalType的URI,它是在示例中声明的Intent过滤器。
1.5 Android应用程序记录
在Android4.0(API Level 14)中引入的Android应用程序记录(Android Application Record---AAR),提供了较强的在扫描到NFC标签时,启动应用程序的确定性。AAR有嵌入到NDEF记录内部的应用程序的包名。你能够把一个AAR添加到你的NDEF消息的任何记录中,因为Android会针对AAR来搜索整个NDEF消息。如果它找到一个AAR,它就会基于AAR内部的包名来启动应用程序。如果该应用程序不在当前的设备上,会启动Google Play来下载对应的应用程序。
如果你想要防止其他的应用对相同的Intent的过滤并潜在的处理你部署的特定的NFC标签,那么AAR是有用的。AAR仅在应用程序级被支持,因为包名的约束,并不能在Activity级别来过滤Intent。如果你想要在Activity级处理Intent,请使用Intent过滤器。
如果NFC标签中包含了AAR,则NFC标签调度系统会按照下列方式来调度:
1. 通常,尝试使用Intent过滤器来启动一个Activity。如果跟该Intent匹配的Activity也跟AAR匹配,那么就启动该Activity。
2. 如果跟Intent队形的Activity跟AAR不匹配,或者是有多个Activity能够处理该Intent,或者是没有能够处理该Intent的Activity存在,那么就启动由AAR指定的应用程序。
3. 如果没有跟该AAR对应的应用程序,那么就会启动Google Play来小组基于该AAR的应用程序。
注意:你能够用前台调度系统来重写AAR和Intent调度系统,在NFC标签被发现时。它允许优先使用前台的Activity。用这种方法,Activity必须是在前台来重写AAR和Intent调度系统。
如果你依然想要过滤扫描到的没有包含AAR的NFC标签,通常,你能够声明Intent过滤器。如果你的应用程序对不包含AAR的其他NFC标签感兴趣,这种做法是有用的。例如,你可能想要保证你的应用程序处理你部署的专用NFC标签,以及由第三方部署的普通的NFC标签。要记住AAR是在Android4.0以后才指定的,因此部署NFC标签时,你很可能希望使用能够广泛支持AAR和MIME类型/URI的是设备。另外,在你部署NFC标签时,还要想如何编写你的NFC标签,以便让大多数设备(Android设备和其他设备)支持。同过定义相对唯一的MIME类型或URI,让应用程序更容易的区分,就可以做到这一点。
Android提供了简单的创建AAR的API:createApplicationRecord()。你需要做的所有工作就是把AAR嵌入到你的NdefMessage中。除非AAR是NdefMessage中的唯一记录,否则不要把使用NdefMessage的第一条记录。这是因为,Android系统会检查NdefMessage的第一条记录来判断NFC标签的MIME类型或URI,这些信息被用于创建对应应用程序的Intent对象。以下代码演示了如何创建一个AAR:
NdefMessage msg
= new NdefMessage(
new NdefRecord[] {
...,
NdefRecord.createApplicationRecord("com.example.android.beam")
}
1.6 把NDEF消息发射到其他设备上
Android Beam允许在两个Android设备之间进行简单的对等数据交换,想要把数据发送给另一个设备的应用程序必须是在前台,并且接收数据的设备必须不被锁定。当发射设备跟接收设备的距离足够近的时候,发射设备会显示“Touch to Beam(触摸发射)”的UI。然后,用户能够选择是否把消息发射给接收设备。
注意:在API Level 10中可以利用前台的NDEF推送,它提供了与Android Beam类似的功能。这些API已经过时了,但是在一些老旧设备上还有效。更多的信息请看enableForegroundNdefPush()。
通过调用下列两个方法中的任意一个,就能够为你的应用程序启用Android Beam:
1. setNdefPushMessage():这个方法把接收到的NdefMessage对象作为一个消息设置给Beam。当两个设备足够近的时候,就会自动的发送消息。
2. setNdefPushMessageCallback():接收包含createNdefMessage()方法的回调,当设备在发射数据的范围内时,这个回调方法会被调用。回调会让你只在需要的时候创建NDEF消息。
一个Activity一次只能推送一条NDEF消息,因此如果同时使用了这两种方法,那么setNdefPushMessageCallback()方法的优先级要高于setNdefPushMessage()方法。要使用Android
Beam,通常必须满足以下条件:
1. 发射数据的Activity必须是在前台。两个设备的屏幕都必须没有被锁定;
2. 必须发要发射的数据封装到一个NdefMessage对象中;
3. 接收发射数据的NFC设备必须支持com.android.npp
NDEF推送协议或是NFC组织的SNEP协议(简单的NDEF交换协议)。在API Level9(Android2.3)到API Level 13(Android3.2)的设备上需要com.android.npp协议。在API Level 14(Android4.0)和以后的设备上,com.android.npp和SNEP都需要。
注意:如果在前台的Activity启用了Android Beam,那么标准的Intent调度系统就会被禁用。但是,如果该Activity还启用了前台调度,那么在前台调度系统中,它依然能够扫描到跟Intent过滤器匹配的NFC标签。
启用Android Beam:
1. 创建一个准备推送到另一个设备上的包含NdefRecord的NdefMessage对象。
2. 调用带有NdefMessage类型参数的setNdefPushMessage()方法,或者是在Activity的onCreate()方法中调用setNdefPushMessageCallback方法来传递实现NfcAdapter.CreateNdefMessageCallback接口的对象。这两个方法都至少需要一个准备要启用Android Beam的Activity,以及一个可选的其他的活跃的Activity列表。
通常,如果你的Activity在任何时候都值推送相同的NDEF消息,那么当两个设备在通信范围内的时候,使用setNdefPushMessage()就可以了。当你的应用程序要关注应用程序的当前内容,并想要根据用户在你的应用程序中的行为来推送NDEF消息时,就要使用setNdefPushMessageCallback方法。
下列示例代码演示了如何在activity的onCreate()方法中调用NfcAdapter.CreateNdefMessageCallback方法(完整的示例请看AndroidBeamDemo)。这个示例中还有帮助创建MIME记录的方法:
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;
public class
Beame xtends Activity implements CreateNdefMessageCallback{
NfcAdapter mNfcAdapter;
TextView textView;
@Override
publicvoid onCreate(Bundle
savedInstanceState){
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
TextView textView =(TextView)
findViewById(R.id.textView);
// Check for available NFC Adapter
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
publicNdefMessage
createNdefMessage(NfcEventevent){
String text =("Beam me up,
Android!\n\n"+"Beam Time: "+System.currentTimeMillis());
NdefMessage msg
=newNdefMessage(newNdefRecord[]{ createMime(
"application/vnd.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
publicvoid onResume(){
super.onResume();
// Check to see that the Activity started due
to an Android Beam
if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(getIntent().getAction())){
processIntent(getIntent());
}
}
@Override
publicvoid 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){
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(newString(msg.getRecords()[0].getPayload()));
}
}
注意:上例代码把AAR给注释掉了,你可以删除它。如果你启用了AAR,那么该应用程序就会始终接收在AAR中指定的Android Beam消息。如果该应用程序不存在,Google Play就会启动下载程序。因此,如果使用AAR,对于Android4.0以后的设备,下列的Intent过滤器,在技术上不是必须的:
<intent-filter>
<action
android:name="android.nfc.action.NDEF_DISCOVERED"/>
<category android:name="android.intent.category.DEFAULT"/>
<data
android:mimeType="application/vnd.com.example.android.beam"/>
</intent-filter>
有了这个Intent过滤器,com.example.android.beam应用就能够在以下情况下被启动:
1. 扫描到NFC标签;
2. 接收到com.example.android.beam类型的AAR或NDEF消息中包含一条application/vnd.com.example.android.beam类型的MIME记录的Android beam的时候。
即使通过AAR能够保证了一个应用程序被启动或下载,但是还是推荐使用Intent过滤器,因为它会让你选择启动应用程序中Activity,而不是总启动AAR中指定的应用程序包的主Activity。AAR没有Activity级别的粒度。而且还有一些android设备不支持AAR,你还应该在NDEF消息的第一条NDEF记录中嵌入标识信息,以及对应的过滤器。
2.Advanced
NFC
本文介绍一些高级的NFC专题,如多样的NFC标签技术、编写NFC标签、以及前台调度,前台调度允许在前台的应用程序优先调度Intent事件,即使还有其他的过滤同样的Intent事件的应用程序存在。
2.1 Android所支持的NFC标签技术
在使用NFC标签和Android设备来进行工作的时候,使用的读写NFC标签上数据的主要格式是NDEF。当设备扫描到带有NDEF的数据时,Android会提供对消息解析的支持,并在可能的时候,会以NdefMessage对象的形式来发送它。但是,有些情况下,设备扫描到的NFC标签没有包含NDEF数据,或者该NDEF数据没有被映射到MIME类型或URI。在这些情况下,你需要打开跟NFC标签的通信,并用自己的协议(原始的字节形式)来读写它。Android用android.nfc.tech包提供了对这些情况的一般性支持,这个包在下表1中介绍。你能够使用getTechList()方法来判断NFC标签所支持的的技术,并且用android.nfc.tech提供的一个类来创建对应的TagTechnology对象。
表1.NFC标签所支持的技术
类 |
介绍 |
TagTechnology |
所有的NFC标签技术类必须实现的接口。 |
NfcA |
提供对NFC-A(ISO 14443-3A)属性和I/O操作的访问。 |
NfcB |
提供对NFC-B(ISO 14443-3B)属性和I/O操作的访问。 |
NfcF |
提供对NFC-F(ISO 6319-4)属性和I/O操作的访问。 |
NfcV |
提供对NFC-V(ISO 15693)属性和I/O操作的访问。 |
IsoDep |
提供对NFC-A(ISO 14443-4)属性和I/O操作的访问。 |
Ndef |
提供对NDEF格式的NFC标签上的NDEF数据和操作的访问。 |
NdefFormatable |
提供了对可以被NDEF格式化的NFC标签的格式化操作。 |
下面的标签技术在Android的设备上不是必须被支持。
表2.可选的NFC标签所支持的技术
类 |
介绍 |
MifareClassic |
如果Android设备支持MIFARE,那么它提供了对经典的MIFARE类型标签属性和I/O操作的访问。 |
MifareUltralight |
如果Android设备支持MIFARE,那么它提供了对超薄的MIFARE类型标签属性和I/O操作的访问。 |
2.1.1 NFC标签和ACTION_TECH_DISCOVERED类型的Intent协同工作
当设备扫描到带有NDEF数据的NFC标签,但却不能映射到MIME或URI时,NFC标签调度系统就尝试使用ACTION_TECH_DISCOVERED类型的Intent来启动一个Activity。在被扫描到的NFC标签上没有NDEF数据时,也会使用ACTION_TECH_DISCOVERED类型的Intent。有了这种回退机制,如果调度系统不能够帮你解析数据,那么你就可以直接使用NFC标签上数据来工作。基本步骤如下:
1. 给你希望处理的NFC标签指定ACTION_TECH_DISCOVERED类型的Intent过滤器。更多信息请看“NFC的Intent过滤”。通常,在NDEF消息不能被映射到MIME类型或URI时,或者被扫描到的NFC标签不包含NDEF数据时,NFC标签调度系统会尝试启动一个ACTION_TECH_DISCOVERED类型的Intent。更多信息,请看“NFC标签调度系统”。
2. 应用程序接收到Intent对象时,从该Intent对象中获取Tag对象:
Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
3. 通过调用android.nfc.tech包中对应类的一个get工厂方法,来获取一个TagTechnology对象实例。在调用get工厂方法之前,通过调用getTechList()方法来枚举NFC标签所支持的技术。例如,用下列方法从Tag对象中获取MifareUltralight对象实例:
MifareUltralight.get(intent.getParcelableExtra(NfcAdapter.EXTRA_TAG));
2.1.2 读写NFC标签
读写NFC标签,要涉及到从Intent对象中获取标签,并要打开与标签的通信。要读写NFC标签数据,你必须要定义自己的协议栈。但是,要记住在直接使用NFC标签工作时,你依然能够读写NDEF数据。这是你想要如何构建的事情。下例演示了如何使用MIFARE超薄标签来工作:
package com.example.android.nfc;
import android.nfc.Tag;
import android.nfc.tech.MifareUltralight;
import android.util.Log;
import java.io.IOException;
import java.nio.charset.Charset;
public class MifareUltralightTagTester{
private static final
String TAG =MifareUltralightTagTester.class.getSimpleName();
public void
writeTag(Tag tag,String tagText){
MifareUltralight
ultralight =MifareUltralight.get(tag);
try{
ultralight.connect();
ultralight.writePage(4,"abcd".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(5,"efgh".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(6,"ijkl".getBytes(Charset.forName("US-ASCII")));
ultralight.writePage(7,"mnop".getBytes(Charset.forName("US-ASCII")));
}catch(IOException
e){
Log.e(TAG,"IOException
while closing MifareUltralight...", e);
}finally{
try{
ultralight.close();
}catch(IOException
e){
Log.e(TAG,"IOException
while closing MifareUltralight...", e);
}
}
}
public String
readTag(Tag tag){
MifareUltralight
mifare =MifareUltralight.get(tag);
try{
mifare.connect();
byte[]
payload = mifare.readPages(4);
returnnewString(payload,Charset.forName("US-ASCII"));
}catch(IOException
e){
Log.e(TAG,"IOException
while writing MifareUltralight message...", e);
}finally{
if(mifare
!=null){
try{
mifare.close();
}catch(IOException
e){
Log.e(TAG,"Error
closing tag...", e);
}
}
}
return
null;
}
}
2.2使用前台调度系统
前台调度系统允许一个Activity拦截Intent对象,并且声明该Activity的优先级要比其他的处理相同Intent对象的Activity高。使用这个系统涉及到为Android系统构建一些数据结构,以便能够把相应的Intent对象发送给你的应用程序,以下是启用前台调度系统的步骤:
1.在你的Activity的onCreate()方法中添加下列代码:
A. 创建一个PendingIntent对象,以便Android系统能够在扫描到NFC标签时,用它来封装NFC标签的详细信息。
PendingIntent pendingIntent
=PendingIntent.getActivity(
this,0,newIntent(this,
getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),0);
B. 声明你想要截获处理的Intent对象的Intent过滤器。前台调度系统会在设备扫描到NFC标签时,用声明的Intent过滤器来检查接收到的Intent对象。如果匹配就会让你的应用程序来处理这个Intent对象,如果不匹配,前台调度系统会回退到Intent调度系统。如果Intent过滤器和技术过滤器的数组指定了null,那么就说明你要过滤所有的退回到TAG_DISCOVERED类型的Intent对象的标签。以下代码会用于处理所有的NDEF_DISCOVERED的MIME类型。只有在需要的时候才做这种处理:
IntentFilter
ndef =newIntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
try{
ndef.addDataType("*/*");
/*
Handles all MIME based dispatches.You should specify only the ones that you
need. */
}catch(MalformedMimeTypeException
e){
Throw
new RuntimeException("fail", e);
}
intentFiltersArray
=newIntentFilter[]{ndef,};
C. 建立一个应用程序希望处理的NFC标签技术的数组。调用Object.class.getName()方法来获取你想要支持的技术的类:
techListsArray =
new String[][] { new String[] {NfcF.class.getName() } };
2.重写下列Activity生命周期的回调方法,并且添加逻辑在Activity挂起(onPause())和获得焦点(onResume())时,来启用和禁用前台调度。enableForegroundDispatch()方法必须在主线程中被调用,并且只有在该Activity在前台的时候(要保证在onResume()方法中调用这个方法)。你还需要实现onNewIntent回调方法来处理扫描到的NFC标签的数据:
public void
onPause(){
super.onPause();
mAdapter.disableForegroundDispatch(this);
}
public void
onResume(){
super.onResume();
mAdapter.enableForegroundDispatch(this, pendingIntent,
intentFiltersArray, techListsArray);
}
public void
onNewIntent(Intent intent){
Tag tagFromIntent =
intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
//do something with tagFromIntent
}
完整的示例请看API
Demo中的ForegroundDispatch
Android_NFC_开发介绍的更多相关文章
- 【转载】Ssh整合开发介绍和简单的登入案例实现
Ssh整合开发介绍和简单的登入案例实现 Ssh整合开发介绍和简单的登入案例实现 一 介绍: Ssh是strtus2-2.3.1.2+ spring-2.5.6+hibernate-3.6.8整合的开 ...
- OC多文件开发介绍
OC多文件开发介绍: 1.为什么要使用多文件? 在工作中,通常把不同的类放到不同的文件中,每个类的声明和实现分开,声明写在.h头文件中,实现写在相应的.m文件中去,类名是什么,文件名的前缀就是什么.假 ...
- Java Web开发介绍
转自:http://www.cnblogs.com/pythontesting/p/4963021.html Java Web开发介绍 简介 Java很好地支持web开发,在桌面上Eclipse RC ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(三)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(三) Lucene有表达式就有运算符,而运算符使用起来确实很方便,但另外一个问题来了. 代码 4.3.4.1 Analyzer anal ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(二)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(二) 4.3 表达式用户搜索,只会输入一个或几个词,也可能是一句话.输入的语句是如何变成搜索条件的上一篇已经略有提及. 4.3.1 观察 ...
- Lucene.Net 2.3.1开发介绍 —— 四、搜索(一)
原文:Lucene.Net 2.3.1开发介绍 -- 四.搜索(一) 既然是内容筛选,或者说是搜索引擎,有索引,必然要有搜索.搜索虽然与索引有关,那也只是与索引后的文件有关,和索引的程序是无关的,因此 ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(七)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(七) 5.IndexWriter 索引这部分最后讲的是IndexWriter.如果说前面提到的都是数据的结构,那么IndexWriter ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(六)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(六) 2.2 Field的Boost 如果说Document的Boost是一条线,那么Field的Boost则是一个点.怎么理解这个点呢 ...
- Lucene.Net 2.3.1开发介绍 —— 三、索引(五)
原文:Lucene.Net 2.3.1开发介绍 -- 三.索引(五) 话接上篇,继续来说权重对排序的影响.从上面的4个测试,只能说是有个直观的理解了.“哦,是!调整权重是能影响排序了,但是好像没办法来 ...
随机推荐
- [转]浅谈C/C++内存泄露及其检测工具
转自:http://www.cnblogs.com/taoxu0903/archive/2007/10/27/939261.html 对于一个c/c++程序员来说,内存泄漏是一个常见的也是令人头疼的问 ...
- Monkey学习笔记<四>:Monkey服务器命令
#使用如下命令将本地pc和手机连接起来 adb shell monkey --port 1080 adb forward tcp 1080:tcp 1080 telnet localhost 1080 ...
- LeetCode_Interleaving String
Given s1, s2, s3, find whether s3 is formed by the interleaving of s1 and s2. For example, Given: s1 ...
- C# System.AppDomain类
进程是存在独立的内存和资源的,但是AppDomain仅仅是逻辑上的一种抽象.一个process可以存在多个AppDomain.各个AppDomain之间的数据时相互独立的.一个线程可以穿梭多个AppD ...
- ArcGIS 栅格数据已加载后的获取
原文 http://www.cnblogs.com/zoe-j/archive/2012/02/16/2354037.html 简单记一下,最近开始做Arcgis engine的开发, 已经通过了to ...
- 一些.Net面试题 (BS 方向)
http://www.cnblogs.com/PurpleTide/archive/2012/03/10/2389496.html 解决方案和思路类: 设计和策略: 1.有一个网站的中购买功能, 假设 ...
- 【Python脚本】Python创建删除文件-----------我的第一个Python脚本
Python相对C++和Java来说,是解释性语言,非常适合来编写脚本. 很久之前就开始学习Python的语法了,今天写了第一个Python的脚本,来简化我的一些日常工作. 我平时学习的时候喜欢新建一 ...
- Python 列表生成式、生成器、迭代器
列表生成式 列表生成式即List Comprehensions,是Python内置的非常简单却强大的可以用来创建list的生成式. 如果要生成[1x1, 2x2, 3x3, ..., 10x10]怎么 ...
- js中的注意事项(持续整理)
1.兼容性 <div class="toutiao_r fl_r" id ="toutiao_r"></div> 这个div中有两个样式 ...
- Bridging signals(二分 二分+stl dp)
欢迎参加——每周六晚的BestCoder(有米!) Bridging signals Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 6 ...