• Android中读取NFC标签卡中的ID


    场景

    APP中读取NFC卡中的标签ID,作为用户的唯一标识进行登录验证。

    首先需要确保手机支持NFC功能。其次具备一张NFC卡片。

    读取id就是利用的读卡器模式,当把卡片靠近手机的NFC天线的时候,NFC会识别到卡,

    然后把卡对象装到intent里面,

    并发送广播NfcAdapter.ACTION_TECH_DISCOVERED,

    应用程序接到这个广播之后,通过intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)来获取到卡对象,

    然后就可以对卡进行读写

    注:

    博客:
    https://blog.csdn.net/badao_liumang_qizhi
    关注公众号
    霸道的程序猿
    获取编程相关电子书、教程推送与免费下载。

    实现

    1、新建项目,添加权限

    打开Android Studio新建一个项目,在AndroidManifest.xml中添加权限。

        <!--    NFC所需权限-->
        <uses-permission android:name="android.permission.NFC" />
        <!-- 要求当前设备必须要有NFC芯片 -->
        <uses-feature android:name="android.hardware.nfc" android:required="true" />

    2、将要读取NFC的Activity设置为singleTop

    这里是在MainActivity中

            <activity android:name=".MainActivity" android:launchMode="singleTop">
                <intent-filter>
                    <action android:name="android.intent.action.MAIN" />
    
                    <category android:name="android.intent.category.LAUNCHER" />
                </intent-filter>
            </activity>

    Activity共有四种启动模式:

    standard

    标准模式,也是Activity的默认启动模式,允许存在多个Activity实例,

    每次启动页面时都会生成一个新的Activity实例。

    singleTop

    相比于standard,有新的页面启动请求时,当目标Activity处于当前栈顶时,

    会调用Activity的onNewIntent()方法,但不创建新实例;其他情况都和standard一致。

    其他两种不做介绍。

    NFC检测到对象时,会在系统startActivity,那么目标activity已经是启动了,

    所以我们需要在onNewIntent方法中接受tag对象,同时activity启动模式设为singleTop或singleTask也为了避免重复创建实例

    3、设计页面布局

    打开activity_main.xml,修改如下

    <?xml version="1.0" encoding="utf-8"?>
    <RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
        android:id="@+id/activity_main"
        android:layout_width="match_parent"
        android:layout_height="match_parent"
        android:background="#151414"
        >
        <LinearLayout
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal"
            android:layout_centerInParent="true"
            >
            <TextView
                android:layout_width="wrap_content"
                android:text="读取到的卡UID: "
                android:textColor="#fff"
                android:layout_height="wrap_content" />
            <TextView
                android:textColor="#fff"
                android:id="@+id/tv_uid"
                android:text="                            "
                android:layout_width="wrap_content"
                android:layout_height="wrap_content"/>
        </LinearLayout>
    </RelativeLayout>

    4、修改Activity

    在OnCreate方法中,获取NfcAdapter实例,然后获取通知,判断支持NFC并且打开后,当获取通知后会调用onNewIntent方法。

        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //获取显示文本框
            tvUid = (TextView) findViewById(R.id.tv_uid);
            //获取NfcAdapter实例
            nfcAdapter = NfcAdapter.getDefaultAdapter(this);
            //获取通知
            pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
                    getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
            //如果获取不到则不支持NFC
            if (nfcAdapter == null) {
                Toast.makeText(MainActivity.this,"设备不支持NFC",Toast.LENGTH_LONG).show();
                return;
            }
            //如果获取到的为不可用状态则未启用NFC
            if (nfcAdapter!=null&&!nfcAdapter.isEnabled()) {
                Toast.makeText(MainActivity.this,"请在系统设置中先启用NFC功能",Toast.LENGTH_LONG).show();
                return;
            }
            //因为启动模式是singleTop,于是会调用onNewIntent方法
            onNewIntent(getIntent());
    
        }

    在onNewIntent中,解析intent携带的卡对象

        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            //获取、传递、解析intent对象,intent中携带卡对象
            resolveIntent(intent);
        }
    
        //解析intent
        void resolveIntent(Intent intent) {
            //获取intent中携带的标签对象
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            if (tag != null) {
                //处理标签对象
                processTag(intent);
            }
        }

    在处理标签对象的方法中获取携带的数据中的ID字节数组并转换成十六进制字符串显示。

        //处理tag
        public void processTag(Intent intent) {
            //获取到卡对象
            Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            //获取卡id这里即uid,字节数组类型
            byte[] aa = tagFromIntent.getId();
            //字节数组转十六进制字符串
            String str = ByteArrayToHexString(aa);
            tvUid.setText(str);
    
        }

    完整Activity代码

    package com.badao.nfcdemo;
    
    import androidx.appcompat.app.AppCompatActivity;
    
    import android.app.PendingIntent;
    import android.content.Intent;
    import android.nfc.NfcAdapter;
    import android.nfc.Tag;
    import android.os.Bundle;
    import android.widget.TextView;
    import android.widget.Toast;
    
    public class MainActivity extends AppCompatActivity {
    
    
        private NfcAdapter nfcAdapter;
        private PendingIntent pendingIntent;
        private TextView tvUid;
    
        @Override
        protected void onCreate(Bundle savedInstanceState) {
            super.onCreate(savedInstanceState);
            setContentView(R.layout.activity_main);
    
            //获取显示文本框
            tvUid = (TextView) findViewById(R.id.tv_uid);
            //获取NfcAdapter实例
            nfcAdapter = NfcAdapter.getDefaultAdapter(this);
            //获取通知
            pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
                    getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
            //如果获取不到则不支持NFC
            if (nfcAdapter == null) {
                Toast.makeText(MainActivity.this,"设备不支持NFC",Toast.LENGTH_LONG).show();
                return;
            }
            //如果获取到的为不可用状态则未启用NFC
            if (nfcAdapter!=null&&!nfcAdapter.isEnabled()) {
                Toast.makeText(MainActivity.this,"请在系统设置中先启用NFC功能",Toast.LENGTH_LONG).show();
                return;
            }
            //因为启动模式是singleTop,于是会调用onNewIntent方法
            onNewIntent(getIntent());
    
        }
    
    
        @Override
        protected void onNewIntent(Intent intent) {
            super.onNewIntent(intent);
            //获取、传递、解析intent对象,intent中携带卡对象
            resolveIntent(intent);
        }
    
        //解析intent
        void resolveIntent(Intent intent) {
            //获取intent中携带的标签对象
            Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            if (tag != null) {
                //处理标签对象
                processTag(intent);
            }
        }
    
        //字节数组转换十六进制
        private String ByteArrayToHexString(byte[] inarray) {
            int i, j, in;
            String[] hex = { "0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A",
                    "B", "C", "D", "E", "F" };
            String out = "";
            for (j = 0; j < inarray.length; ++j) {
                in = (int) inarray[j] & 0xff;
                i = (in >> 4) & 0x0f;
                out += hex[i];
                i = in & 0x0f;
                out += hex[i];
            }
            return out;
        }
    
    
        //处理tag
        public void processTag(Intent intent) {
            //获取到卡对象
            Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            //获取卡id这里即uid,字节数组类型
            byte[] aa = tagFromIntent.getId();
            //字节数组转十六进制字符串
            String str = ByteArrayToHexString(aa);
            tvUid.setText(str);
    
        }
    
        @Override
        protected void onPause() {
            super.onPause();
            if (nfcAdapter != null)
                //设置程序不优先处理
                nfcAdapter.disableForegroundDispatch(this);
        }
    
        @Override
        protected void onResume() {
            super.onResume();
            if (nfcAdapter != null)
                //设置程序优先处理
                nfcAdapter.enableForegroundDispatch(this, pendingIntent,
                        null, null);
        }
    
    }

    5、运行app,打开nfc,将NFC卡片靠近手机

    可以以debug模式运行,依次打断点查看效果

    博客园: https://www.cnblogs.com/badaoliumangqizhi/ 关注公众号 霸道的程序猿 获取编程相关电子书、教程推送与免费下载。
  • 相关阅读:
    ng机器学习视频笔记(八) ——机器学习系统调试(cv、查准率与召回率等)
    ng机器学习视频笔记(七) ——神经网络的代价函数、反向传播、梯度检验、随机初始化
    post body 传输参数
    laravel队列使用
    nginx配置框架问题
    中大型网站架构之路一
    mongo笔记2
    架构4(lvs lb集群解决方案二 lvs+keepalived)
    架构3(基于LVS LB集群解决方案一:piranha)
    YII2 BUG记录
  • 原文地址:https://www.cnblogs.com/badaoliumangqizhi/p/15406532.html
Copyright © 2020-2023  润新知