Android中的NFC操作

本文详细介绍了如何在Android应用中使用NFC功能,包括权限申请、设置意图过滤器、检测NFC功能、启用禁用NFC感应、NFC数据解码以及MifareClassic的使用。
摘要由CSDN通过智能技术生成

目录

1.申请权限

2.设置意图过滤器

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

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

5.NFC数据解码

6.案例代码一览


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

1.申请权限

<!-- NFC权限,无需动态申请 -->
<uses-permission android:name="android.permission.NFC" />

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标签指定源文件。
<!--AndroidManifests-->
<activity
    android:name=".NFCActivity"
    android:exported="true" >

    <intent-filter>
        <action android:name="android.nfc.action.NDEF_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>

    <intent-filter>
        <action android:name="android.nfc.action.TAG_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>

    <intent-filter>
        <action android:name="android.nfc.action.TECH_DISCOVERED"/>
        <category android:name="android.intent.category.DEFAULT"/>
    </intent-filter>

    <!--定义了android.nfc.action.TECH_DISCOVERED的具体NFC技术-->
    <!--资源文件位于xml/nfc_tech_filter.xml中-->
    <meta-data android:name="android.nfc.action.TECH_DISCOVERED"
        android:resource="@xml/nfc_tech_filter"/>

</activity>
<!--xml/nfc_tech_filter.xml文件内容如下-->
<!--该文件为Android所有能支持的NFC类型-->
<resource>
    <tech-list>
        <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.IsoDep</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>
