2025-07-22 16:43:14

Android中的NFC操作

目录

1.申请权限

2.设置意图过滤器

3.判断NFC功能是否可用(NfcAdapter)

4.NFC感应(NfcAdapter)启用与禁用

5.NFC数据解码

6.案例代码一览

NFC的全称是“Near Field Communication”,意思是近场通信、与邻近的区域通信。该功能由NfcAdapter(NFC适配器)控制。

1.申请权限

2.设置意图过滤器

在清单文件(AndroidManifests)中为Activity设置意图过滤器(IntentFilter);在程序检测到NFC操作时将跳转至该界面。

本部分操作用于从外部直接打开指定Activity。

android.nfc.action.NDEF_DISCOVERED:指定了当应用程序收到包含NDEF(NFC Data Exchange Format)数据的NFC标签时应该触发的动作。NDEF是一种用于在NFC设备之间交换信息的标准格式。android.nfc.action.TAG_DISCOVERED:定义了当检测到NFC标签时应该触发的动作。这个动作用于处理未包含NDEF数据的NFC标签。android.nfc.action.TECH_DISCOVERED:指定了当检测到支持的NFC技术时应该触发的动作。这允许应用程序处理特定的NFC技术。其中具体的NFC技术由meta-data标签指定源文件。

android:name=".NFCActivity"

android:exported="true" >

android:resource="@xml/nfc_tech_filter"/>

android.nfc.tech.NfcA

android.nfc.tech.NfcB

android.nfc.tech.NfcF

android.nfc.tech.NfcV

android.nfc.tech.IsoDep

android.nfc.tech.Ndef

android.nfc.tech.NdefFormatable

android.nfc.tech.MifareClassic

android.nfc.tech.MifareUltralight

3.判断NFC功能是否可用(NfcAdapter)

可使用NfcAdapter(NFC适配器)进行判断,未开启时跳转至NFC设置界面;NfcAdapter常用方法如下:

getDefaultAdapter(静态方法):获取NFC适配器对象;设备无NFC功能时返回null。isEnabled:判断NFC功能是否可用(即是否开启)。enableForegroundDispatch:用于启用NFC感应;第一个参数为上下文环境,第三参数为用于触发的待定意图,第三个参数为过滤器(会触发待定意图的NFC事件类型),第四个参数为指定NFC技术类型的二维数组。disableForegroundDispatch:用于禁用NFC感应。

//获取NFC适配器

NfcAdapter nfcAdapter=NfcAdapter.getDefaultAdapter(MainActivity.this);

//判断设备是否有NFC功能

if(nfcAdapter==null){

textView.setText("设备无NFC功能");

}

//判断设备是否开启NFC功能

else if (!nfcAdapter.isEnabled()) {

textView.setText("设备未开启NFC功能");

//跳转至设置NFC界面

Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS);

startActivity(intent);

}

else {

textView.setText("设备已开启NFC功能");

}

4.NFC感应(NfcAdapter)启用与禁用

建议在页面暂停时禁用NFC感应,在页面运行时启用NFC感应。

用于触发的待定意图(PendingIntent)为读取NFC信息通常为跳转至当前界面(即会触发onNewIntent方法);请注意需将Activity设置为仅有一个,可在清单文件将launchMode设置为singleTop,或为Intent使用.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP)。

//准备NFC感应启动参数

//用于触发的待定意图

Intent intent=new Intent(MainActivity.this,MainActivity.class);

//intent=intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

PendingIntent pendingIntent=PendingIntent.getActivity(MainActivity.this,12345,intent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);

//过滤器数组(会触发待定意图的NFC事件类型)

IntentFilter[] intentFilter=new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)};

//指定NFC技术类型的二维数组

String[][] techList=new String[][]{new String[]{NfcA.class.getName()},{IsoDep.class.getName()}};

protected void onResume() {

super.onResume();

if(nfcAdapter!=null&&nfcAdapter.isEnabled()){

//启用NFC感应

nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,intentFilter,techList);

}

}

protected void onPause() {

super.onPause();

if(nfcAdapter!=null&&nfcAdapter.isEnabled()){

//禁用NFC感应

nfcAdapter.disableForegroundDispatch(MainActivity.this);

}

}

5.NFC数据解码

用于触发的待定意图(PendingIntent)为读取NFC信息通常为跳转至当前界面(即会触发onNewIntent方法);请注意需将Activity设置为仅有一个。

可以通过重写onNewIntent方法,获取NFC数据并解码:

使用Intent获取action并判断是否为NFC操作触发;action返回结果可能为null;可无此步使用Intent获取其中包含的Tag型数据;可使用Tag数据获取卡序列号( getId()方法 );tag返回结果可能为null使用Tag数据获取MifareClassic对象MifareClassic对象连接到NFC卡根据MifareClassic对象获取卡中数据关闭MifareClassic与卡的连接,无论是否出现异常

MifareClassic类常用方法:

get(静态方法):从Tag对象中获取卡片对象的信息。connet:连接卡片数据。close:释放卡片数据。getType:获取卡片类型。TYPE_CLASSIC表示传统型,TYPE_PLUS表示加强型,TYPE_PRO表示专业型。getSectorCount:获取扇形区域。getBlockCount:获取分块个数。getSize:获取存储大小,单位字节。

