欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

Android開發(fā)實(shí)現(xiàn)NFC刷卡讀取的兩種方式

 更新時(shí)間:2021年09月18日 11:54:13   作者:TheFlashArrow  
這篇文章主要為大家詳細(xì)介紹了Android開發(fā)中實(shí)現(xiàn)NFC刷卡讀取的兩種方式,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下

場(chǎng)景:NFC是目前Android手機(jī)一個(gè)主流的配置硬件項(xiàng),本文主要講解一下Android開發(fā)中,NFC刷卡的兩種實(shí)現(xiàn)方式以及相關(guān)方法源碼解析。

①:Manifest注冊(cè)方式:這種方式主要是在Manifest文件對(duì)應(yīng)的activity下,配置過(guò)濾器,以響應(yīng)不同類型NFC  Action。使用這種方式,在刷卡時(shí),如果手機(jī)中有多個(gè)應(yīng)用都存在該NFC實(shí)現(xiàn)方案,系統(tǒng)會(huì)彈出能響應(yīng)NFC事件的應(yīng)用列表供用戶選擇,用戶需要點(diǎn)擊目標(biāo)應(yīng)用來(lái)響應(yīng)本次NFC刷卡事件。目前我公司這邊項(xiàng)目中使用了該邏輯,比較簡(jiǎn)便,這里先貼一下該方式的實(shí)現(xiàn)邏輯。

Manifest配置:

<!--權(quán)限要加,這是一個(gè)普通權(quán)限,不需要?jiǎng)討B(tài)申請(qǐng),但是在小米手機(jī)里需要?jiǎng)討B(tài)申請(qǐng)-->
     <uses-permission android:name="android.permission.NFC" />
   
     <uses-feature
        android:name="android.hardware.nfc"
        android:required="false" />
 
     <application> 
        ...   
        <activity
            android:name=".NfcActivity"
            android:launchMode="singleTask"
            android:screenOrientation="portrait"
            android:theme="@android:style/Theme.Translucent">
            <!--透明主題,把刷卡變成一個(gè)無(wú)感知的過(guò)程-->
            <intent-filter>
                <action android:name="android.nfc.action.NDEF_DISCOVERED" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.TAG_DISCOVERED" />
 
                <category android:name="android.intent.category.DEFAULT" />
            </intent-filter>
            <intent-filter>
                <action android:name="android.nfc.action.TECH_DISCOVERED" />
                <!--使用這個(gè)過(guò)濾器 這里其實(shí)還要用 meta-data 配置一下標(biāo)簽過(guò)濾,-->
                <!--我項(xiàng)目中是 NDEF_DISCOVERED 這個(gè)TECH_DISCOVERED形同虛設(shè)-->
            </intent-filter>
            <meta-data
                android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_tech" />
        </activity>
</application> 

nfc_tech.xml:這個(gè)文件就是TECH_DISCOVERED需要配置的,其中,tech-list之間是邏輯或關(guān)系,tech之間是邏輯與關(guān)系,與方案②中的techLists原理以及用途是類似的。

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:android="http://schemas.android.com/apk/res/android">
 
    <tech-list>
        <tech>android.nfc.tech.Ndef</tech>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
 
    <tech-list>
        <tech>android.nfc.tech.NfcB</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcF</tech>
    </tech-list>
</resources>

NfcActivity:

