天天看點

Android裝置與nfc裝置建立連接配接 寫入和讀取一次掃描完成

最近在做Android掃描nfc裝置的項目  發現隻有一次掃描讀取資料 一次掃描寫入資料的情況  而沒有一次掃描寫入資料之後直接讀取出來的需求  在這裡記錄一下

1.擷取nfc裝置支援的類型   有Nfca,Nfcv,Ndef,Isodep,MifareUltralight等  我們用戶端需要知道nfc晶片支援的類型然後去做讀寫操作

以ndef為例下面為示例代碼
           
@Override
protected void onNewIntent(Intent intent) {
    super.onNewIntent(intent);
    // 為了保證getIntent擷取的是最新的
    setIntent(intent);
    if (startScan) {
        //1.擷取Tag對象
        String action = intent.getAction();
        if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) ||
                NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) ||
                NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
            tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
            boolean result = writeTag(tag, intent);
            Log.e("yanwei", "寫标簽标簽成功..............................." + result);
        }
    }
}
           
/**
 * 寫資料
 *
 * @param tag 标簽
 * @return
 */
public boolean writeTag(Tag tag, Intent intent) {
    String str[] = tag.getTechList();
    if (str != null) {
        if (str.length > 0) {
            boolean supportNdef = false;
            for (int i = 0; i < str.length; i++) {
                if ("android.nfc.tech.Ndef".equals(str[i])) {
                    supportNdef = true;
                }
                Log.e("yanwei", "detectedTag = " + str[i]);
            }
            if (!supportNdef) {
                Log.e("yanwei", "不支援ndef");
                Toast.makeText(mContext, "晶片不支援ndef格式", Toast.LENGTH_SHORT).show();
            } else {
            }
        }
    }
    NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{createRecord()});
    try {
        Ndef ndef = Ndef.get(tag);
        if (ndef != null) {
            int size = ndefMessage.toByteArray().length;
            if (size > ndef.getMaxSize()) {
                Log.e("yanwei ", "寫不下  --  size = " + size + " , maxSize = " + ndef.getMaxSize());
            }
            ndef.connect();
            if (!ndef.isWritable()) {
                Log.e("yanwei ", "标簽不可寫入");
                return false;
            }
            ndef.writeNdefMessage(ndefMessage);

            Message msg = new Message();
            msg.obj = intent;
            mHandler.sendMessageDelayed(msg, 350);
            return true;
        } else {
            NdefFormatable ndefFormatable = NdefFormatable.get(tag);
            if (ndefFormatable != null) {
                ndefFormatable.connect();
                ndefFormatable.format(ndefMessage);
                Log.e("yanwei", "type = " + "ndefFormatable");
                return true;
            } else {
                Log.e("yanwei", "ndefFormatable不支援");
                return false;
            }
        }
    } catch (Exception e) {
        startScan = false;
        popWindow.dismiss();
        Toast.makeText(mContext, "寫入裝置資料失敗", Toast.LENGTH_LONG).show();
        Log.e("yanwei", "Exception = " + e.getMessage() + " ,, " + e.getLocalizedMessage() + " ,, ");
    }
    return false;
}
           
private Handler mHandler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        super.handleMessage(msg);
        Log.e("yanwei", "3.5ms");
        Intent intent = (Intent) msg.obj;
        Parcelable[] rawMessage = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
        NdefMessage[] ndefMessages = null;
        // 判斷是哪種類型的資料 預設為NDEF格式
        if (rawMessage != null) {
            ndefMessages = new NdefMessage[rawMessage.length];
            for (int i = 0; i < rawMessage.length; i++) {
                ndefMessages[i] = (NdefMessage) rawMessage[i];
            }
        }
        NdefMessage ndefMessage = null;
        if (ndefMessages.length > 0) {
            ndefMessage = ndefMessages[0];
        }
        if (ndefMessage != null) {
            NdefRecord record = ndefMessage.getRecords()[0];
            parseTextRecord(record);
        } else {
            Log.e("yanwei", "ndefMessage == null");
            startScan = false;
            popWindow.dismiss();
            Toast.makeText(mContext, "讀取裝置資料失敗", Toast.LENGTH_LONG).show();
        }
    }
};
           

實際上我們通過onNewIntent方法回調接收到nfc相關的intent之後  Android裝置就與nfc晶片建立了連結  不管你用哪種格式的資料(nfca,nfcv,ndef....)

他們都有一個建立連結的方法 例如:ndef.connect();  建立連結之後 調用寫入的方法開始寫入  本例為350ms之後去intent中讀取資料,也可以通過msg傳值ndef來進行讀取

msg.obg = ndef;   Ndef ndef = (Ndef)msg.obg; NdefMessage message = ndef.getNdefMessage();這樣讀取  具體看你自己的需求  這樣就可以寫入資料之後 馬上讀取出資料了

而不用再次掃描裝置   希望能幫到你