protected void onNewIntent(Intent intent) {

super.onNewIntent(intent);

//读取NFC信息

Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

if(tag!=null){

//获取序列号

byte[] id_bytes=tag.getId();

String id="";

for(int i=0;i

id=id+id_bytes[i];

}

//创建MifareClassic对象

MifareClassic classic=MifareClassic.get(tag);

try {

//连接卡片

classic.connect();

//获取类型

int typeI=classic.getType();

String type=null;

if(typeI==MifareClassic.TYPE_CLASSIC){

type="传统类型";

}

else if(typeI==MifareClassic.TYPE_PLUS) {

type="增强类型";

}

else if (typeI==MifareClassic.TYPE_PRO) {

type="专业类型";

}

else {

type="未知类型";

}

//获取其他数据

int i1=classic.getSectorCount();//扇形区域

int i2=classic.getBlockCount();//分块个数

int i3=classic.getSize();//内存大小

} catch (IOException e) {

throw new RuntimeException(e);

}finally {

try {

//无论是否发生异常都要释放卡片数据(关闭连接)

classic.close();

} catch (IOException e) {

throw new RuntimeException(e);

}

}

}

}

6.案例代码一览

以下为MainActivity(界面只有一个TextView)的全部代码,请在清单文件声明(静态申请)NFC权限后使用。

public class MainActivity extends AppCompatActivity {

private NfcAdapter nfcAdapter=null;

private PendingIntent pendingIntent=null;

private IntentFilter[] intentFilter=null;

private String[][] techList=null;

private TextView textView=null;

@SuppressLint("MissingInflatedId")

protected void onCreate(Bundle savedInstanceState) {

super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);

//获取控件

textView=findViewById(R.id.textView);

//获取NFC适配器

nfcAdapter=NfcAdapter.getDefaultAdapter(MainActivity.this);

//判断设备是否有NFC功能

if(nfcAdapter==null){

textView.setText("设备无NFC功能");

}

//判断设备是否开启NFC功能

else if (!nfcAdapter.isEnabled()) {

textView.setText("设备未开启NFC功能");

//跳转至NFC设置界面

Intent intent=new Intent(Settings.ACTION_NFC_SETTINGS);

startActivity(intent);

}

else {

textView.setText("设备已开启NFC功能");

}

//准备NFC感应启动参数

//用于触发的待定意图

Intent intent=new Intent(MainActivity.this,MainActivity.class);

//intent=intent.addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP);

pendingIntent=PendingIntent.getActivity(MainActivity.this,12345,intent,PendingIntent.FLAG_UPDATE_CURRENT|PendingIntent.FLAG_IMMUTABLE);

//过滤器(会触发待定意图的NFC事件类型)

intentFilter=new IntentFilter[]{new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)};

//指定NFC技术类型

techList=new String[][]{new String[]{NfcA.class.getName()},{IsoDep.class.getName()}};

}

protected void onResume() {

super.onResume();

if(nfcAdapter!=null&&nfcAdapter.isEnabled()){

//启用NFC感应

nfcAdapter.enableForegroundDispatch(MainActivity.this,pendingIntent,intentFilter,techList);

}

}

protected void onPause() {

super.onPause();

if(nfcAdapter!=null&&nfcAdapter.isEnabled()){

//禁用NFC感应

nfcAdapter.disableForegroundDispatch(MainActivity.this);

}

}

//该界面触发NFC自动调用该方法

protected void onNewIntent(Intent intent) {

super.onNewIntent(intent);

String outString="NFC卡无数据";

//读取NFC信息

Tag tag=intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);

if(tag!=null){

//获取序列号

byte[] id_bytes=tag.getId();

String id="";

for(int i=0;i

id=id+id_bytes[i];

}

outString="序列号为:"+id+"\n";

//创建MifareClassic对象

MifareClassic classic=MifareClassic.get(tag);

try {

//连接卡片

classic.connect();

//获取类型

int typeI=classic.getType();

String type=null;

if(typeI==MifareClassic.TYPE_CLASSIC){

type="传统类型";

}

else if(typeI==MifareClassic.TYPE_PLUS) {

type="增强类型";

}

else if (typeI==MifareClassic.TYPE_PRO) {

type="专业类型";

}

else {

type="未知类型";

}

//获取其他数据

int i1=classic.getSectorCount();//扇形区域

int i2=classic.getBlockCount();//分块个数

int i3=classic.getSize();//内存大小

outString=outString+type+"\n"+"扇形区域:"+i1+"\n分块个数:"+i2+"\n内存大小:"+i3;

} catch (IOException e) {

throw new RuntimeException(e);

}finally {

try {

//无论是否发生异常都要关闭连接

classic.close();

} catch (IOException e) {

throw new RuntimeException(e);

}

}

}

textView.setText(outString);

if(outString.equals("NFC卡无数据")){

Handler handler=new Handler(new Handler.Callback() {

public boolean handleMessage(@NonNull Message message) {

textView.setText("设备已开启NFC功能");

return true;

}

});

new Thread(new Runnable() {

public void run() {

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

throw new RuntimeException(e);

}

handler.sendEmptyMessage(123);

}

}).start();

}

}

}

tag:NFC,nfc,芯片,磁卡,近距通信