public class NfcActivity extends Activity {
 
    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_nfc);
        initData();
    }
 
    /**
     * 初始化數(shù)據(jù)
     */
    private void initData() {
        NfcAdapter adapter = NfcAdapter.getDefaultAdapter(this);
        if (null == adapter) {
            Toast.makeText(this, "不支持NFC功能", Toast.LENGTH_SHORT).show();
        } else if (!adapter.isEnabled()) {
            Intent intent = new Intent(Settings.ACTION_NFC_SETTINGS);
            // 根據(jù)包名打開對(duì)應(yīng)的設(shè)置界面
            startActivity(intent);
        }
 
        //我項(xiàng)目中是拿了NFC卡的tag中的id數(shù)據(jù),這根據(jù)具體情況來(lái);
        // 可以在NfcAdapter源碼中查看,具體能拿到哪些數(shù)據(jù)
        Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
        String id = bytesToHex(tag.getId());
 
        //TODO 目前我這邊項(xiàng)目中,拿到數(shù)據(jù)后,通過(guò)EventBus分發(fā)到對(duì)應(yīng)的activity,當(dāng)然也能使用其他分發(fā)響應(yīng)方式,
 
        //關(guān)閉動(dòng)畫,畢竟對(duì)用戶來(lái)說(shuō),刷卡應(yīng)當(dāng)是一個(gè)無(wú)感知的過(guò)程
        overridePendingTransition(0, 0);
        finish();
    }
 
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        initData();
    }
 
    /**
     *  2轉(zhuǎn)10
     * @param src
     * @return
     */
    private static String bytesToTenNum(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        if (src == null || src.length <= 0) {
            return null;
        }
        char[] buffer = new char[2];
        for (int i = 0; i < src.length; i++) {
            buffer[1] = Character.toUpperCase(Character.forDigit(
                    (src[i] >>> 4) & 0x0F, 16));
            buffer[0] = Character.toUpperCase(Character.forDigit(src[i] & 0x0F,
                    16));
            stringBuilder.append(buffer);
        }
        stringBuilder.reverse();
        BigInteger bigi = new BigInteger(stringBuilder.toString(), 16);
        return bigi.toString();
    }
 
    /**
     * 2轉(zhuǎn)16
     * @param src
     * @return
     */
    private static String bytesToHex(byte[] src){
        StringBuffer sb = new StringBuffer();
        if (src == null || src.length <= 0) {
            return null;
        }
        String sTemp;
        for (int i = 0; i < src.length; i++) {
            sTemp = Integer.toHexString(0xFF & src[i]);
            if (sTemp.length() < 2){
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }
}

②:前臺(tái)響應(yīng)機(jī)制:這種方式與第一種的區(qū)別如下:方法一中,NFC事件由系統(tǒng)分發(fā),需要選擇應(yīng)用去響應(yīng)事件;而方法二,直接使用前臺(tái)activity來(lái)捕獲NFC事件進(jìn)行響應(yīng),并且優(yōu)先級(jí)高于方案一。

下面對(duì)該方案進(jìn)行解析,直接懟上代碼。這里我新建了一個(gè)NfcTestActivity進(jìn)行測(cè)試,布局文件就補(bǔ)貼了,隨便丟一個(gè)就行。

NfcTestActivity:

/**
 * @author Flash
 * 創(chuàng)建時(shí)間:2021-07-30 11:14
 */
public class NfcTestActivity extends AppCompatActivity {
 
    NfcAdapter mNfcAdapter;
    PendingIntent pIntent;
 
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_nfc_test);
        initNfc();
        Log.i("FlashTestNFC", "onCreate");
    }
 
    @Override
    protected void onStop() {
        super.onStop();
        Log.i("FlashTestNFC", "onStop");
    }
 
    @Override
    protected void onDestroy() {
        super.onDestroy();
        Log.i("FlashTestNFC", "onDestroy");
    }
 
    /**
     * 初始化
     */
    private void initNfc(){
        mNfcAdapter = NfcAdapter.getDefaultAdapter(this);
        pIntent = PendingIntent.getActivity(this, 0,
                //在Manifest里或者這里設(shè)置當(dāng)前activity啟動(dòng)模式,否則每次向陽(yáng)NFC事件,activity會(huì)重復(fù)創(chuàng)建
                // 當(dāng)然也要按照具體情況來(lái),你設(shè)置成singleTask也不是不行,
                new Intent(this, getClass()).addFlags(Intent.FLAG_ACTIVITY_SINGLE_TOP),
                0);
    }
 
    @Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        //這里必須setIntent,set  NFC事件響應(yīng)后的intent才能拿到數(shù)據(jù)
        setIntent(intent);
        Log.i("FlashTestNFC", "onNewIntent");
        Tag tag = getIntent().getParcelableExtra(NfcAdapter.EXTRA_TAG);
 
        //TODO 獲取數(shù)據(jù)進(jìn)行下一步處理
 
        Log.i("FlashTestNFC--Tag", bytesToHex(tag.getId()));
    }
 
    @Override
    protected void onResume() {
        super.onResume();
        Log.i("FlashTestNFC", "onResume");
        if (mNfcAdapter != null) {
            //添加intent-filter
            IntentFilter ndef = new IntentFilter(NfcAdapter.ACTION_NDEF_DISCOVERED);
            IntentFilter tag = new IntentFilter(NfcAdapter.ACTION_TAG_DISCOVERED);
            IntentFilter tech = new IntentFilter(NfcAdapter.ACTION_TECH_DISCOVERED);
            IntentFilter[] filters = new IntentFilter[]{ndef, tag, tech};
 
            //添加 ACTION_TECH_DISCOVERED 情況下所能讀取的NFC格式,這里列的比較全,實(shí)際我這里是沒有用到的,因?yàn)闇y(cè)試的卡是NDEF的
            String[][] techList = new String[][]{
                    new String[]{
                            "android.nfc.tech.Ndef",
                            "android.nfc.tech.NfcA",
                            "android.nfc.tech.NfcB",
                            "android.nfc.tech.NfcF",
                            "android.nfc.tech.NfcV",
                            "android.nfc.tech.NdefFormatable",
                            "android.nfc.tech.MifareClassic",
                            "android.nfc.tech.MifareUltralight",
                            "android.nfc.tech.NfcBarcode"
                    }
            };
            mNfcAdapter.enableForegroundDispatch(this, pIntent, filters, techList);
        }
    }
 
    @Override
    protected void onPause() {
        super.onPause();
        Log.i("FlashTestNFC", "onPause");
        if (mNfcAdapter != null) {
            mNfcAdapter.disableForegroundDispatch(this);
        }
    }
 
    /**
     * 2進(jìn)制to 16進(jìn)制
     * @param src
     * @return
     */
    private static String bytesToHex(byte[] src){
        StringBuffer sb = new StringBuffer();
        if (src == null || src.length <= 0) {
            return null;
        }
        String sTemp;
        for (int i = 0; i < src.length; i++) {
            sTemp = Integer.toHexString(0xFF & src[i]);
            if (sTemp.length() < 2){
                sb.append(0);
            }
            sb.append(sTemp.toUpperCase());
        }
        return sb.toString();
    }
}

