1590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/*
2590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Copyright (C) 2010 The Android Open Source Project
3590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
4590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Licensed under the Apache License, Version 2.0 (the "License");
5590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * you may not use this file except in compliance with the License.
6590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * You may obtain a copy of the License at
7590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
8590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *      http://www.apache.org/licenses/LICENSE-2.0
9590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly *
10590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * Unless required by applicable law or agreed to in writing, software
11590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * distributed under the License is distributed on an "AS IS" BASIS,
12590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * See the License for the specific language governing permissions and
14590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly * limitations under the License.
15590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */
16590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
174e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonpackage android.nfc.tech;
18590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
196be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.ErrorCodes;
206be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.FormatException;
214e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamiltonimport android.nfc.INfcTag;
226be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.NdefMessage;
236be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.nfc.Tag;
2474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pellyimport android.nfc.TagLostException;
256be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport android.os.Bundle;
26590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pellyimport android.os.RemoteException;
273dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pellyimport android.util.Log;
286be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonimport java.io.IOException;
30590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
31590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly/**
3274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * Provides access to NDEF content and operations on a {@link Tag}.
336be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton *
3474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Acquire a {@link Ndef} object using {@link #get}.
3574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
3674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>NDEF is an NFC Forum data format. The data formats are implemented in
3774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link android.nfc.NdefMessage} and
3874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link android.nfc.NdefRecord}. This class provides methods to
3974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * retrieve and modify the {@link android.nfc.NdefMessage}
4074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * on a tag.
4174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
4274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>There are currently four NFC Forum standardized tag types that can be
4374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * formatted to contain NDEF data.
4474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <ul>
4574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <li>NFC Forum Type 1 Tag ({@link #NFC_FORUM_TYPE_1}), such as the Innovision Topaz
4639cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <li>NFC Forum Type 2 Tag ({@link #NFC_FORUM_TYPE_2}), such as the NXP MIFARE Ultralight
4774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <li>NFC Forum Type 3 Tag ({@link #NFC_FORUM_TYPE_3}), such as Sony Felica
4874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <li>NFC Forum Type 4 Tag ({@link #NFC_FORUM_TYPE_4}), such as NXP MIFARE Desfire
4974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * </ul>
5074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * It is mandatory for all Android devices with NFC to correctly enumerate
5174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * {@link Ndef} on NFC Forum Tag Types 1-4, and implement all NDEF operations
5274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * as defined in this class.
5374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
5465e37ee936e2406e58719584ce30b6aa21792ce0Paul Quei * <p>Some vendors have their own well defined specifications for storing NDEF data
5574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * on tags that do not fall into the above categories. Android devices with NFC
5674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * should enumerate and implement {@link Ndef} under these vendor specifications
5774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * where possible, but it is not mandatory. {@link #getType} returns a String
5874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * describing this specification, for example {@link #MIFARE_CLASSIC} is
5974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <code>com.nxp.ndef.mifareclassic</code>.
6074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
6174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>Android devices that support MIFARE Classic must also correctly
6274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * implement {@link Ndef} on MIFARE Classic tags formatted to NDEF.
6374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly *
6474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * <p>For guaranteed compatibility across all Android devices with NFC, it is
6574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * recommended to use NFC Forum Types 1-4 in new deployments of NFC tags
6674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly * with NDEF payload. Vendor NDEF formats will not work on all Android devices.
676be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton *
6839cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * <p class="note"><strong>Note:</strong> Methods that perform I/O operations
6939cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly * require the {@link android.Manifest.permission#NFC} permission.
70590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly */
716be655c768a82716612c00fdd156254d8dc00f42Jeff Hamiltonpublic final class Ndef extends BasicTagTechnology {
723dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly    private static final String TAG = "NFC";
733dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly
743300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    /** @hide */
753300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    public static final int NDEF_MODE_READ_ONLY = 1;
763300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    /** @hide */
773300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    public static final int NDEF_MODE_READ_WRITE = 2;
783300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    /** @hide */
793300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    public static final int NDEF_MODE_UNKNOWN = 3;
80590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
8172df4ea8300ad345eb256cf43d8dae35eef39ba2Martijn Coenen    /** @hide */
8272df4ea8300ad345eb256cf43d8dae35eef39ba2Martijn Coenen    public static final String EXTRA_NDEF_MSG = "ndefmsg";
8372df4ea8300ad345eb256cf43d8dae35eef39ba2Martijn Coenen
846d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen    /** @hide */
856d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen    public static final String EXTRA_NDEF_MAXLENGTH = "ndefmaxlength";
866d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen
873300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    /** @hide */
883300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    public static final String EXTRA_NDEF_CARDSTATE = "ndefcardstate";
893300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen
90d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen    /** @hide */
91d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen    public static final String EXTRA_NDEF_TYPE = "ndeftype";
92d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen
93f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    /** @hide */
94f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final int TYPE_OTHER = -1;
95f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    /** @hide */
96f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final int TYPE_1 = 1;
97f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    /** @hide */
98f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final int TYPE_2 = 2;
99f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    /** @hide */
100f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final int TYPE_3 = 3;
101f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    /** @hide */
102f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final int TYPE_4 = 4;
103f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    /** @hide */
104f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final int TYPE_MIFARE_CLASSIC = 101;
1055644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton    /** @hide */
1065644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton    public static final int TYPE_ICODE_SLI = 102;
107f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly
108f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    /** @hide */
109f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final String UNKNOWN = "android.ndef.unknown";
110f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly
11174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /** NFC Forum Tag Type 1 */
112f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final String NFC_FORUM_TYPE_1 = "org.nfcforum.ndef.type1";
11374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /** NFC Forum Tag Type 2 */
114f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final String NFC_FORUM_TYPE_2 = "org.nfcforum.ndef.type2";
11574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /** NFC Forum Tag Type 4 */
116f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final String NFC_FORUM_TYPE_3 = "org.nfcforum.ndef.type3";
11774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /** NFC Forum Tag Type 4 */
118f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final String NFC_FORUM_TYPE_4 = "org.nfcforum.ndef.type4";
11974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly    /** NDEF on MIFARE Classic */
120f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public static final String MIFARE_CLASSIC = "com.nxp.ndef.mifareclassic";
1215644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton    /**
1225644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton     * NDEF on iCODE SLI
1235644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton     * @hide
1245644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton     */
1255644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton    public static final String ICODE_SLI = "com.nxp.ndef.icodesli";
126d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen
1273300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    private final int mMaxNdefSize;
1283300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    private final int mCardState;
129e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen    private final NdefMessage mNdefMsg;
130d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen    private final int mNdefType;
1316d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen
132590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
13374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Get an instance of {@link Ndef} for the given tag.
13474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
13574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Returns null if {@link Ndef} was not enumerated in {@link Tag#getTechList}.
13674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * This indicates the tag is not NDEF formatted, or that this tag
13774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * is NDEF formatted but under a vendor specification that this Android
13874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * device does not implement.
1394e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     *
14074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
14174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
1420bec15ebed8b8639076cba184af3235e17f48718Martijn Coenen     * @param tag an NDEF compatible tag
1430bec15ebed8b8639076cba184af3235e17f48718Martijn Coenen     * @return Ndef object
1444e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton     */
1454e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public static Ndef get(Tag tag) {
1464e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        if (!tag.hasTech(TagTechnology.NDEF)) return null;
1474e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        try {
1484e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return new Ndef(tag);
1494e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        } catch (RemoteException e) {
1504e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            return null;
1514e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        }
1524e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    }
1534e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton
1544e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    /**
155590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * Internal constructor, to be used by NfcAdapter
156590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     * @hide
157590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
1584e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton    public Ndef(Tag tag) throws RemoteException {
1594e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        super(tag, TagTechnology.NDEF);
1604e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton        Bundle extras = tag.getTechExtras(TagTechnology.NDEF);
1616d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen        if (extras != null) {
1623300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen            mMaxNdefSize = extras.getInt(EXTRA_NDEF_MAXLENGTH);
1633300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen            mCardState = extras.getInt(EXTRA_NDEF_CARDSTATE);
164e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen            mNdefMsg = extras.getParcelable(EXTRA_NDEF_MSG);
165d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen            mNdefType = extras.getInt(EXTRA_NDEF_TYPE);
1666d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen        } else {
1673300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen            throw new NullPointerException("NDEF tech extras are null.");
1686d9fc7e1efa9e99bdab366fc5d579c139fd04e71Martijn Coenen        }
1693300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen
1706be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    }
171a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau
1726be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    /**
17374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Get the {@link NdefMessage} that was read from the tag at discovery time.
17474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
17574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>If the NDEF Message is modified by an I/O operation then it
17674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * will not be updated here, this function only returns what was discovered
17774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * when the tag entered the field.
178a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     * <p>Note that this method may return null if the tag was in the
179a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     * INITIALIZED state as defined by NFC Forum, as in this state the
180a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     * tag is formatted to support NDEF but does not contain a message yet.
18174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
182a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     * @return NDEF Message read from the tag at discovery time, can be null
1836be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     */
184e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen    public NdefMessage getCachedNdefMessage() {
185e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen        return mNdefMsg;
186a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau    }
187a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau
188a926540d5455a973dd8ca19c00c108620d9c68c2Sylvain Fonteneau    /**
18974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Get the NDEF tag type.
19074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
191ddbb2c997b8462d7242b50ea1689a53122d4fce4Nick Pelly     * <p>Returns one of {@link #NFC_FORUM_TYPE_1}, {@link #NFC_FORUM_TYPE_2},
192ddbb2c997b8462d7242b50ea1689a53122d4fce4Nick Pelly     * {@link #NFC_FORUM_TYPE_3}, {@link #NFC_FORUM_TYPE_4},
19374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * {@link #MIFARE_CLASSIC} or another NDEF tag type that has not yet been
19474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * formalized in this Android API.
19574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
19674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
19774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
19874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return a string representing the NDEF tag type
199d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen     */
200f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public String getType() {
201f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly        switch (mNdefType) {
202f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly            case TYPE_1:
203f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly                return NFC_FORUM_TYPE_1;
204f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly            case TYPE_2:
205f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly                return NFC_FORUM_TYPE_2;
206f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly            case TYPE_3:
207f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly                return NFC_FORUM_TYPE_3;
208f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly            case TYPE_4:
209f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly                return NFC_FORUM_TYPE_4;
210f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly            case TYPE_MIFARE_CLASSIC:
211f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly                return MIFARE_CLASSIC;
2125644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton            case TYPE_ICODE_SLI:
2135644d0e18ad847b66a8cb4f185cb28edebe75d88Jeff Hamilton                return ICODE_SLI;
214f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly            default:
215f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly                return UNKNOWN;
216f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly        }
217d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen    }
218d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen
219d27ebf1e698c4e6929cb635768031a2e25b18acdMartijn Coenen    /**
22074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Get the maximum NDEF message size in bytes.
22174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
22274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
22374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
22474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return size in bytes
2256be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton     */
2263300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    public int getMaxSize() {
2273300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen        return mMaxNdefSize;
2286be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    }
2296be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton
2306be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    /**
23174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Determine if the tag is writable.
23274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
23374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>NFC Forum tags can be in read-only or read-write states.
23474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
23574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
23674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
237e47150e933e6f610546f57183477f324566e521eNick Pelly     * <p>Requires {@link android.Manifest.permission#NFC} permission.
23874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
23974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return true if the tag is writable
240590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
2413300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen    public boolean isWritable() {
2423300e4c3ea2f2317532ded6f9e79d6ad9e038679Martijn Coenen        return (mCardState == NDEF_MODE_READ_WRITE);
243590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
244590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
245590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
24674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Read the current {@link android.nfc.NdefMessage} on this tag.
24774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
24874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>This always reads the current NDEF Message stored on the tag.
24974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
250a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     * <p>Note that this method may return null if the tag was in the
251a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     * INITIALIZED state as defined by NFC Forum, as in that state the
252a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     * tag is formatted to support NDEF but does not contain a message yet.
253a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     *
25474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>This is an I/O operation and will block until complete. It must
25574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * not be called from the main application thread. A blocked call will be canceled with
25674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * {@link IOException} if {@link #close} is called from another thread.
25774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
2586c65344fcf5aa1499dafe1cad1d1ba5c66293776Martijn Coenen     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
2596c65344fcf5aa1499dafe1cad1d1ba5c66293776Martijn Coenen     *
260a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen     * @return the NDEF Message, can be null
26174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws TagLostException if the tag leaves the field
26274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws IOException if there is an I/O failure, or the operation is canceled
26374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws FormatException if the NDEF Message on the tag is malformed
264e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen     */
265e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen    public NdefMessage getNdefMessage() throws IOException, FormatException {
2664049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        checkConnected();
2674049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
268e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen        try {
2694e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            INfcTag tagService = mTag.getTagService();
27023fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            if (tagService == null) {
27123fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen                throw new IOException("Mock tags don't support this operation.");
27223fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            }
273e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen            int serviceHandle = mTag.getServiceHandle();
2744e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            if (tagService.isNdef(serviceHandle)) {
2754e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton                NdefMessage msg = tagService.ndefRead(serviceHandle);
276a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen                if (msg == null && !tagService.isPresent(serviceHandle)) {
277a032783241cbbed47ed05df32c56298ee0f9902bMartijn Coenen                    throw new TagLostException();
278e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen                }
279e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen                return msg;
280266e0a387123773538d7768a63d37793500169a1Mathias Jeppsson            } else if (!tagService.isPresent(serviceHandle)) {
281266e0a387123773538d7768a63d37793500169a1Mathias Jeppsson                throw new TagLostException();
282e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen            } else {
283e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen                return null;
284e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen            }
285e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen        } catch (RemoteException e) {
2863dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly            Log.e(TAG, "NFC service dead", e);
287e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen            return null;
288e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen        }
289e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen    }
2903ce86481cbde92e2cb6fe3a46cbedd8b2a5c4b48Jeff Hamilton
291e3f6336bcffc250da90ec864bccfa73ad1d016b9Martijn Coenen    /**
29274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Overwrite the {@link NdefMessage} on this tag.
29374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
29474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>This is an I/O operation and will block until complete. It must
29574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * not be called from the main application thread. A blocked call will be canceled with
29674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * {@link IOException} if {@link #close} is called from another thread.
29774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
29839cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
29939cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly     *
30074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @param msg the NDEF Message to write, must not be null
30174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws TagLostException if the tag leaves the field
30274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws IOException if there is an I/O failure, or the operation is canceled
30374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws FormatException if the NDEF Message to write is malformed
304590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
3056be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton    public void writeNdefMessage(NdefMessage msg) throws IOException, FormatException {
3064049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        checkConnected();
3074049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
308590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        try {
3094e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            INfcTag tagService = mTag.getTagService();
31023fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            if (tagService == null) {
31123fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen                throw new IOException("Mock tags don't support this operation.");
31223fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            }
31301d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen            int serviceHandle = mTag.getServiceHandle();
3144e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            if (tagService.isNdef(serviceHandle)) {
3154e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton                int errorCode = tagService.ndefWrite(serviceHandle, msg);
31601d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                switch (errorCode) {
31701d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                    case ErrorCodes.SUCCESS:
31801d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                        break;
31901d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                    case ErrorCodes.ERROR_IO:
32001d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                        throw new IOException();
32101d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                    case ErrorCodes.ERROR_INVALID_PARAM:
32201d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                        throw new FormatException();
32301d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                    default:
32401d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                        // Should not happen
32501d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                        throw new IOException();
32601d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                }
32701d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen            }
32801d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen            else {
32901d159aa2c6303089269258f3ae047e74df9e2a9Martijn Coenen                throw new IOException("Tag is not ndef");
330590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            }
331590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        } catch (RemoteException e) {
3323dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly            Log.e(TAG, "NFC service dead", e);
333590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
334590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
335590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly
336590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    /**
33774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Indicates whether a tag can be made read-only with {@link #makeReadOnly()}.
33874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
33974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>Does not cause any RF activity and does not block.
34074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
34174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return true if it is possible to make this tag read-only
34225be53652167300183282d170a00a6df576523f5Martijn Coenen     */
343f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public boolean canMakeReadOnly() {
344faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen        INfcTag tagService = mTag.getTagService();
34523fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen        if (tagService == null) {
34623fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            return false;
34723fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen        }
348faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen        try {
349faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen            return tagService.canMakeReadOnly(mNdefType);
350faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen        } catch (RemoteException e) {
351faca12adc62d148505fadfd286e6a2752c197fa0Martijn Coenen            Log.e(TAG, "NFC service dead", e);
35225be53652167300183282d170a00a6df576523f5Martijn Coenen            return false;
35325be53652167300183282d170a00a6df576523f5Martijn Coenen        }
35425be53652167300183282d170a00a6df576523f5Martijn Coenen    }
35525be53652167300183282d170a00a6df576523f5Martijn Coenen
35625be53652167300183282d170a00a6df576523f5Martijn Coenen    /**
35774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * Make a tag read-only.
35874fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
35974fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>This sets the CC field to indicate the tag is read-only,
36074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * and where possible permanently sets the lock bits to prevent
36174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * any further modification of the memory.
36274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>This is a one-way process and cannot be reverted!
36374fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
36474fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * <p>This is an I/O operation and will block until complete. It must
36574fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * not be called from the main application thread. A blocked call will be canceled with
36674fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * {@link IOException} if {@link #close} is called from another thread.
36774fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     *
36839cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly     * <p class="note">Requires the {@link android.Manifest.permission#NFC} permission.
36939cf3a445e507f219ecc8a476f6038f095d9d520Nick Pelly     *
37074fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @return true on success, false if it is not possible to make this tag read-only
37174fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws TagLostException if the tag leaves the field
37274fe6c6b245ebe7d3b3d96962c32980d88dca4f5Nick Pelly     * @throws IOException if there is an I/O failure, or the operation is canceled
373590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly     */
374f003e26df96067b4b136f0859012cb7ec3ed930fNick Pelly    public boolean makeReadOnly() throws IOException {
3754049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen        checkConnected();
3764049f9d00a86f848d42d2429068496b31a6795adMartijn Coenen
377590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        try {
3784e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            INfcTag tagService = mTag.getTagService();
37923fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            if (tagService == null) {
38023fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen                return false;
38123fc93a7c1e340e79642d3d0bf4b4658c8645c8eMartijn Coenen            }
3824e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton            if (tagService.isNdef(mTag.getServiceHandle())) {
3834e21e1d21a877cce4db5ec8c5786604cc10f2d7eJeff Hamilton                int errorCode = tagService.ndefMakeReadOnly(mTag.getServiceHandle());
38407e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                switch (errorCode) {
38507e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                    case ErrorCodes.SUCCESS:
38607e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                        return true;
38707e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                    case ErrorCodes.ERROR_IO:
38807e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                        throw new IOException();
38907e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                    case ErrorCodes.ERROR_INVALID_PARAM:
39007e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                        return false;
39107e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                    default:
39207e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                        // Should not happen
39307e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                        throw new IOException();
39407e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen                }
39507e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen           }
39607e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen           else {
39707e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen               throw new IOException("Tag is not ndef");
39807e6f616d122496342a5bae51323bb218d88f7f2Martijn Coenen           }
399590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        } catch (RemoteException e) {
4003dd6c458530476eccb33bc05c9c9cd83823bcf8dNick Pelly            Log.e(TAG, "NFC service dead", e);
401590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly            return false;
402590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly        }
403590b73bc5b8e5f7b59bff1d9264a52388a5162e6Nick Pelly    }
4046be655c768a82716612c00fdd156254d8dc00f42Jeff Hamilton}
405