要获取NFC标签,首先需要添加NFC权限
<uses-feature
android:name="android.hardware.nfc"
android:required="true"/>
<uses-permission android:name="android.permission.NFC"/>
获取NFC标签及其ID
class NfcActivity : BaseActivity() {
private lateinit var imgBack: ImageView
private lateinit var mNfcAdapter: NfcAdapter
private lateinit var mPendingIntent: PendingIntent
//nfc标签信息
private lateinit var tvNfcTag: TextView
//nfc十进制ID
private lateinit var tvNfcD: TextView
//nfc16进制ID
private lateinit var tvNfcH: TextView
/**
* 启动Activity
*/
override fun onStart() {
super.onStart()
mNfcAdapter = NfcAdapter.getDefaultAdapter(this)
//一旦截获NFC消息,就会通过PendingIntent调用窗口
mPendingIntent = PendingIntent.getActivity(this, 0, Intent(this, javaClass), 0)
}
override fun getLayoutId(): Int {
return R.layout.activity_nfc
}
override fun eventBus(event: Any?) {
}
override fun onCreate(savedInstanceState: Bundle?) {
super.onCreate(savedInstanceState)
imgBack = findViewById(R.id.img_nfc_back)
tvNfcD = findViewById(R.id.tv_nfc_d)
tvNfcH = findViewById(R.id.tv_nfc_h)
tvNfcTag = findViewById(R.id.tv_nfc_tag)
imgBack.setOnClickListener { finish() }
}
override fun onResume() {
super.onResume()
//设置处理优于所有其他NFC的处理
mNfcAdapter.enableForegroundDispatch(
this,
mPendingIntent,
null,
null
)
}
override fun onPause() {
super.onPause()
//恢复默认状态
mNfcAdapter.disableForegroundDispatch(this)
}
override fun onNewIntent(intent: Intent?) {
super.onNewIntent(intent)
// readFromTag(intent);
readNfcTag(intent!!)
}
/**
* 读取NFC标签文本数据
*/
private fun readNfcTag(intent: Intent) {
val tag: Tag? = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)
if (tag != null) {
val cardNo = flipHexStr(ByteArrayToHexString(tag.id)).toLong(16)
tvNfcD.text = cardNo.toString()
tvNfcH.text = ByteArrayToHexString(tag.id)
}
if (NfcAdapter.ACTION_NDEF_DISCOVERED == intent.action) {
val rawMessages = intent.getParcelableArrayExtra(
NfcAdapter.EXTRA_NDEF_MESSAGES
)
var msgs: Array<NdefMessage?>? = null
var contentSize = 0
if (rawMessages != null) {
msgs = arrayOfNulls(rawMessages.size)
for (i in rawMessages.indices) {
msgs[i] = rawMessages[i] as NdefMessage
contentSize += msgs[i]!!.toByteArray().size
}
}
try {
if (null != msgs) {
val record = msgs[0]!!.records[0]
val textRecord: String? =
NfcUtil.parseTextRecord(record)
Log.e("nfcTag-->", "" + textRecord)
tvNfcTag.text = textRecord
}
} catch (e: Exception) {
e.printStackTrace()
Log.e("nfcError-->", "" + e)
}
}
}
}
获取标签及其ID的工具类
public class NfcUtil {
/**
* 解析NDEF文本数据,从第三个字节开始,后面的文本数据
* @param ndefRecord
* @return
*/
public static String parseTextRecord(NdefRecord ndefRecord) {
/**
* 判断数据是否为NDEF格式
* 判断TNF
*/
if (ndefRecord.getTnf() != NdefRecord.TNF_WELL_KNOWN) {
return null;
}
//判断可变的长度的类型
if (!Arrays.equals(ndefRecord.getType(), NdefRecord.RTD_TEXT)) {
return null;
}
try {
//获得字节数组,然后进行分析
byte[] payload = ndefRecord.getPayload();
//下面开始NDEF文本数据第一个字节,状态字节
//判断文本是基于UTF-8还是UTF-16的,取第一个字节"位与"上16进制的80,16进制的80也就是最高位是1,
//其他位都是0,所以进行"位与"运算后就会保留最高位
String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8" : "UTF-16";
//3f最高两位是0,第六位是1,所以进行"位与"运算后获得第六位
int languageCodeLength = payload[0] & 0x3f;
//下面开始NDEF文本数据第二个字节,语言编码
//获得语言编码
String languageCode = new String(payload, 1, languageCodeLength, StandardCharsets.US_ASCII);
//下面开始NDEF文本数据后面的字节,解析出文本
String textRecord = new String(payload, languageCodeLength + 1,
payload.length - languageCodeLength - 1, textEncoding);
return textRecord;
} catch (Exception e) {
throw new IllegalArgumentException();
}
}
// 16转10进制
public static String flipHexStr(String s) {
StringBuilder result = new StringBuilder();
for (int i = 0; i <= s.length() - 2; i = i + 2) {
result.append(new StringBuilder(s.substring(i, i + 2)).reverse());
}
return result.reverse().toString();
}
public static 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"};
StringBuilder out = new StringBuilder();
for (j = 0; j < inarray.length; ++j) {
in = (int) inarray[j] & 0xff;
i = (in >> 4) & 0x0f;
out.append(hex[i]);
i = in & 0x0f;
out.append(hex[i]);
}
return out.toString();
}
}