NdefFormatable.java revision f003e26df96067b4b136f0859012cb7ec3ed930f
1/*
2 * Copyright (C) 2010 The Android Open Source Project
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 *      http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package android.nfc.tech;
18
19import android.nfc.ErrorCodes;
20import android.nfc.FormatException;
21import android.nfc.INfcTag;
22import android.nfc.NdefMessage;
23import android.nfc.NfcAdapter;
24import android.nfc.Tag;
25import android.os.RemoteException;
26import android.util.Log;
27
28import java.io.IOException;
29
30/**
31 * An interface to a {@link Tag} allowing to format the tag as NDEF.
32 *
33 * <p>You can acquire this kind of connection with {@link #get}.
34 *
35 * <p class="note"><strong>Note:</strong>
36 * Use of this class requires the {@link android.Manifest.permission#NFC}
37 * permission.
38 */
39public final class NdefFormatable extends BasicTagTechnology {
40    private static final String TAG = "NFC";
41
42    /**
43     * Returns an instance of this tech for the given tag. If the tag doesn't support
44     * this tech type null is returned.
45     *
46     * @param tag The tag to get the tech from
47     */
48    public static NdefFormatable get(Tag tag) {
49        if (!tag.hasTech(TagTechnology.NDEF_FORMATABLE)) return null;
50        try {
51            return new NdefFormatable(tag);
52        } catch (RemoteException e) {
53            return null;
54        }
55    }
56
57    /**
58     * Internal constructor, to be used by NfcAdapter
59     * @hide
60     */
61    public NdefFormatable(Tag tag) throws RemoteException {
62        super(tag, TagTechnology.NDEF_FORMATABLE);
63    }
64
65    /**
66     * Formats a tag as NDEF, if possible. You may supply a first
67     * NdefMessage to be written on the tag.
68     * <p>Either all steps succeed, or an IOException is thrown if any one step
69     * fails.
70     */
71    public void format(NdefMessage firstMessage) throws IOException, FormatException {
72        format(firstMessage, false);
73    }
74
75    /**
76     * Formats a tag as NDEF, if possible. You may supply a first
77     * NdefMessage to be written on the tag.
78     * <p>Either all steps succeed, or an IOException is thrown if any one step
79     * fails.
80     */
81    public void formatReadOnly(NdefMessage firstMessage) throws IOException, FormatException {
82        format(firstMessage, true);
83    }
84
85    /*package*/ void format(NdefMessage firstMessage, boolean makeReadOnly) throws IOException,
86            FormatException {
87        checkConnected();
88
89        try {
90            int serviceHandle = mTag.getServiceHandle();
91            INfcTag tagService = mTag.getTagService();
92            int errorCode = tagService.formatNdef(serviceHandle, MifareClassic.KEY_DEFAULT);
93            switch (errorCode) {
94                case ErrorCodes.SUCCESS:
95                    break;
96                case ErrorCodes.ERROR_IO:
97                    throw new IOException();
98                case ErrorCodes.ERROR_INVALID_PARAM:
99                    throw new FormatException();
100                default:
101                    // Should not happen
102                    throw new IOException();
103            }
104            // Now check and see if the format worked
105            if (tagService.isNdef(serviceHandle)) {
106                errorCode = tagService.ndefWrite(serviceHandle, firstMessage);
107                switch (errorCode) {
108                    case ErrorCodes.SUCCESS:
109                        break;
110                    case ErrorCodes.ERROR_IO:
111                        throw new IOException();
112                    case ErrorCodes.ERROR_INVALID_PARAM:
113                        throw new FormatException();
114                    default:
115                        // Should not happen
116                        throw new IOException();
117                }
118            } else {
119                throw new IOException();
120            }
121            // optionally make read-only
122            if (makeReadOnly) {
123                errorCode = tagService.ndefMakeReadOnly(serviceHandle);
124                switch (errorCode) {
125                    case ErrorCodes.SUCCESS:
126                        break;
127                    case ErrorCodes.ERROR_IO:
128                        throw new IOException();
129                    case ErrorCodes.ERROR_INVALID_PARAM:
130                        throw new IOException();
131                    default:
132                        // Should not happen
133                        throw new IOException();
134                }
135            }
136        } catch (RemoteException e) {
137            Log.e(TAG, "NFC service dead", e);
138        }
139    }
140}
141