Android读取NFC卡片数据

这里以nfc公交卡为例子

使用如下
  1. 请将需要获取nfc数据的 Activity 对应的清单文件里面设置成 栈顶模式,并在intent 标签内添加 action -- nfc
java 复制代码
android:launchMode="singleTop"
java 复制代码
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
  1. 在对应Activity内的各个生命周期内加入以下代码
onCreate 创建nfc

初始化NFC show 里面是说明当前设备是否支持NFC是否打开NFC

java 复制代码
NfcUtil.createNfc(this,object : NfcUtil.NFCCreateBack{
            override fun show(s: String) {
                Log.e("NFC_TAG", "createNfc: -${s}", )
            }
        })

该设备是否支持NFC

java 复制代码
NfcUtil.getNFC(this)

跳到手机系统NFC设置界面

java 复制代码
NfcUtil.jumpNFC()
onResume 开启nfc监听
java 复制代码
NfcUtil.resumeNfc()
onPause 关闭nfc监听
java 复制代码
NfcUtil.pauseNfc()
onNewIntent 获取监听到的数据
java 复制代码
//这里必须setIntent,set  NFC事件响应后的intent才能拿到数据
        setIntent(intent)
        NfcUtil.resolveIntent(intent!!,object: NfcUtil.NFCBack{
            override fun onSuc(s: NfcUtil.NFCBean) {
                tv1?.text = "名称: ${s.tagID_hex}"
                tv2?.text = "ID: ${s.tagID_dec}"
                tv3?.text = "内存大小: ${s.tagID_size}"
                tv4?.text = "名称: ${s.msg}"
            }

        })

NfcUtil

java 复制代码
/**
 * Nfc读取工具类
 * */
@SuppressLint("StaticFieldLeak")
object NfcUtil {

    private var activity: Activity? = null
    var mNfcAdapter: NfcAdapter? = null
    var pIntent: PendingIntent? = null
    lateinit var mIntentFilter: Array<IntentFilter>
    lateinit var mTechList: Array<Array<String>>

