Android NFC读取数据
1、添加相应的权限和gradle引用
<uses-feature
android:name="android.hardware.nfc"
android:required="true"/>
<uses-permission android:name="android.permission.NFC"/>
api 'com.google.guava:guava:25.1-android'
2、在res下创建xml文件夹,然后新建xml文件nfc_tech_filter
<?xml version="1.0" encoding="utf-8"?> <resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2"> <tech-list> <resources > <tech-list> <!--<tech>android.nfc.tech.IsoDep</tech>--> <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.Ndef</tech> <!--<tech>android.nfc.tech.NdefFormatable</tech>--> <!--<tech>android.nfc.tech.MifareClassic</tech>--> <!--<tech>android.nfc.tech.MifareUltralight</tech>--> </tech-list> </resources> </tech-list> </resources>
3、使用NFC的activity添加设置
<activity android:name=".activitys.rfid_nfc.NFCActivity" android:launchMode="singleTop"> <intent-filter> <action android:name="android.nfc.action.NDEF_DISCOVERED" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TECH_DISCOVERED" /> </intent-filter> <intent-filter> <action android:name="android.nfc.action.TAG_DISCOVERED" /> </intent-filter> <meta-data android:name="android.nfc.action.TECH_DISCOVERED" android:resource="@xml/nfc_tech_filter" /> </activity>
4、NFCActivity代码
package com.sam.more.activitys.rfid_nfc; import android.annotation.SuppressLint; import android.app.PendingIntent; import android.content.Intent; import android.nfc.NdefMessage; import android.nfc.NfcAdapter; import android.os.Bundle; import android.support.v7.app.AppCompatActivity; import android.util.Log; import android.view.View; import android.widget.Button; import android.widget.TextView; import android.widget.Toast; import com.sam.more.R; import java.util.Calendar; import java.util.List; import butterknife.BindView; import butterknife.ButterKnife; import butterknife.OnClick; /** * Author: Sam * Date: 2020/11/25 9:41 * Describe:NFC读取数据页面 */ public class NFCActivity extends AppCompatActivity { private static final String TAG = "NfcActivity"; @BindView(R.id.tv_show_nfc) TextView tvShowNfc; @BindView(R.id.btn_clean) Button btnClean; private PendingIntent mPendingIntent; private NfcAdapter mNfcAdapter; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_nfc); ButterKnife.bind(this); Log.i(TAG, "onCreate: "); //初始化nfc mNfcAdapter = NfcAdapter.getDefaultAdapter(this); mPendingIntent = PendingIntent.getActivity(this, 0, new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0); if (mNfcAdapter == null) { Toast.makeText(this, "NFC不可用", Toast.LENGTH_SHORT).show(); finish(); return; } } @Override protected void onResume() { super.onResume(); Log.i(TAG, "onResume: "); if (mNfcAdapter != null) { //有nfc功能 if (mNfcAdapter.isEnabled()) { //nfc功能打开了 //隐式启动 mNfcAdapter.enableForegroundDispatch(this, mPendingIntent, null, null); } else { Toast.makeText(this, "请打开NFC功能", Toast.LENGTH_SHORT).show(); } } } @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); Log.i(TAG, "onNewIntent: "); setIntent(intent); if (mNfcAdapter != null) { //有nfc功能 if (mNfcAdapter.isEnabled()) {//nfc功能打开了 resolveIntent(getIntent()); } else { Toast.makeText(this, "请打开NFC功能", Toast.LENGTH_SHORT).show(); } } } @Override protected void onPause() { super.onPause(); if (mNfcAdapter != null) { mNfcAdapter.disableForegroundDispatch(this); } } //初次判断是什么类型的NFC卡 private void resolveIntent(Intent intent) { NdefMessage[] msgs = NfcUtils.getNdefMsg(intent); //重点功能,解析nfc标签中的数据 if (msgs == null) { Toast.makeText(this, "非NFC启动", Toast.LENGTH_SHORT).show(); } else { setNFCMsgView(msgs); } } /** * 显示扫描后的信息 * * @param ndefMessages ndef数据 */ @SuppressLint("SetTextI18n") private void setNFCMsgView(NdefMessage[] ndefMessages) { if (ndefMessages == null || ndefMessages.length == 0) { return; } Calendar calendar = Calendar.getInstance(); int hour = calendar.get(Calendar.HOUR_OF_DAY); int minute = calendar.get(Calendar.MINUTE); tvShowNfc.append(hour + ":" + minute + "\n"); List<ParsedNdefRecord> records = NdefMessageParser.parse(ndefMessages[0]); final int size = records.size(); for (int i = 0; i < size; i++) { ParsedNdefRecord record = records.get(i); tvShowNfc.append(record.getViewText() + "\n"); } } @OnClick({R.id.btn_clean}) public void onViewClicked(View view) { switch (view.getId()) { case R.id.btn_clean: tvShowNfc.setText(""); break; } } }
NfcUtils工具类
package com.sam.more.activitys.rfid_nfc; import android.content.Intent; import android.nfc.NdefMessage; import android.nfc.NdefRecord; import android.nfc.NfcAdapter; import android.nfc.Tag; import android.nfc.tech.MifareClassic; import android.nfc.tech.MifareUltralight; import android.os.Parcelable; import android.util.Log; import java.util.Arrays; /** * Auther: Sam * Time: 2020/11/24 17:26 * Describe: */ public class NfcUtils { private static final String TAG = "NfcUtil"; /** * 解析 ndefRecord 文本数据 * * @param ndefRecord * @return */ public static String parse(NdefRecord ndefRecord) { // verify tnf 得到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(); // payload[0]取第一个字节。 0x80:十六进制(最高位是1剩下全是0) String textEncoding = ((payload[0] & 0x80) == 0) ? "UTF-8" : "UTF-16"; // 获得语言编码长度 int languageCodeLength = payload[0] & 0x3f; // 获得语言编码 String languageCode = new String(payload, 1, languageCodeLength, "US-ASCII"); // String text = new String(payload, languageCodeLength + 1, payload.length - languageCodeLength - 1, textEncoding); return text; } catch (Exception e) { throw new IllegalArgumentException(); } } //初次判断是什么类型的NFC卡 public static NdefMessage[] getNdefMsg(Intent intent) { if (intent == null) return null; //nfc卡支持的格式 Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); String[] temp = tag.getTechList(); for (String s : temp) { Log.i(TAG, "resolveIntent tag: " + s); } String action = intent.getAction(); if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) || NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) || NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) { Parcelable[] rawMessage = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES); NdefMessage[] ndefMessages; // 判断是哪种类型的数据 默认为NDEF格式 if (rawMessage != null) { Log.i(TAG, "getNdefMsg: ndef格式 "); ndefMessages = new NdefMessage[rawMessage.length]; for (int i = 0; i < rawMessage.length; i++) { ndefMessages[i] = (NdefMessage) rawMessage[i]; } } else { //未知类型 Log.i(TAG, "getNdefMsg: 未知类型"); byte[] empty = new byte[0]; byte[] id = intent.getByteArrayExtra(NfcAdapter.EXTRA_ID); Parcelable parcelable = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG); byte[] payload = dumpTagData(parcelable).getBytes(); NdefRecord record = new NdefRecord(NdefRecord.TNF_UNKNOWN, empty, id, payload); NdefMessage msg = new NdefMessage(new NdefRecord[]{record}); ndefMessages = new NdefMessage[]{msg}; } return ndefMessages; } return null; } //一般公交卡,扫描的信息 private static String dumpTagData(Parcelable p) { StringBuilder sb = new StringBuilder(); Tag tag = (Tag) p; byte[] id = tag.getId(); 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"); String prefix = "android.nfc.tech."; sb.append("Technologies: "); for (String tech : tag.getTechList()) { sb.append(tech.substring(prefix.length())); sb.append(", "); } sb.delete(sb.length() - 2, sb.length()); for (String tech : tag.getTechList()) { if (tech.equals(MifareClassic.class.getName())) { sb.append('\n'); MifareClassic mifareTag = MifareClassic.get(tag); String type = "Unknown"; switch (mifareTag.getType()) { case MifareClassic.TYPE_CLASSIC: type = "Classic"; break; case MifareClassic.TYPE_PLUS: type = "Plus"; break; case MifareClassic.TYPE_PRO: type = "Pro"; break; } sb.append("Mifare Classic type: "); sb.append(type); sb.append('\n'); sb.append("Mifare size: "); sb.append(mifareTag.getSize() + " bytes"); sb.append('\n'); sb.append("Mifare sectors: "); sb.append(mifareTag.getSectorCount()); sb.append('\n'); sb.append("Mifare blocks: "); sb.append(mifareTag.getBlockCount()); } if (tech.equals(MifareUltralight.class.getName())) { sb.append('\n'); MifareUltralight mifareUlTag = MifareUltralight.get(tag); String type = "Unknown"; switch (mifareUlTag.getType()) { case MifareUltralight.TYPE_ULTRALIGHT: type = "Ultralight"; break; case MifareUltralight.TYPE_ULTRALIGHT_C: type = "Ultralight C"; break; } sb.append("Mifare Ultralight type: "); sb.append(type); } } return sb.toString(); } private static String getHex(byte[] bytes) { StringBuilder sb = new StringBuilder(); for (int i = bytes.length - 1; i >= 0; --i) { int b = bytes[i] & 0xff; if (b < 0x10) sb.append('0'); sb.append(Integer.toHexString(b)); if (i > 0) { sb.append(" "); } } return sb.toString(); } private static long getDec(byte[] bytes) { long result = 0; long factor = 1; for (int i = 0; i < bytes.length; ++i) { long value = bytes[i] & 0xffl; result += value * factor; factor *= 256l; } return result; } private static long getReversed(byte[] bytes) { long result = 0; long factor = 1; for (int i = bytes.length - 1; i >= 0; --i) { long value = bytes[i] & 0xffl; result += value * factor; factor *= 256l; } return result; } }
完整资源地址:https://download.csdn.net/download/Jeyden_827/13187753