解析:主要其實(shí)就是NfcAdapter.enableForegroundDispatch(),開啟前臺(tái)響應(yīng);在onNewIntent中獲取系統(tǒng)傳遞過(guò)來(lái)的數(shù)據(jù),并解析;在前臺(tái)activity停止時(shí),使用NfcAdapter.disableForegroundDispatch()關(guān)閉響應(yīng)。下圖是該activity在設(shè)置啟動(dòng)模式為singleTop或singleTask情況下,刷卡后該activity生命周期變化:

enableForegroundDispatch源碼注釋解析,這里大致翻譯一下:

  • 將發(fā)現(xiàn)的tag(可以理解為NFC刷卡事件)優(yōu)先分配給應(yīng)用程序的前臺(tái)activity;
  • 如果給該方法提供了任何IntentFilters,那么會(huì)優(yōu)先去匹配ACTION_NDEF_DISCOVERED和ACTION_TAG_DISCOVERED。由于ACTION_TECH_DISCOVERED依賴于 IntentFilter 匹配之外的元數(shù)據(jù),使用改IntentFilter要通過(guò)單獨(dú)傳入techLists來(lái)處理的。techLists中的每個(gè)第一級(jí)條目下的配置必須全部匹配才行。如果任何一級(jí)下的內(nèi)容都匹配,則分派將通過(guò)給定的 PendingIntent 進(jìn)行路由。(這三句話我解釋一下:techLists參數(shù)是一個(gè)二維數(shù)組,可以設(shè)置很多級(jí),每一級(jí)下是第二級(jí),在第二級(jí)中放置相關(guān)匹配項(xiàng);看我方法②中對(duì)techLists數(shù)組的構(gòu)建方式就能明白)。換句話說(shuō),第一級(jí)內(nèi)容是邏輯或關(guān)系,第二級(jí)內(nèi)容是邏輯與關(guān)系。
  • 如果IntentFilters和techLists都傳了null,那么會(huì)默認(rèn)匹配ACTION_TAG_DISCOVERED
  • 這個(gè)方法必須在主線程調(diào)用,并且activity必須處于前臺(tái)的情況下。同時(shí),在activity調(diào)用enableForegroundDispatch方法后,必須在onPause時(shí)調(diào)用disableForegroundDispatch進(jìn)行關(guān)閉。
  • Manifest文件中要聲明NFC權(quán)限。

總結(jié):大概19年8-9月份的時(shí)候,那會(huì)兒剛開始實(shí)習(xí)不久,當(dāng)時(shí)手頭負(fù)責(zé)的項(xiàng)目就涉及到NFC刷卡,使用了方案①中的方式。在開發(fā)過(guò)程中,調(diào)試機(jī)為自己的華為Mate 20手機(jī),每一次我打開刷卡頁(yè)面進(jìn)行刷卡時(shí),都會(huì)默認(rèn)跳轉(zhuǎn)到微信的NFC事件響應(yīng)頁(yè)面,這叫一個(gè)頭大;后來(lái)直接找到微信NFC開關(guān),將其關(guān)閉后才不影響調(diào)試。好在線上手持機(jī)設(shè)備都是不讓用戶安裝其他應(yīng)用的。當(dāng)時(shí)還很奇怪,微信到底咋就能強(qiáng)占這NFC響應(yīng),現(xiàn)在我終于找到了答案并進(jìn)行了一定深度的挖掘。
對(duì)于這兩種方案,我更加偏向于方案②,因?yàn)榻换ド夏軌蝮w驗(yàn)更好,使用方案①用戶可能還會(huì)有一個(gè)選擇的過(guò)程。