    //创建必要数据
    fun createNfc(a: Activity,c: NFCCreateBack){
        activity = a
        mNfcAdapter = NfcAdapter.getDefaultAdapter(activity)
        if (mNfcAdapter == null) {
            c.show("设备不支持NFC!")
        }else{
            if (!mNfcAdapter!!.isEnabled) {
                c.show("请在系统设置中先启用NFC功能!")
            }
            pIntent = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.S) {
                PendingIntent.getActivity(activity, 0, Intent(activity,activity?.javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), PendingIntent.FLAG_MUTABLE )
            } else {
                PendingIntent.getActivity(activity, 0, Intent(activity, activity?.javaClass).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0)
            }
        }
    }

    //创建回调
    interface NFCCreateBack{
        fun show(s: String)
    }


    //进入界面调用
    fun resumeNfc(){
        mNfcAdapter?.let {
            //intentFilter过滤----ndef
            val ndefFilter = IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED)
            try {
                //文本类型
                ndefFilter.addDataType("text/plain")
            } catch (e: MalformedMimeTypeException) {
                e.printStackTrace()
            }
            //intentFilter过滤----非ndef
            val techFilter = IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED)
            val tag = IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED)

            //intentFilter过滤器列表
            mIntentFilter = arrayOf(ndefFilter,techFilter,tag)
            //匹配的数据格式列表
            mTechList = arrayOf(
                arrayOf(MifareClassic::class.java.name),
                arrayOf(NfcA::class.java.name),
                arrayOf(Ndef::class.java.name),
                arrayOf(NdefFormatable::class.java.name)
            )
            it.enableForegroundDispatch(activity, pIntent, mIntentFilter, mTechList)
        }
    }

    //去除NFC监听
    fun pauseNfc(){
        mNfcAdapter?.disableForegroundDispatch(activity)
    }

    //处理接收到的NFC数据
    fun resolveIntent(intent: Intent,nfcBack: NFCBack){
        val action = intent.action
        Log.e("NFC_TAG", "action Type: $action")
       if (NfcAdapter.ACTION_TECH_DISCOVERED == intent.action) {
            val tag1: Parcelable? = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
            if (tag1 != null) {
                Log.e("NFC_TAG", "解析数据: ${dumpTagData66(tag1,nfcBack)}")
                dumpTagData66(tag1,nfcBack)
            }
        }else {
           val tag: Tag? = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
           var tagIDHex: String = ""
           var tagIDDec: String = ""
           val tagIDSize: String = "1024"
           if (tag != null) {
               val nfcId = dumpTagData(tag)
               tagIDHex = getHex(tag.id).toString()
               tagIDDec = getDec(tag.id).toString()
               if (nfcId.isNotEmpty()) {
                   Log.e("NFC_TAG", "接收到卡片ID: $nfcId")
               } else {
                   Log.e("NFC_TAG", "识别失败!请重新刷卡!")
               }

           }
           nfcBack.onSuc(NFCBean(tagIDHex,tagIDDec,tagIDSize,""))
       }
    }

    //回调
    interface NFCBack{
        fun onSuc(s: NFCBean)
    }

    //数据内容实体类
    data class NFCBean(
        var tagID_hex: String? = "", //id,不同的解析
        var tagID_dec: String? = "", //id,不同的解析
        var tagID_size: String? = "", //id,不同的解析
        var msg: String? = "" //详细数据
    )

    private fun dumpTagData(p: Tag): String {
        val id = p.id
        return bytesToHexString(id)
    }

    /**
     * 将字节数组转换为字符串
     */
    private fun bytesToHexString(inT: ByteArray): String {
        var i: Int
        var iny: Int
        val hex =
            arrayOf("0", "1", "2", "3", "4", "5", "6", "7", "8", "9", "A", "B", "C", "D", "E", "F")
        var out = ""
        var j: Int = 0
        while (j < inT.size) {
            iny = inT[j].toInt() and 0xff
            i = iny shr 4 and 0x0f
            out += hex[i]
            i = iny and 0x0f
            out += hex[i]
            ++j
        }
        return out
    }

    //一般公家卡,扫描的信息
    private fun dumpTagData66(p: Parcelable,nfcBack: NFCBack): String {

        var tagIDHex: String = ""
        var tagIDDec: String = ""
        var tagIDSize: String = "1024"
        var msg = ""

        val sb = java.lang.StringBuilder()
        val tag = p as Tag
        val id = tag.id
        sb.append("Tag ID (hex): ").append(getHex(id)).append("\n")
        sb.append("Tag ID (dec): ").append(getDec(id)).append("\n")
        sb.append("ID (reversed): ").append(getReversed(id)).append("\n")
        val prefix = "android.nfc.tech."
        sb.append("Technologies: ")

        tagIDHex = getHex(id).toString()
        tagIDDec = getDec(id).toString()
        for (tech in tag.techList) {
            sb.append(tech.substring(prefix.length))
            sb.append(", ")
        }
        sb.delete(sb.length - 2, sb.length)
        for (tech in tag.techList) {
            if (tech == MifareClassic::class.java.name) {
                sb.append('\n')
                val mifareTag = MifareClassic.get(tag)
                tagIDSize = mifareTag.size.toString()
                var type = "Unknown"
                when (mifareTag.type) {
                    MifareClassic.TYPE_CLASSIC -> type = "Classic"
                    MifareClassic.TYPE_PLUS -> type = "Plus"
                    MifareClassic.TYPE_PRO -> type = "Pro"
                }
                sb.append("Mifare Classic type: ")
                sb.append(type)
                sb.append('\n')
                sb.append("Mifare size: ")
                sb.append("${mifareTag.size} bytes")
                sb.append('\n')
                sb.append("Mifare sectors: ")
                sb.append(mifareTag.sectorCount)
                sb.append('\n')
                sb.append("Mifare blocks: ")
                sb.append(mifareTag.blockCount)
            }
            if (tech == MifareUltralight::class.java.name) {
                sb.append('\n')
                val mifareUlTag: MifareUltralight = MifareUltralight.get(tag)
                var type = "Unknown"
                when (mifareUlTag.type) {
                    MifareUltralight.TYPE_ULTRALIGHT -> type = "Ultralight"
                    MifareUltralight.TYPE_ULTRALIGHT_C -> type = "Ultralight C"
                }
                sb.append("Mifare Ultralight type: ")
                sb.append(type)
            }
        }
        msg = sb.toString()
        nfcBack.onSuc(NFCBean(tagIDHex,tagIDDec,tagIDSize,msg))
        return sb.toString()
    }

    private fun getHex(bytes: ByteArray): String? {
        val sb = StringBuilder()
        for (i in bytes.indices.reversed()) {
            val b = bytes[i].toInt() and 0xff
            if (b < 0x10) sb.append('0')
            sb.append(Integer.toHexString(b))
            if (i > 0) {
                sb.append(" ")
            }
        }
        return sb.toString()
    }

    private fun getDec(bytes: ByteArray): Long {
        var result: Long = 0
        var factor: Long = 1
        for (i in bytes.indices) {
            val value = bytes[i].toLong() and 0xffL
            result += value * factor
            factor *= 256L
        }
        return result
    }

    private fun getReversed(bytes: ByteArray): Long {
        var result: Long = 0
        var factor: Long = 1
        for (i in bytes.indices.reversed()) {
            val value = bytes[i].toLong() and 0xffL
            result += value * factor
            factor *= 256L
        }
        return result
    }

    /**
     * 跳转到NFC设置界面*/
    fun jumpNFC(){
        val setNfc = Intent(Settings.ACTION_NFC_SETTINGS)
        activity!!.startActivity(setNfc)
    }

    /**
     * 该设备是否支持NFC*/
    fun getNFC(context: Context): Boolean{
        val packageManager = context.packageManager
        return packageManager.hasSystemFeature(PackageManager.FEATURE_NFC)
    }
}
相关推荐
雾里看山1 小时前
【MySQL】 库的操作
android·数据库·笔记·mysql
水瓶丫头站住10 小时前
安卓APP如何适配不同的手机分辨率
android·智能手机
xvch10 小时前
Kotlin 2.1.0 入门教程(五)
android·kotlin
xvch14 小时前
Kotlin 2.1.0 入门教程(七)
android·kotlin
望风的懒蜗牛14 小时前
编译Android平台使用的FFmpeg库
android
浩宇软件开发15 小时前
Android开发,待办事项提醒App的设计与实现(个人中心页)
android·android studio·android开发
ac-er888815 小时前
Yii框架中的多语言支持:如何实现国际化
android·开发语言·php
苏金标16 小时前
The maximum compatible Gradle JVM version is 17.
android
zhangphil16 小时前
Android BitmapShader简洁实现马赛克,Kotlin(一)
android·kotlin
iofomo21 小时前
Android平台从上到下,无需ROOT/解锁/刷机,应用级拦截框架的最后一环,SVC系统调用拦截。
android