</resource>

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数据并解码:

  1. 使用Intent获取action并判断是否为NFC操作触发;action返回结果可能为null;可无此步
  2. 使用Intent获取其中包含的Tag型数据;可使用Tag数据获取卡序列号( getId()方法 )tag返回结果可能为null
  3. 使用Tag数据获取MifareClassic对象
  4. MifareClassic对象连接到NFC卡
  5. 根据MifareClassic对象获取卡中数据
  6. 关闭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_bytes.length;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_bytes.length;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,芯片,磁卡,近距通信

  • 55
    点赞
  • 24
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
### 回答1: Android调用NFC读取NFC卡片的过程如下:首先,需要确认设备的硬件支持NFC功能,并且设备的操作系统版本必须是Android 4.0或更高版本。然后,在Android应用程序,需要在AndroidManifest.xml文件添加必要的权限和NFC相关的配置。 接下来,需要在应用程序注册一个NFC适配器对象,以便与设备的NFC芯片进行通信。然后,可以通过检测NFC设备是否处于范围内来启动应用程序的特定操作,例如读取卡片的数据。 读取NFC卡片的过程包括以下步骤:首先,需要创建一个PendingIntent对象,以便在检测到NFC设备时接收通知。然后,使用NFC适配器对象调用enableForegroundDispatch()方法,将PendingIntent对象传递给它。这将使应用程序在检测到NFC设备时接收到通知,并初始化NFC操作。 在读取NFC卡片之前,需要创建一个IntentFilter对象,以过滤掉不相关的NFC标签。可以使用ACTION_NDEF_DISCOVERED和ACTION_TECH_DISCOVERED等值来设置过滤器。然后,将IntentFilter对象传递给NFC适配器的enableForegroundDispatch()方法。 当NFC适配器检测到NFC设备时,将调用应用程序的onNewIntent()方法。在onNewIntent()方法,可以通过调用getParcelableExtra()方法获取传递给PendingIntent对象的Intent,并从提取出NFC标签的数据。 最后,可以使用读取到的NFC标签数据进行其他的处理操作,例如解析数据、显示在应用界面上或将其发送到远程服务器等。 在读取NFC卡片的过程需要注意的是,NFC设备必须处于活动状态,并且应用程序必须拥有前台调度权限,才能成功读取NFC卡片。此外,由于不同的NFC卡片类型和厂商可能有不同的协议和数据格式,因此需要根据具体的NFC卡片来实现相应的处理逻辑。 ### 回答2: Android调用NFC读取NFC卡片的过程如下: 首先,需要在AndroidManifest.xml文件添加必要的权限和特性声明,以确保应用能够访问NFC功能。例如,需要添加以下权限声明: ``` <uses-permission android:name="android.permission.NFC" /> ``` 在应用的Activity,需要注册一个NFC监听器,以接收NFC设备的读取事件。可以通过以下方式实现: ``` private NfcAdapter mNfcAdapter; ... @Override protected void onCreate(Bundle savedInstanceState) { ... mNfcAdapter = NfcAdapter.getDefaultAdapter(this); ... } ... @Override public void onResume() { super.onResume(); if (mNfcAdapter != null) { Intent intent = new Intent(this, this.getClass()).addFlags(Intent.FLAG_RECEIVER_REPLACE_PENDING); PendingIntent pendingIntent = PendingIntent.getActivity(this, 0, intent, 0); IntentFilter[] intentFilters = new IntentFilter[]{}; mNfcAdapter.enableForegroundDispatch(this, pendingIntent, intentFilters, null); } } ... @Override public void onPause() { super.onPause(); if (mNfcAdapter != null) { mNfcAdapter.disableForegroundDispatch(this); } } ... @Override public void onNewIntent(Intent intent) { super.onNewIntent(intent); if (intent.hasExtra(NfcAdapter.EXTRA_TAG)) { Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); // 在此处理读取到的NFC卡片数据 } } ``` 以上代码,`mNfcAdapter`是NFC适配器实例,`onResume()`方法用于在应用进入前台时启用前台调度,以便接收NFC设备事件,`onPause()`方法用于在应用进入后台时禁用前台调度,`onNewIntent()`方法用于处理读取到的NFC卡片数据。 在`onNewIntent()`方法,可以通过`intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)`来获取到读取到的NFC标签,并进行相应的操作,例如读取和写入卡片数据等。 需要注意的是,以上代码只展示了基本的NFC读取流程,具体的读取和处理操作需要根据需求进一步实现。 ### 回答3: Android调用NFC读取NFC卡片需要经过以下的步骤: 首先,确保设备支持NFC功能。大多数Android设备都已经集成了NFC芯片,但仍然需要在设备的设置确认是否启用NFC功能。 然后,在Android的Manifest文件添加必要的权限和配置。这些权限包括NFC权限,以及与NFC相关的Intent过滤器。例如,可以添加以下代码来声明NFC权限: <uses-permission android:name="android.permission.NFC"/> 同时,还需要添加一个Intent过滤器,以便应用程序能够响应NFC相关的意图。以下是示例代码: <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED"/> </intent-filter> 接下来,需要创建一个能够响应NFC意图的活动或服务。这可以通过继承Android提供的NFC活动类或服务类来实现。在这个活动或服务,可以使用NFC适配器来检测和连接到NFC标签。以下是示例代码: NfcAdapter nfcAdapter = NfcAdapter.getDefaultAdapter(this); if (nfcAdapter != null && nfcAdapter.isEnabled()) { // NFC已经启用,可以进行相关操作 } else { // 设备不支持或未启用NFC功能 } 在检测到NFC标签后,可以通过NFC适配器获取NFC标签的ID或数据。例如,可以使用以下代码获取NFC标签的ID: Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String tagId = bytesToHexString(tag.getId()); 最后,可以根据需要对NFC标签的ID或数据进行进一步的处理。例如,可以将ID与系统已知的标签ID进行比较,或者读取和写入NFC标签的数据。 总之,Android调用NFC读取NFC卡片需要确认设备支持NFC功能、添加必要的权限和配置、创建能够响应NFC意图的活动或服务、使用NFC适配器进行NFC标签的检测和连接,并对NFC标签的ID或数据进行处理。以上是一个简单的概述,更详细的实现可以参考Android开发文档关于NFC的相关内容。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

在下嗷呜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值