nfc
NDEF:
NFC Data Exchange Format:NFC数据交换格式,NFC组织约定的NFC tag中的数据格式。他是轻量级的紧凑的二进制格式,可带有URL、vCard和NFC定义的各种数据类型
android nfc中Ndef格式的读写
检测到标签后在Activity中的处理流程
1.在onCreate()中获取NFCAdapter对象
NfcAdapter nfcAdapter=NfcAdapter.getDefaultAdapter(this);
2.在onNewIntent()中获取Tag对象或是NdefMessage信息
获取Tag对象:
Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
获取DeafMessage信息:
Parcelabel[] rawMsgs=getIntent().getParcelabelArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
3.也可以通过Tag创建Ndef对象等,以实现标签的属性和I/O操作
Ndef ndef=Ndef.get(tag);
NDEF格式标签的读取流程
1.在onCreate()中获取NFCAdapter对象;
2.在onNewIntent()中判断是否为NDEF格式标签(ACTION_NDEF_DISCOVERED),若是则获取NdefMessage信息;(需要强制转换成NdefMessage对象)
Parcelabel[] rawMsgs=getIntent().getParcelabelArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES)
3.对NdefMessage对象进行解析,获取相关的文本信息或Uri等。
NDEF格式标签的写入流程
1.在onCreate()中获取NFCAdapter对象
2.在onNewIntent()中获取tag对象
Tag tag =intent.getparcelabelExtra(NfcAdapter.EXTRA_TAG);
3.通过Tag创建Ndef对象
Ndef ndef=Ndef.get(tag);
4.将文本数据封装成NdefMessage
5.判断是否为NDEF格式标签
若是NDEF格式:
(1)允许进行标签操作:ndef.connect();
(2)调用ndef.writeNdefMessage(NdefMessage)方法写入。
若非NDEF格式:
(1)NdefFromatable format=NdefFromatable.get();
(2)允许进行标签操作:format.connect();
(3)调用ndef.writeNdefMessage(NdefMessage)方法写入。
NFC的基本类
Android平台提供了两个android.nfc和android.nfc.tech包,里面有API来实现NFC标签的操作。
android.nfc包主要有4个类:
NFCManager类:可以用来滚利Android设备中指出的所有NFC Adapter,但由于大部分Android设备只支持一个NFC Adapter,可以直接使用getDefaultAdapter方法来获得系统支持的Adapter
NFCAdapter类:本设备的NFC adapter,可以定义Intent来请求江系统检测到tags的提醒发送到你的Activity,并提供发送方去注册前台tag提醒发布和前台NDEF推送
NdefMessage类:NDEF是NFC论坛定义的数据结构,用来有效的存数据到标签中,如文本,URL和其他MIME类型一个NdefMessage扮演一个容器,这个容器存放发送和读到的数据,一个NdefMessage对象包含0或多个NdefRecord,每个NDEF record有一个类型,比如文本,URL等,在NDEFMessage里的第一个NFCRecord的类型用来发送tag到一个android设备的activity
Tag类:表示一个被动的NFC目标,比如tag,card等,可提供对标签的各种操作方法。
NFC前台调度
将处理NFC标签的权利交给某个窗口(优先级最高)
1.在onCreate()中获得NFCAdapter对象
2.创建与该Activity关联的PendingIntent
3.指定一个用于处理NFC标签的窗口,通常会在onResume()方法中采用nfcAdapter.enableForegroundDispatch()来实现
4.禁止窗口处理NFC标签,爱用nfcAdapter.disableForegroundDispatch()来实现
点对点的数据交换
前台推送技术支持简单点对点的数据交换,可以用enableForegroundNdefPush(Activity,NdefMessage)方法来打开此功能,用这个功能
- 推送数据的Activity必须是前台Activity
- 必须将要发送的数据封装到NdefMessage对象里
- 棘手推送数据的设备必须支持com.android.npp NDEF推送协议
要打开前台推送:
- 创建一个你要推送给其他NFC设备的包含NdefRecords的NdefMessage
- 在Activity里实现onResume()和onPause()的回调来正确处理前台推送的生命周期,必须在Activity位于前台并在主线程里调用enableForegroundNdefPush(Activity,NdefMessage)(可以在onResume()里调用来保证这点)
在Activity中获取TAG ID
Intent intent =this.getIntent();//在activity中获取Intent对象 // 确保你的Activity是被扫描到的NFC的Intent对象启动的 String intentActionStr = intent.getAction();// 获取到本次启动的action if(NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intentActionStr)// NDEF类型 ||NfcAdapter.ACTION_TECH_DISCOVERED.equals(intentActionStr)// 其他类型 ||NfcAdapter.ACTION_TAG_DISCOVERED.equals(intentActionStr)) {// 未知类型 //在intent中读取Tag id byte[] bytesId = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID) /* //Android NFC API 10 以后对Tag 对象加入方法getID来获取id,所以还可以
//在intent中通过附加信息读取Tag标签对象,即获取扫描到的标签
//然后通过Tag对象读取id Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
// 获取id数组 byte[] bytesId = tag.getId(); */
// 字符串id String strId = new String(dataId); }else{ //activity不是NFC intent启动的后者收到的intent不是NFC扫描到Tag后传入的 }
使用主要到的api:
intent.getByteArrayExtra(NfcAdapter.EXTRA_ID)// 在intent中读取Tag Id 数组
或
Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);//在intent中读取Tag
tag.getId();// 获取Tag Id数组
当NFC检测到NFC标签(Tag)时,通过使用Intent启动适应的Activity。在Acitivity中可以从这个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 标签(Tag)
NFC标签的类型有很少种,需要指出你的activity处理的nfc标签类型,配置的方法有两种:
1. Activity不在前台
当NFC标签被扫描到系统会依照顺序NDEF_DISCOVERED, TECH_DISCOVERED,TAG_DISCOVERED匹配标签类型,直到找到适合的Acitivty处理或者没有处理为止,如果有传递带有标签信息的Intent到处理的Activity(NFC标签调度系统)
1) NDEF_DISCOVERED 在AndroidManifest.xml对Activity配置如下:
<intent-filter>
<action android:name="android.nfc.action.NDEF_DISCOVERED"/> </intent-filter>
2) TAG_DISCOVERED在AndroidManifest.xml对Activity配置如下:
<intent-filter>
<action android:name="android.nfc.action.TAG_DISCOVERED"/>
</intent-filter>
2. Activity在前台
当Activity在前台时,可直接拦截一个tag Intent 获得最高优先级的处理.( 前台调度系统) 示例代码:
private NfcAdapter mAdapter;//NFC适配器 private PendingIntent mPendingIntent;
private IntentFilter[] mFilters;//Intent过滤器 private String[][] mTechLists;// technologies列表 @Override public void onCreate(Bundle savedState) { super.onCreate(savedState); … //获取NFC适配器 mAdapter = NfcAdapter.getDefaultAdapter(this); mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); //intent过滤器,过滤类型为NDEF_DISCOVERED IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
mFilters = new IntentFilter[] {ndef,}; //存放支持technologies的数组 mTechLists = new String[][] { new String[] { NfcF.class.getName() } }; } @Override public void onResume() { super.onResume(); ... //打开功能,使用上面设置的值 mAdapter.enableForegroundDispatch(this, mPendingIntent, mFilters, mTechLists); } @Override public void onPause() { super.onPause(); … //关闭功能 mAdapter.disableForegroundDispatch(this); }
使用主要到的api:
NfcAdapter.getDefaultAdapter(Content content) 本地默认的NFC适配器的引用
NfcAdapter .enableForegroundDispatch(Activity, PendingIntent, IntentFilter[], String[][])
打开前台发布系统,主线程里调用并且Activity在前台
NfcAdapter.disableForegroundDispatch(Content content) 关闭前台发布系统
声明Android Manifest.xml的元素
使用NFC需要申明权限:
<uses-permission android:name="android.permission.NFC" />
如需要在应用商店过滤:
<uses-feature android:name="android.hardware.nfc" android:required="true" />
onNewIntent的应用
onCreate是用来创建一个Activity也就是创建一个窗体,但一个Activity处于任务栈的顶端,若再次调用startActivity去创建他,则不会再次创建,若你想利用已有的Activity处理别的Intent时,你就可以利用onNewIntent来处理。在onNewIntent里面就会获得新的Intent
@Override
protected void onNewIntent(Intent intent){
super.onNewIntent(intent);
}
若果IntentActivity处于任务栈的顶端,也就是说之前打开过的Activity,现在处于onPause,onStop状态的话,其他应用在发送Intent的话,执行顺序为:
onNewIntent
onRestart
onStart
onResume
1.onNewIntent(Intent intent) 是Activity类的方法.它被调用发几种情况如下:
<activity android:name=".NewIntentDemo" android:label="@string/app_name" android:launchMode="singleTask">
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
android:launchMode="singleTask" 配置在 Mainifest 中,它保证了栈中此Activity总是只有一个,无论你启动它多少次;
Activiy配置成android:launchMode="singleTask" ,在点Home键退出Activity而再次启动新的Intent进来时onNewIntent(Intent intent) 方法会被调用到;
2.利用已有的Acivity去处理别的Intent时,你就可以利用onNewIntent来处理,通常被用在有搜索请求的activity,而其该activity有好几个intent-filter,该方法被调用的前提
a、该activity设置如下属性 android:launchMode="singleTop"。
b、该activity已经处在栈的顶端,通过其他的方法又重新启动该acitvity时被调用,如搜索,这时oncreate()方法不调用。
append()往动态字符串数组中添加字符串。
context :
1、它描述的是一个应用程序环境的信息,即上下文。
2、该类是一个抽象(abstract class)类,Android提供了该抽象类的具体实现类(后面我们会讲到是ContextIml类)。
3、通过它我们可以获取应用程序的资源和类,也包括一些应用级别操作,例如:启动一个Activity,发送广播,接受Intent信息 等。。