NFC是Near Field Communication的缩写,也就是近场通信,是一种短距离数据传输技术,该功能相对于传统的蓝牙以及红外等数据传输功能各有利弊,是目前主流的近距离通信技术之一。NFC 提供了一种简单、触控式的解决方案,可以让手机用户简单直观地交换信息、访问内容与服务。
1、配置nfc的使用权限:
//设置MainActivity的启动方式
android:launchMode="SingleTop"
2、Nfc有三层的过滤机制:
1、ACTION_NDEF_DISCOVERED
2、ACTION_TECH_DISCOVERED
3、ACTION_TAG_DISCOVERED
Android按顺序匹配三层过滤机制的流程如下:
声明过滤机制:
使用TECH_DISCOVERED的过滤规则需先在/res/xml下面创建一个过滤规则文件,这个里面定义的是nfc实现的各种标准,每一个nfc卡都会符合多个不同的标准。
以下是在nfc_tech.xml定义的多种检测标准:
android.nfc.tech.MifareClassic
android.nfc.tech.MifareUltralight
android.nfc.tech.IsoDep
android.nfc.tech.NfcA
android.nfc.tech.Ndef
android.nfc.tech.NfcB
//可以在一个 组中定义多个标准,如最后一组
以上是使用nfc前的一些配置信息。
3、获取NfcAdapeter适配器
//获取Nfc适配器,判断设备是否支持nfc
mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
if(mNfcAdapter==null){
Toast.makeText(this, "该设备比支持nfc", Toast.LENGTH_SHORT).show();
return;
}
if(!mNfcAdapter.isEnabled()){
Toast.makeText(this, "先打开nfc功能", Toast.LENGTH_SHORT).show();
return;
}
4、因为设置的启动方式是”SingleTop”,在手机检测到有nfc标签时,系统会给当前的activity发送一个intent,就会调用onNewIntent(Intent intent)的方法,所以重写该方法,在该方法中对nfc标签进行解析。
protected void onNewIntent(Intent intent) {
// TODO 自动生成的方法存根
super.onNewIntent(intent);
//判断发来的intent是否我们设置的过滤机制,不是则退出不做处理
if (!NfcAdapter.ACTION_TECH_DISCOVERED.equals(intent.getAction())) {
return;
}
//获取到Tag标签对象
tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
if(tag!=null){
//Tag标签中的Ndef内容
ndef = Ndef.get(tag);
}else{
return;
}
//获取此标签中支持的技术
String[] techList=tag.getTechList();
for (String tech:techList){
Log.d("TECH",tech);
}
}
同时需要在onResume()和onPause()设置对nfc标签的连接的监听
PendingIntent pend = PendingIntent.getActivity(this, 0, new Intent(this, getClass())
.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
//开始监听nfc功能
protected void onResume() {
// TODO 自动生成的方法存根
super.onResume();
if (mNfcAdapter != null) {
//开始监听NFC设备是否连接,如果连接就发pend意图,设置当前程序为优先处理nfc的程序
mNfcAdapter.enableForegroundDispatch(this, pend, null, null);
}
}
//停止监听nfc
protected void onPause() {
// TODO 自动生成的方法存根
super.onPause();
if (mNfcAdapter != null) {
mNfcAdapter.disableForegroundDispatch(this);
}
}
5、解析卡片的信息
//获取卡片的ID
tag.getId();
//可将以下方法将ID转换成16进制码
private String bytesToHexString(byte[] bArray) {
StringBuffer strBuf = new StringBuffer(bArray.length);
String strTemp;
for(int i = 0; i < bArray.length; i++) {
strTemp = Integer.toHexString(0xFF & bArray[i]);
if(strTemp.length() < 2) {
strBuf.append(0);
}
strBuf.append(strTemp.toUpperCase());
}
return strBuf.toString();
}
//获取卡片类型
String[] techList = tag.getTechList();
//NFC卡的类型: Mifare Classic/UltraLight Info/IsoDep
for (int i = 0; i < techList.length; i++) {
//根据不同的卡片类型获取各自的Tag
if (techList[i].equals(NfcA.class.getName())) {
NfcA nfc = NfcA.get(tag);
try {
if ("".equals(type))
Log.d("Type",NfcA.class.getName());
} catch (Exception e) {
e.printStackTrace();
}
} else if (techList[i].equals(MifareUltralight.class.getName())) {
MifareUltralight mifareUlTag = MifareUltralight
.get(tag);
switch (mifareUlTag.getType()) {
case MifareUltralight.TYPE_ULTRALIGHT:
Log.d("Type","ULTRALIGHT");
break;
case MifareUltralight.TYPE_ULTRALIGHT_C:
Log.d("Type","ULTRALIGHT_C");
break;
}
}else if(techList[i].equals(IsoDep.class.getName())){
Log.d("Type",IsoDep.class.getName());
}
}
6、读取卡片的内容:卡片的内容主要是这三种类型:1、文本类型,2、应用程序类型,3、Uri链接类型
应用程序跟Uri链接类型在andriod检测到nfc标签时可以快速启动程序或打开网页。
private void readIntent(){
if (tag == null) {
return;
}
if(ndef==null){
return;
}
try {
//打开连接
ndef.connect();
//读取标签中的ndef内容
NdefMessage message = ndef.getNdefMessage();
//获取标签中的内容长度
int length = message.getByteArrayLength();
if(message==null){
Toast.makeText(this, "Null Message", Toast.LENGTH_SHORT).show();
ndef.close();
return;
}
//一个NdefMessage是有一条或多条的NdefRecord组成。
NdefRecord[] recoder = message.getRecords();
for(NdefRecord r:recoder){
//使用该方法获取该NdefRecord中的实际内容
byte[] b = r.getPayload();
//如果直接使用r.toString()获取到的内容还包括了ndef格式中的一些前缀数据
}
//将消息转换成字节数组
//关闭连接
ndef.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
catch (FormatException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
7、往标签中写入数据,上一节说到nfc的内容有主要是三种类型,不同的数据类型对应着不同的写入方式
//文本类型
NdefRecord recordText=new NdefRecord(NdefRecord.TNF_WELL_KNOWN,NdefRecord.RTD_TEXT,
new byte[]{0},"Hello World!".getBytes(Charset.forName("utf-8")));
//应用程序类型
NdefRecord recordPack=NdefRecord.createApplicationRecord(packageName);
//packageName是程序包名,可通过下面的方法获取系统中所有程序的包名
PackageManager manager = getPackageManager();
List packageInfos = manager.getInstalledPackages(PackageManager.GET_ACTIVITIES);
String[] mPackage = new String[packageInfos.size()];;
//遍历
int i=0;
for (PackageInfo pi : packageInfos) {
//获取软件名和包名
mPackage[i] = pi.applicationInfo.loadLabel(manager)+"\n"+pi.packageName;
i++;
}
//Uri类型
NdefRecord recordUri = NdefRecord.createUri(Uri.parse("www.baidu.com"));
//创建NdefMessage,并将以上的NdefRecord添加进来,写入的NdefRecord可以是任意一条,也可以是多条
NdefMessage message = new NdefMessagge(new NdefRecord[]{recordText,recordPack,recordUri);
//将NdefMessage写进标签中
//获得写入大小
int size = ndefMessage.toByteArray().length;
//判断是否是NDEF标签
try {
if(ndef != null) {
//说明是NDEF标签,开始连接
ndef.connect();
//判断是否可写
if(!ndef.isWritable()){
Toast.makeText(this, "当前设备不支持写入",Toast.LENGTH_LONG).show();
ndef.close();
return;
}
//获取标签的容量大小,判断是否足够写入
if(ndef.getMaxSize() < size){
Toast.makeText(this, "容量不足",Toast.LENGTH_LONG).show();
ndef.close();
return;
}
//写入
try {
//使用该方法将ndefmessage写进标签
ndef.writeNdefMessage(ndefMessage);
Toast.makeText(this, "写入成功",Toast.LENGTH_LONG).show();
ndef.close();
} catch (FormatException e) {
e.printStackTrace();
}
}
} catch (IOException e) {
e.printStackTrace();
}
以上就是在安卓系统上的nfc功能的使用,可以通过设置标签的内容实现某种功能,如将某一应用程序的包名写进标签,在标签靠近安卓板后,系统会自动打开该应用程序。