以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。

相關(guān)文章

  • Android仿iOS實(shí)現(xiàn)側(cè)滑返回功能(類似微信)

    Android仿iOS實(shí)現(xiàn)側(cè)滑返回功能(類似微信)

    這篇文章主要為大家詳細(xì)介紹了Android仿iOS實(shí)現(xiàn)側(cè)滑返回功能,類似微信功能,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-12-12
  • Android Activity啟動(dòng)模式之singleTask實(shí)例詳解

    Android Activity啟動(dòng)模式之singleTask實(shí)例詳解

    這篇文章主要介紹了Android Activity啟動(dòng)模式之singleTask,結(jié)合實(shí)例形式較為詳細(xì)的分析了singleTask模式的功能、使用方法與相關(guān)注意事項(xiàng),需要的朋友可以參考下
    2016-01-01
  • Android?NDK開發(fā)(C語(yǔ)言--聯(lián)合體與枚舉)

    Android?NDK開發(fā)(C語(yǔ)言--聯(lián)合體與枚舉)

    這篇文章主要介紹了Android?NDK開發(fā)C語(yǔ)言聯(lián)合體與枚舉,共用體是一種特殊的數(shù)據(jù)類型,允許您在相同的內(nèi)存位置存儲(chǔ)不同的數(shù)據(jù)類型。您可以定義一個(gè)帶有多成員的共用體,但是任何時(shí)候只能有一個(gè)成員帶有值。下面詳細(xì)介紹該內(nèi)容,需要的朋友可以參考一下
    2021-12-12
  • Android SQLite詳解及示例代碼

    Android SQLite詳解及示例代碼

    本文主要講解Android SQLite,這里對(duì)數(shù)據(jù)庫(kù)SQLite 做了詳細(xì)的知識(shí)資料整理,并附示例代碼和實(shí)現(xiàn)效果圖,有需要的小伙伴可以參考下
    2016-08-08
  • android開發(fā)之listView組件用法實(shí)例簡(jiǎn)析

    android開發(fā)之listView組件用法實(shí)例簡(jiǎn)析

    這篇文章主要介紹了android開發(fā)之listView組件用法,結(jié)合實(shí)例形式簡(jiǎn)單分析了listView組件的相關(guān)屬性與使用技巧,需要的朋友可以參考下
    2016-01-01
  • Android封裝常用工具類的示例詳解

    Android封裝常用工具類的示例詳解

    這篇文章主要為大家整理了一些Android封裝的常用工具類,包括日志封裝類、線程封裝類、解壓縮類等,文中的示例代碼講解詳細(xì),有需要的可以參考下
    2024-03-03
  • Android Button點(diǎn)擊事件的四種實(shí)現(xiàn)方法

    Android Button點(diǎn)擊事件的四種實(shí)現(xiàn)方法

    這篇文章主要為大家詳細(xì)介紹了Android Button點(diǎn)擊事件的四種實(shí)現(xiàn)方法,具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-07-07
  • Android仿QQ長(zhǎng)按刪除彈出框功能示例

    Android仿QQ長(zhǎng)按刪除彈出框功能示例

    對(duì)于列表來(lái)說(shuō),如果想操作某個(gè)列表項(xiàng),一般會(huì)采用長(zhǎng)按彈出菜單的形式,默認(rèn)的上下文菜單比較難看,而QQ的上下文菜單就人性化多了,整個(gè)菜單給用戶一種氣泡彈出的感覺,而且會(huì)顯示在手指按下的位置,接下來(lái)通過(guò)本文給大家分享Android仿QQ長(zhǎng)按刪除彈出框功能,一起看看吧
    2017-03-03
  • Android仿微信通訊錄列表側(cè)邊欄效果

    Android仿微信通訊錄列表側(cè)邊欄效果

    這篇文章主要為大家詳細(xì)介紹了Android仿微信通訊錄列表側(cè)邊欄效果,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下
    2017-02-02
  • Android WebView 的簡(jiǎn)單使用

    Android WebView 的簡(jiǎn)單使用

    這篇文章主要介紹了Android WebView 的簡(jiǎn)單使用的相關(guān)資料,這里提供簡(jiǎn)單實(shí)例及實(shí)現(xiàn)代碼,需要的朋友可以參考下
    2016-12-12

最新評(píng)論