Android中讀取NFC標簽卡中的ID


場景

APP中讀取NFC卡中的標簽ID,作為用戶的唯一標識進行登錄驗證。

首先需要確保手機支持NFC功能。其次具備一張NFC卡片。

讀取id就是利用的讀卡器模式,當把卡片靠近手機的NFC天線的時候,NFC會識別到卡,

然后把卡對象裝到intent里面,

並發送廣播NfcAdapter.ACTION_TECH_DISCOVERED,

應用程序接到這個廣播之后,通過intent.getParcelableExtra(NfcAdapter.EXTRA_TAG)來獲取到卡對象,

然后就可以對卡進行讀寫

注:

博客:
https://blog.csdn.net/badao_liumang_qizhi
關注公眾號
霸道的程序猿
獲取編程相關電子書、教程推送與免費下載。

實現

1、新建項目,添加權限

打開Android Studio新建一個項目,在AndroidManifest.xml中添加權限。

    <!--    NFC所需權限-->
    <uses-permission android:name="android.permission.NFC" />
    <!-- 要求當前設備必須要有NFC芯片 -->
    <uses-feature android:name="android.hardware.nfc" android:required="true" />

 

 

 

2、將要讀取NFC的Activity設置為singleTop

這里是在MainActivity中

        <activity android:name=".MainActivity" android:launchMode="singleTop">
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

 

 

 

Activity共有四種啟動模式:

standard

標准模式,也是Activity的默認啟動模式,允許存在多個Activity實例,

每次啟動頁面時都會生成一個新的Activity實例。

singleTop

相比於standard,有新的頁面啟動請求時,當目標Activity處於當前棧頂時,

會調用Activity的onNewIntent()方法,但不創建新實例;其他情況都和standard一致。

其他兩種不做介紹。

NFC檢測到對象時,會在系統startActivity,那么目標activity已經是啟動了,

所以我們需要在onNewIntent方法中接受tag對象,同時activity啟動模式設為singleTop或singleTask也為了避免重復創建實例

3、設計頁面布局

打開activity_main.xml,修改如下

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/activity_main"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    android:background="#151414"
    >
    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:orientation="horizontal"
        android:layout_centerInParent="true"
        >
        <TextView
            android:layout_width="wrap_content"
            android:text="讀取到的卡UID: "
            android:textColor="#fff"
            android:layout_height="wrap_content" />
        <TextView
            android:textColor="#fff"
            android:id="@+id/tv_uid"
            android:text="                            "
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"/>
    </LinearLayout>
</RelativeLayout>

4、修改Activity

在OnCreate方法中,獲取NfcAdapter實例,然后獲取通知,判斷支持NFC並且打開后,當獲取通知后會調用onNewIntent方法。

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //獲取顯示文本框
        tvUid = (TextView) findViewById(R.id.tv_uid);
        //獲取NfcAdapter實例
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        //獲取通知
        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        //如果獲取不到則不支持NFC
        if (nfcAdapter == null) {
            Toast.makeText(MainActivity.this,"設備不支持NFC",Toast.LENGTH_LONG).show();
            return;
        }
        //如果獲取到的為不可用狀態則未啟用NFC
        if (nfcAdapter!=null&&!nfcAdapter.isEnabled()) {
            Toast.makeText(MainActivity.this,"請在系統設置中先啟用NFC功能",Toast.LENGTH_LONG).show();
            return;
        }
        //因為啟動模式是singleTop,於是會調用onNewIntent方法
        onNewIntent(getIntent());

    }

在onNewIntent中,解析intent攜帶的卡對象

    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        //獲取、傳遞、解析intent對象,intent中攜帶卡對象
        resolveIntent(intent);
    }

    //解析intent
    void resolveIntent(Intent intent) {
        //獲取intent中攜帶的標簽對象
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (tag != null) {
            //處理標簽對象
            processTag(intent);
        }
    }

在處理標簽對象的方法中獲取攜帶的數據中的ID字節數組並轉換成十六進制字符串顯示。

    //處理tag
    public void processTag(Intent intent) {
        //獲取到卡對象
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        //獲取卡id這里即uid,字節數組類型
        byte[] aa = tagFromIntent.getId();
        //字節數組轉十六進制字符串
        String str = ByteArrayToHexString(aa);
        tvUid.setText(str);

    }

完整Activity代碼

package com.badao.nfcdemo;

import androidx.appcompat.app.AppCompatActivity;

import android.app.PendingIntent;
import android.content.Intent;
import android.nfc.NfcAdapter;
import android.nfc.Tag;
import android.os.Bundle;
import android.widget.TextView;
import android.widget.Toast;

public class MainActivity extends AppCompatActivity {


    private NfcAdapter nfcAdapter;
    private PendingIntent pendingIntent;
    private TextView tvUid;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        //獲取顯示文本框
        tvUid = (TextView) findViewById(R.id.tv_uid);
        //獲取NfcAdapter實例
        nfcAdapter = NfcAdapter.getDefaultAdapter(this);
        //獲取通知
        pendingIntent = PendingIntent.getActivity(this, 0, new Intent(this,
                getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP), 0);
        //如果獲取不到則不支持NFC
        if (nfcAdapter == null) {
            Toast.makeText(MainActivity.this,"設備不支持NFC",Toast.LENGTH_LONG).show();
            return;
        }
        //如果獲取到的為不可用狀態則未啟用NFC
        if (nfcAdapter!=null&&!nfcAdapter.isEnabled()) {
            Toast.makeText(MainActivity.this,"請在系統設置中先啟用NFC功能",Toast.LENGTH_LONG).show();
            return;
        }
        //因為啟動模式是singleTop,於是會調用onNewIntent方法
        onNewIntent(getIntent());

    }


    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        //獲取、傳遞、解析intent對象,intent中攜帶卡對象
        resolveIntent(intent);
    }

    //解析intent
    void resolveIntent(Intent intent) {
        //獲取intent中攜帶的標簽對象
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (tag != null) {
            //處理標簽對象
            processTag(intent);
        }
    }

    //字節數組轉換十六進制
    private 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" };
        String out = "";
        for (j = 0; j < inarray.length; ++j) {
            in = (int) inarray[j] & 0xff;
            i = (in >> 4) & 0x0f;
            out += hex[i];
            i = in & 0x0f;
            out += hex[i];
        }
        return out;
    }


    //處理tag
    public void processTag(Intent intent) {
        //獲取到卡對象
        Tag tagFromIntent = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        //獲取卡id這里即uid,字節數組類型
        byte[] aa = tagFromIntent.getId();
        //字節數組轉十六進制字符串
        String str = ByteArrayToHexString(aa);
        tvUid.setText(str);

    }

    @Override
    protected void onPause() {
        super.onPause();
        if (nfcAdapter != null)
            //設置程序不優先處理
            nfcAdapter.disableForegroundDispatch(this);
    }

    @Override
    protected void onResume() {
        super.onResume();
        if (nfcAdapter != null)
            //設置程序優先處理
            nfcAdapter.enableForegroundDispatch(this, pendingIntent,
                    null, null);
    }

}

 

5、運行app,打開nfc,將NFC卡片靠近手機

 

 

可以以debug模式運行,依次打斷點查看效果

 

 

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM