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

 

posted @ 2021-04-28 23:39  卧龙传奇  阅读(1294)  评论(0编辑  收藏  举报