經過一番修改   發現了很多需要優化的地方

1.ndef讀寫資料的時候 需要在子線程中操作

Android裝置與nfc裝置建立連接配接 寫入和讀取一次掃描完成
Android裝置與nfc裝置建立連接配接 寫入和讀取一次掃描完成

2.在寫入資料 350ms後(這個延時是用來給硬體接收我們寫入資料之後操作的時長),判斷ndef的連結狀态,ndef.isConnect();如果傳回false

說明目前連結已經中斷,繼續調用讀取方法會報android.nfc.TagLostException異常 Android系統會預設開啟第二次掃描

@Override
    protected void onNewIntent(Intent intent) {
        super.onNewIntent(intent);
        //1.擷取Tag對象
        String action = intent.getAction();
        Log.e(TAG, "onNewIntent = " + action);
        if (startScan) {
            mIntent = intent;
            startScan = false;
            if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action) ||
                    NfcAdapter.ACTION_TECH_DISCOVERED.equals(action) ||
                    NfcAdapter.ACTION_TAG_DISCOVERED.equals(action)) {
                tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
                boolean result = writeTag();
                Log.e(TAG, "寫标簽标簽成功..............................." + result);
            }
        }
    }
           
/**
     * 寫資料
     *
     * @return
     */
    public boolean writeTag() {
        String str[] = tag.getTechList();
        if (str != null) {
            if (str.length > 0) {
                boolean supportNdef = false;
                for (int i = 0; i < str.length; i++) {
                    if ("android.nfc.tech.Ndef".equals(str[i])) {
                        supportNdef = true;
                    }
                    Log.e(TAG, "detectedTag = " + str[i]);
                }
                if (!supportNdef) {
                    Log.e(TAG, "不支援ndef");
                    Toast.makeText(mContext, "晶片不支援ndef格式", Toast.LENGTH_SHORT).show();
                } else {
                }
            }
        }
        final NdefMessage ndefMessage = new NdefMessage(new NdefRecord[]{createRecord()});
        try {
            final Ndef ndef = Ndef.get(tag);
            if (ndef != null) {
                int size = ndefMessage.toByteArray().length;
                if (size > ndef.getMaxSize()) {
                    Log.e(TAG, "寫不下  --  size = " + size + " , maxSize = " + ndef.getMaxSize());
                }
                ndef.connect();
                if (!ndef.isWritable()) {
                    Log.e(TAG, "标簽不可寫入");
                    return false;
                }

                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        try {
                            ndef.writeNdefMessage(ndefMessage);
                            Thread.sleep(350);

                            boolean isConnect = ndef.isConnected();
                            Log.e(TAG, "isConnect = " + isConnect);

                            NdefMessage ndefMsg = ndef.getNdefMessage();
                            Message msg = new Message();
                            msg.obj = ndefMsg;
                            msg.what = 0;
                            mHandler.sendMessage(msg);
                            ndef.close();
                        } catch (FormatException e) {
                            e.printStackTrace();
                            Log.e(TAG, "FormatException = " + e);
                            mHandler.sendEmptyMessage(1);
                            return;
                        } catch (IOException e) {
                            e.printStackTrace();
                            Log.e(TAG, "IOException = " + e);
                            mHandler.sendEmptyMessage(1);
                            return;
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                            Log.e(TAG, "InterruptedException = " + e);
                            mHandler.sendEmptyMessage(1);
                            return;
                        }
                    }
                }).start();


                return true;
            } else {
                NdefFormatable ndefFormatable = NdefFormatable.get(tag);
                if (ndefFormatable != null) {
                    ndefFormatable.connect();
                    ndefFormatable.format(ndefMessage);
                    Log.e(TAG, "type = " + "ndefFormatable");
                    return true;
                } else {
                    Log.e(TAG, "ndefFormatable不支援");
                    return false;
                }
            }
        } catch (Exception e) {
            startScan = false;
            popWindow.dismiss();
            Toast.makeText(mContext, "寫入裝置資料失敗", Toast.LENGTH_LONG).show();
            Log.e(TAG, "Exception = " + e.getMessage() + " ,, " + e.getLocalizedMessage() + " ,, ");
        }
        return false;
    }
           
private Handler mHandler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            Log.e(TAG, "350ms");
            if (msg.what == 0) {
                NdefMessage ndefMessage = (NdefMessage) msg.obj;
                if (ndefMessage != null) {
                    NdefRecord record = ndefMessage.getRecords()[0];
                    parseTextRecord(record);
                } else {
                    Log.e(TAG, "ndefMessage == null");
                    startScan = false;
                    popWindow.dismiss();
                    Toast.makeText(mContext, "讀取裝置資料失敗", Toast.LENGTH_LONG).show();
                }
            } else {
                startScan = false;
                popWindow.dismiss();
                Toast.makeText(mContext, "通訊失敗", Toast.LENGTH_LONG).show();
            }
        }
    };