2014年6月12日木曜日

NFCは難しいことをしなければ簡単ダ。

APIレベルの指定は最新版を。あまりに低いと呼び出せない。

昔はもっと難しかったのに、今は簡単。Androidが面倒を見てくれる。

まずはテキストデータをやりとりすることを考える。

NDEF_DISCOVEREDを使うことを考える。これを使えればほとんどをAndroid OSが面倒を見てくれる。

TNF_EXTERNAL_TYPEを使えば、ドメイン名+ファイルタイプ(独自定義)が使える。RTD-TEXTを使うなという記述があるが、TEXTが無難である。

以下に例を示す。ここでのmimeは関係無し。下記の strMをapplication-manifestのintent-filterに利用できる。

intentはonCreate()で保存しておく。mIntent。


 

-----------------------------
private void writeTag(Intent intent, String text, String mime) throws IOException, FormatException {
        String action = intent.getAction();
//    if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(action)) {
    // Ndefメッセージの生成 androidが決めているNDEFレコード形式があるので、それを守らないとintent filterと合致しなくなる。
        String strM = "example.com:exampleType";
        NdefRecord mimeRecord = new NdefRecord(
            NdefRecord.TNF_EXTERNAL_TYPE, strM.getBytes(), new byte[0], text.getBytes());

        NdefMessage msg = new NdefMessage(new NdefRecord[] {mimeRecord});
        // Ndefメッセージの書き込み
        Tag tag = intent.getParcelableExtra(NfcAdapter.EXTRA_TAG);
        if (tag != null)
        {
            Ndef ndef = Ndef.get(tag);
            ndef.connect();
            ndef.writeNdefMessage(msg);
            Log.v("NFC", "write " + text);
            ndef.close();
            Toast.makeText(this,  "wrote " + text + "with TNF_EXTERNL_TYPE(" + strM + ")", Toast.LENGTH_LONG).show();
        }
        else
            Toast.makeText(this,  "no NFC", Toast.LENGTH_LONG).show();
    //}
}
------------------------------

               <intent-filter>
            <action android:name="android.nfc.action.NDEF_DISCOVERED" />
            <category android:name="android.intent.category.DEFAULT" />
            <data android:scheme="vnd.android.nfc"
                android:host="ext"
                android:pathPrefix="/example.com:exampleType"/>
            </intent-filter>
--------------------------------

但し、これだけをintent-filterにしておくと空っぽのNFCを読めないので、上手い確認ができない。

そこで、よくある,以下の定義をする。

            <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" />
                <category android:name="android.intent.category.DEFAULT" />
              </intent-filter>
                    <meta-data
                android:name="android.nfc.action.TAG_DISCOVERED"
                android:resource="@xml/nfc_filter" />
                    <meta-data
                android:name="android.nfc.action.TECH_DISCOVERED"
                android:resource="@xml/nfc_filter" />
--------------------------------------

res\xml\nfc_filter.xmlに

__

<?xml version="1.0" encoding="utf-8"?>
<resources xmlns:xliff="urn:oasis:names:tc:xliff:document:1.2">
    <tech-list>
        <tech>android.nfc.tech.IsoDep</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.MifareClassic</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.MifareUltralight</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.Ndef</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NdefFormatable</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcA</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcB</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcBarcode</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcF</tech>
    </tech-list>
    <tech-list>
        <tech>android.nfc.tech.NfcV</tech>
    </tech-list>
</resources>

__

を入れておく。
書込み釦のリスナー
\

btn.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v)
    {
       
        String strMime;
        EditText edit = (EditText)findViewById(R.id.edtMsg);
        String strMsg = edit.getText().toString();
        if (strMsg.length() > 0)
        {
            SpannableStringBuilder sp = (SpannableStringBuilder)edit.getText();
            // ICタグへの書き込み
            try
            {
                writeTag(intent, sp.toString());
            }
            catch (IOException e)
            {
                e.printStackTrace();
            }
            catch (FormatException e)
            {
                e.printStackTrace();
            }
        }
    }
});


以下は読み出し部--------------------


if (NfcAdapter.ACTION_NDEF_DISCOVERED.equals(intent.getAction())) {
    // NDEF検出による呼び出し。
    Parcelable[] raws = intent.getParcelableArrayExtra(NfcAdapter.EXTRA_NDEF_MESSAGES);
    NdefMessage[] msgs = new NdefMessage[raws.length];
    String str = "";
    EditText edit = (EditText)findViewById(R.id.edtMsg);
    String strMsg = edit.getText().toString();
    for (int i=0; i<raws.length; i++) {
        msgs[i] = (NdefMessage)raws[i];
        for (NdefRecord record : msgs[i].getRecords()) {
            str += "Type : " + new String(record.getType()) + "\n";
            str += "TNF : " + record.getTnf() + "\n";
            byte[] payload = record.getPayload();
            if (payload == null)
                break;
            int idx = 0;
            str += "payload = ";
            str += new String(payload);
            if (strMsg.length() == 0)
            {
                strMsg = new String(payload);
                edit.setText(strMsg);
            }
        }
    }
    text.setText(str);


}

\

==================================

0 件のコメント:

コメントを投稿