Android读取NFC卡片数据
这里以nfc公交卡为例子
使用如下
- 请将需要获取nfc数据的 Activity 对应的清单文件里面设置成 栈顶模式,并在intent 标签内添加 action – nfc
android:launchMode="singleTop"
<action android:name="android.nfc.action.NDEF_DISCOVERED" />
- 在对应Activity内的各个生命周期内加入以下代码
onCreate 创建nfc
初始化NFC show 里面是说明当前设备是否支持NFC是否打开NFC
NfcUtil.createNfc(this,object : NfcUtil.NFCCreateBack{
override fun show(s: String) {
Log.e("NFC_TAG", "createNfc: -${s}", )
}
})
该设备是否支持NFC
NfcUtil.getNFC(this)
跳到手机系统NFC设置界面
NfcUtil.jumpNFC()
onResume 开启nfc监听
NfcUtil.resumeNfc()
onPause 关闭nfc监听
NfcUtil.pauseNfc()
onNewIntent 获取监听到的数据
//这里必须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
/**
* 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)
}
}