OLD | NEW |
---|---|
(Empty) | |
1 // Copyright 2016 The Chromium Authors. All rights reserved. | |
2 // Use of this source code is governed by a BSD-style license that can be | |
3 // found in the LICENSE file. | |
4 | |
5 package org.chromium.device.nfc; | |
6 | |
7 import android.Manifest; | |
8 import android.annotation.TargetApi; | |
9 import android.app.Activity; | |
10 import android.content.Context; | |
11 import android.content.pm.PackageManager; | |
12 import android.nfc.FormatException; | |
13 import android.nfc.NdefMessage; | |
14 import android.nfc.NdefRecord; | |
15 import android.nfc.NfcAdapter; | |
16 import android.nfc.NfcAdapter.ReaderCallback; | |
17 import android.nfc.NfcManager; | |
18 import android.nfc.Tag; | |
19 import android.nfc.TagLostException; | |
20 import android.nfc.tech.Ndef; | |
21 import android.nfc.tech.NdefFormatable; | |
22 import android.nfc.tech.TagTechnology; | |
23 import android.os.Build; | |
24 import android.os.Process; | |
25 import android.support.annotation.Nullable; | |
26 | |
27 import org.chromium.base.ApplicationStatus; | |
28 import org.chromium.base.Log; | |
29 import org.chromium.mojo.bindings.Callbacks; | |
30 import org.chromium.mojo.system.MojoException; | |
31 import org.chromium.mojom.device.Nfc; | |
32 import org.chromium.mojom.device.NfcClient; | |
33 import org.chromium.mojom.device.NfcError; | |
34 import org.chromium.mojom.device.NfcErrorType; | |
35 import org.chromium.mojom.device.NfcMessage; | |
36 import org.chromium.mojom.device.NfcPushOptions; | |
37 import org.chromium.mojom.device.NfcPushTarget; | |
38 import org.chromium.mojom.device.NfcRecord; | |
39 import org.chromium.mojom.device.NfcRecordType; | |
40 import org.chromium.mojom.device.NfcWatchOptions; | |
41 | |
42 import java.io.IOException; | |
43 import java.io.UnsupportedEncodingException; | |
44 import java.util.ArrayList; | |
45 import java.util.List; | |
46 | |
47 /** | |
48 * Android implementation of the NFC mojo service defined in | |
49 * device/nfc/nfc.mojom. | |
50 */ | |
51 public class NfcImpl implements Nfc { | |
52 private static final String TAG = "NfcImpl"; | |
53 private static final String DOMAIN = "w3.org"; | |
54 private static final String TYPE = "webnfc"; | |
55 private static final String TEXT_MIME = "text/plain"; | |
56 private static final String CHARSET_UTF8 = ";charset=UTF-8"; | |
57 private static final String CHARSET_UTF16 = ";charset=UTF-16"; | |
58 | |
59 /** | |
60 * Used to get instance of NFC adapter, @see android.nfc.NfcManager | |
61 */ | |
62 private final NfcManager mNfcManager; | |
63 | |
64 /** | |
65 * NFC adapter. @see android.nfc.NfcAdapter | |
66 */ | |
67 private final NfcAdapter mNfcAdapter; | |
68 | |
69 /** | |
70 * Context that is pasesed to NFC mojo service. Used to check permissions | |
Ted C
2016/04/28 17:27:22
line wrapping for comments should be 100 in java
shalamov
2016/05/11 14:09:57
Done.
| |
71 * and get Android NFC system service. | |
72 */ | |
73 private final Context mContext; | |
74 | |
75 /** | |
76 * Activity object that is requred to enable / disable NFC reader mode opera tions. | |
77 */ | |
78 private final Activity mActivity; | |
79 | |
80 /** | |
81 * Flag that indicates whether NFC permission is granted. | |
82 */ | |
83 private final boolean mHasPermission; | |
84 | |
85 /** | |
86 * Implementation of android.nfc.NfcAdapter.ReaderCallback. @see ReaderCallb ackHandler | |
87 */ | |
88 private ReaderCallbackHandler mReaderCallbackHandler; | |
89 | |
90 /** | |
91 * Object that contains data that was passed to method | |
92 * #push(NfcMessage message, NfcPushOptions options, PushResponse callback) | |
93 * @see PendingPushOperation | |
94 */ | |
95 private PendingPushOperation mPendingPushOperation; | |
96 | |
97 /** | |
98 * Utility that provides I/O operations for a Tag. Created on demand when | |
99 * Tag is found. @see NfcTagWriter | |
100 */ | |
101 private NfcTagWriter mTagWriter; | |
102 | |
103 public NfcImpl(Context context) { | |
104 mContext = context; | |
105 int permission = | |
106 context.checkPermission(Manifest.permission.NFC, Process.myPid() , Process.myUid()); | |
107 mHasPermission = permission == PackageManager.PERMISSION_GRANTED; | |
108 if (mHasPermission) { | |
109 mActivity = ApplicationStatus.getLastTrackedFocusedActivity(); | |
Ted C
2016/04/28 17:27:22
we should really avoid using this call if at all p
shalamov
2016/05/11 14:09:57
Done.
| |
110 mNfcManager = (NfcManager) mContext.getSystemService(Context.NFC_SER VICE); | |
111 if (mNfcManager != null) { | |
112 mNfcAdapter = mNfcManager.getDefaultAdapter(); | |
113 } else { | |
114 Log.w(TAG, "NFC is not supported."); | |
115 mNfcAdapter = null; | |
116 } | |
117 } else { | |
118 Log.w(TAG, "NFC operations are not permitted."); | |
119 mNfcAdapter = null; | |
120 mNfcManager = null; | |
121 mActivity = null; | |
122 } | |
123 } | |
124 | |
125 /** | |
126 * Sets NfcClient. NfcClient interface is used to notify mojo NFC service | |
127 * client when NFC device is in proximity and has NfcMessage that matches | |
128 * NfcWatchOptions criteria. | |
129 * @see Nfc#watch(NfcWatchOptions options, WatchResponse callback) | |
130 * | |
131 * @param client @see NfcClient | |
132 */ | |
133 @Override | |
134 public void setClient(NfcClient client) { | |
135 // todo(shalamov): Should be implemented when watch() is implemented. | |
Ted C
2016/04/28 17:27:21
nit, TODO should be capitalized
shalamov
2016/05/11 14:09:57
Done.
| |
136 } | |
137 | |
138 /** | |
139 * Pushes NfcMessage to Tag or Peer, whenever NFC device is in proximity. | |
140 * At the moment, only passive NFC devices are supported (NfcPushTarget.TAG) . | |
141 * | |
142 * @param message that should be pushed to NFC device. | |
143 * @param options that contain information about timeout and target device t ype. | |
144 * @param callback that is used to notify when push operation is completed. | |
145 */ | |
146 @Override | |
147 public void push(NfcMessage message, NfcPushOptions options, PushResponse ca llback) { | |
148 if (!checkIfReady(callback)) return; | |
149 | |
150 if (options.target == NfcPushTarget.PEER) { | |
151 callback.call(createError(NfcErrorType.NOT_SUPPORTED)); | |
152 return; | |
153 } | |
154 | |
155 // If previous pending push operation is not completed, subsequent call | |
156 // should cancel pending operation. | |
157 if (mPendingPushOperation != null) { | |
158 mPendingPushOperation.complete(createError(NfcErrorType.OPERATION_CA NCELLED)); | |
159 } | |
160 | |
161 mPendingPushOperation = new PendingPushOperation(message, options, callb ack); | |
162 enableReaderMode(); | |
Ted C
2016/04/28 17:27:22
as far as I can tell, push only works if Android i
| |
163 processPendingPushOperation(); | |
164 } | |
165 | |
166 /** | |
167 * Cancels pending push operation. | |
168 * At the moment, only passive NFC devices are supported (NfcPushTarget.TAG) . | |
169 * | |
170 * @param target @see NfcPushTarget | |
171 * @param callback that is used to notify caller when cancelPush() is comple ted. | |
172 */ | |
173 @Override | |
174 public void cancelPush(int target, CancelPushResponse callback) { | |
175 if (!checkIfReady(callback)) return; | |
176 | |
177 if (target == NfcPushTarget.PEER) { | |
178 callback.call(createError(NfcErrorType.NOT_SUPPORTED)); | |
179 return; | |
180 } | |
181 | |
182 if (mPendingPushOperation != null) { | |
183 mPendingPushOperation.complete(createError(NfcErrorType.OPERATION_CA NCELLED)); | |
184 mPendingPushOperation = null; | |
185 callback.call(null); | |
186 disableReaderMode(); | |
187 } else { | |
188 callback.call(createError(NfcErrorType.NOT_FOUND)); | |
189 } | |
190 } | |
191 | |
192 /** | |
193 * Watch method allows to set filtering criteria for NfcMessages that are | |
194 * found when NFC device is within proximity. On success, watch ID is | |
195 * returned to caller through WatchResponse callback. When NfcMessage that | |
196 * matches NfcWatchOptions is found, it is passed to NfcClient interface | |
197 * together with corresponding watch ID. | |
198 * @see NfcClient#onWatch(int id, NfcMessage message) | |
199 * | |
200 * @param options used to filter NfcMessages, @see NfcWatchOptions. | |
201 * @param callback that is used to notify caller when watch() is completed a nd return watch ID. | |
202 */ | |
203 @Override | |
204 public void watch(NfcWatchOptions options, WatchResponse callback) { | |
205 if (!checkIfReady(callback)) return; | |
206 // todo(shalamov): Not implemented. | |
207 callback.call(0, createError(NfcErrorType.NOT_SUPPORTED)); | |
208 } | |
209 | |
210 /** | |
211 * Cancels NFC watch operation. | |
212 * | |
213 * @param id of watch operation. | |
214 * @param callback that is used to notify caller when cancelWatch() is compl eted. | |
215 */ | |
216 @Override | |
217 public void cancelWatch(int id, CancelWatchResponse callback) { | |
218 if (!checkIfReady(callback)) return; | |
219 // todo(shalamov): Not implemented. | |
220 callback.call(createError(NfcErrorType.NOT_SUPPORTED)); | |
221 } | |
222 | |
223 /** | |
224 * Cancels all NFC watch operations. | |
225 * | |
226 * @param callback that is used to notify caller when cancelAllWatches() is completed. | |
227 */ | |
228 @Override | |
229 public void cancelAllWatches(CancelAllWatchesResponse callback) { | |
230 if (!checkIfReady(callback)) return; | |
231 // todo(shalamov): Not implemented. | |
232 callback.call(createError(NfcErrorType.NOT_SUPPORTED)); | |
233 } | |
234 | |
235 /** | |
236 * Suspends all pending watch / push operations. Should be called when web | |
237 * page visibility is lost. | |
238 */ | |
239 @Override | |
240 public void suspendNfcOperations() { | |
241 // todo(shalamov): Not implemented. | |
242 } | |
243 | |
244 /** | |
245 * Resumes all pending watch / push operations. Should be called when web | |
246 * page becomes visible. | |
247 */ | |
248 @Override | |
249 public void resumeNfcOperations() { | |
250 // todo(shalamov): Not implemented. | |
251 } | |
252 | |
253 @Override | |
254 public void close() {} | |
Ted C
2016/04/28 17:27:22
what close is this associated with?
To me, it loo
shalamov
2016/05/11 14:09:57
Done.
| |
255 | |
256 @Override | |
257 public void onConnectionError(MojoException e) {} | |
258 | |
259 /** | |
260 * Holds information about pending push operation. | |
261 */ | |
262 private static class PendingPushOperation { | |
263 private final NfcMessage mNfcMessage; | |
264 private final NfcPushOptions mNfcPushOptions; | |
265 private final PushResponse mPushResponseCallback; | |
266 | |
267 public PendingPushOperation( | |
268 NfcMessage message, NfcPushOptions options, PushResponse callbac k) { | |
269 mNfcMessage = message; | |
270 mNfcPushOptions = options; | |
271 mPushResponseCallback = callback; | |
272 } | |
273 | |
274 /** | |
275 * Completes pending push operation. | |
276 * | |
277 * @param error should be null when operation is completed successfully, | |
278 * otherwise, error object with corresponding NfcErrorType must be provi ded. | |
Ted C
2016/04/28 17:27:22
align w/ should above
shalamov
2016/05/11 14:09:57
Done.
| |
279 */ | |
280 public void complete(NfcError error) { | |
281 if (mPushResponseCallback != null) mPushResponseCallback.call(error) ; | |
282 } | |
283 | |
284 public NfcMessage message() { | |
285 return mNfcMessage; | |
286 } | |
287 public NfcPushOptions pushOptions() { | |
Ted C
2016/04/28 17:27:22
add a blank line above this.
Also, you could make
shalamov
2016/05/11 14:09:57
Done.
| |
288 return mNfcPushOptions; | |
289 } | |
290 } | |
291 | |
292 /** | |
293 * Helper method that creates NfcError object from NfcErrorType. | |
294 * | |
295 * @param errorType @see NfcErrorType. | |
296 * @return NfcError | |
297 * @see NfcError | |
298 */ | |
299 private NfcError createError(int errorType) { | |
300 NfcError error = new NfcError(); | |
301 error.errorType = errorType; | |
302 return error; | |
303 } | |
304 | |
305 /** | |
306 * Checks if NFC funcionality can be used by the mojo service. | |
307 * If permission to use NFC is granted and hardware is enabled, returns null . | |
308 * | |
309 * @return NfcError | |
310 */ | |
311 @Nullable | |
312 private NfcError checkIfReady() { | |
313 if (!mHasPermission) { | |
314 return createError(NfcErrorType.SECURITY); | |
315 } else if (mNfcManager == null || mNfcAdapter == null | |
316 || Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) { | |
Ted C
2016/04/28 17:27:21
I would still not create the mNfcManager for KK.
shalamov
2016/05/11 14:09:57
Done.
| |
317 return createError(NfcErrorType.NOT_SUPPORTED); | |
318 } else if (!mNfcAdapter.isEnabled()) { | |
319 return createError(NfcErrorType.DEVICE_DISABLED); | |
320 } | |
321 return null; | |
322 } | |
323 | |
324 /** | |
325 * Uses checkIfReady() method and if NFC functionality cannot be used, | |
326 * calls mojo callback with NfcError. | |
327 * | |
328 * @param WatchResponse Callback that is provided to watch() method. | |
329 * @return boolean true if NFC functionality can be used, false otherwise. | |
330 */ | |
331 private boolean checkIfReady(WatchResponse callback) { | |
332 NfcError error = checkIfReady(); | |
333 if (error == null) return true; | |
334 callback.call(0, error); | |
335 return false; | |
336 } | |
337 | |
338 /** | |
339 * Uses checkIfReady() method and if NFC functionality cannot be used, | |
340 * calls mojo callback NfcError. | |
341 * | |
342 * @param callback Generic callback that is provided to push(), cancelPush() , | |
343 * cancelWatch() and cancelAllWatches() methods. | |
344 * @return boolean true if NFC functionality can be used, false otherwise. | |
345 */ | |
346 private boolean checkIfReady(Callbacks.Callback1<NfcError> callback) { | |
347 NfcError error = checkIfReady(); | |
348 if (error == null) return true; | |
349 callback.call(error); | |
350 return false; | |
351 } | |
352 | |
353 /** | |
354 * Implementation of android.nfc.NfcAdapter.ReaderCallback. | |
355 * Callback is called when NFC tag is discovered, Tag object is delegated | |
356 * to mojo service implementation method NfcImpl.onTagDiscovered(). | |
357 */ | |
358 @TargetApi(Build.VERSION_CODES.KITKAT) | |
359 private static class ReaderCallbackHandler implements ReaderCallback { | |
360 private final NfcImpl mNfcImpl; | |
361 | |
362 public ReaderCallbackHandler(NfcImpl impl) { | |
363 mNfcImpl = impl; | |
364 } | |
365 | |
366 @Override | |
367 public void onTagDiscovered(Tag tag) { | |
368 mNfcImpl.onTagDiscovered(tag); | |
369 } | |
370 } | |
371 | |
372 /** | |
373 * Enables reader mode, allowing NFC device to read / write NFC tags. | |
374 * @see android.nfc.NfcAdapter#enableReaderMode | |
375 */ | |
376 private void enableReaderMode() { | |
377 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return; | |
378 if (mReaderCallbackHandler != null) return; | |
379 | |
380 mReaderCallbackHandler = new ReaderCallbackHandler(this); | |
381 mNfcAdapter.enableReaderMode(mActivity, mReaderCallbackHandler, | |
382 NfcAdapter.FLAG_READER_NFC_A | NfcAdapter.FLAG_READER_NFC_B | |
383 | NfcAdapter.FLAG_READER_NFC_F | NfcAdapter.FLAG_READER_ NFC_V, | |
384 null); | |
385 } | |
386 | |
387 /** | |
388 * Disables reader mode. | |
389 * @see android.nfc.NfcAdapter#disableReaderMode | |
390 */ | |
391 private void disableReaderMode() { | |
392 if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT) return; | |
393 | |
394 mReaderCallbackHandler = null; | |
395 mNfcAdapter.disableReaderMode(mActivity); | |
396 } | |
397 | |
398 /** | |
399 * NdefFormatable and Ndef interfaces have different signatures for writing | |
400 * NdefMessage to a tag. This interface provides generic write method. | |
401 */ | |
402 private interface TagTechnologyWriter { | |
403 public void write(NdefMessage message) | |
404 throws IOException, TagLostException, FormatException; | |
405 } | |
406 | |
407 /** | |
408 * Implementation of TagTechnologyWriter that can write NdefMessage to NFC t ag. | |
409 */ | |
410 private static class NdefWriter implements TagTechnologyWriter { | |
411 private final Ndef mNdef; | |
412 | |
413 NdefWriter(Ndef ndef) { | |
414 mNdef = ndef; | |
415 } | |
416 | |
417 public void write(NdefMessage message) | |
418 throws IOException, TagLostException, FormatException { | |
419 mNdef.writeNdefMessage(message); | |
420 } | |
421 } | |
422 | |
423 /** | |
424 * Implementation of TagTechnologyWriter that can format empty NFC tag | |
425 * with provided NFCMessage. | |
426 */ | |
427 private static class NdefFormattableWriter implements TagTechnologyWriter { | |
428 private final NdefFormatable mNdefFormattable; | |
429 | |
430 NdefFormattableWriter(NdefFormatable ndefFormattable) { | |
431 mNdefFormattable = ndefFormattable; | |
432 } | |
433 | |
434 public void write(NdefMessage message) | |
435 throws IOException, TagLostException, FormatException { | |
436 mNdefFormattable.format(message); | |
437 } | |
438 } | |
439 | |
440 /** | |
441 * Utility class that holds TagTechnology and TagTechnologyWriter objects. | |
442 * Provides connectivity and I/O related operations for NFC tag. | |
443 */ | |
444 private static class NfcTagWriter { | |
445 private final TagTechnology mTech; | |
446 private final TagTechnologyWriter mTechWriter; | |
447 private boolean mWasConnected = false; | |
Ted C
2016/04/28 17:27:22
false is the default, so you can drop this
shalamov
2016/05/11 14:09:58
Done.
| |
448 | |
449 /** | |
450 * Factory method that creates NfcTagWriter with TagTechnologyWriter | |
451 * appropriate for a given NFC Tag. | |
452 * | |
453 * @param tag @see android.nfc.Tag | |
454 * @return NfcTagWriter or null when unsupported Tag is provided. | |
455 */ | |
456 public static NfcTagWriter create(Tag tag) { | |
457 if (tag == null) return null; | |
458 | |
459 Ndef ndef = Ndef.get(tag); | |
460 if (ndef != null) return new NfcTagWriter(ndef, new NdefWriter(ndef) ); | |
461 | |
462 NdefFormatable formattable = NdefFormatable.get(tag); | |
463 if (formattable != null) { | |
464 return new NfcTagWriter(formattable, new NdefFormattableWriter(f ormattable)); | |
465 } | |
466 | |
467 return null; | |
468 } | |
469 | |
470 private NfcTagWriter(TagTechnology tech, TagTechnologyWriter writer) { | |
471 mTech = tech; | |
472 mTechWriter = writer; | |
473 } | |
474 | |
475 /** | |
476 * Connects to NFC tag. | |
477 */ | |
478 public void connect() throws IOException, TagLostException { | |
479 if (!mTech.isConnected()) { | |
480 mTech.connect(); | |
481 mWasConnected = true; | |
482 } | |
483 } | |
484 | |
485 /** | |
486 * Closes connection. | |
487 */ | |
488 public void close() throws IOException { | |
489 mTech.close(); | |
490 } | |
491 | |
492 /** | |
493 * Writes NdefMessage to NFC tag. | |
494 * | |
495 * @param message @see android.nfc.NdefMessage | |
496 */ | |
497 public void write(NdefMessage message) | |
498 throws IOException, TagLostException, FormatException { | |
499 mTechWriter.write(message); | |
500 } | |
501 | |
502 /** | |
503 * If tag was previously connected and subsequent connection to the same | |
504 * tag fails, consider tag to be out of ragne. | |
505 */ | |
506 public boolean isTagOutOfRange() { | |
507 try { | |
508 connect(); | |
509 } catch (IOException e) { | |
510 return mWasConnected; | |
511 } | |
512 return false; | |
513 } | |
514 } | |
515 | |
516 /** | |
517 * Exception that is raised when mojo NfcMessage cannot be coverted to NdefM essage. | |
518 */ | |
519 private static class InvalidMessageException extends Exception {} | |
520 | |
521 /** | |
522 * Converts mojo NfcMessage to android.nfc.NdefMessage. | |
523 * | |
524 * @param message mojo NfcMessage | |
525 * @return NdefMessage | |
526 * @see android.nfc.NdefMessage | |
527 */ | |
528 private NdefMessage toNdefMessage(NfcMessage message) throws InvalidMessageE xception { | |
529 if (message == null || message.data.length == 0) throw new InvalidMessag eException(); | |
530 | |
531 try { | |
532 List<NdefRecord> records = new ArrayList<NdefRecord>(); | |
533 for (NfcRecord record : message.data) { | |
Ted C
2016/04/28 17:27:21
is message.data an array primitive? In general, t
shalamov
2016/05/11 14:09:57
Done.
| |
534 records.add(toNdefRecord(record)); | |
535 } | |
536 records.add(NdefRecord.createExternal(DOMAIN, TYPE, message.url.getB ytes())); | |
537 NdefRecord[] ndefRecords = new NdefRecord[records.size()]; | |
538 records.toArray(ndefRecords); | |
539 return new NdefMessage(ndefRecords); | |
540 } catch (UnsupportedEncodingException | InvalidMessageException | |
541 | IllegalArgumentException e) { | |
542 throw new InvalidMessageException(); | |
543 } | |
544 } | |
545 | |
546 /** | |
547 * Returns charset of mojo NfcRecord. Only applicable for URL and TEXT recor ds. | |
548 * If charset cannot be determined, UTF-8 charset is used by default. | |
549 * | |
550 * @param record | |
Ted C
2016/04/28 17:27:21
these are a bit terse...you can probably drop thes
shalamov
2016/05/11 14:09:57
Done.
| |
551 * @return String | |
552 */ | |
553 private String getCharset(NfcRecord record) { | |
554 if (record.mediaType.endsWith(CHARSET_UTF8)) return "UTF-8"; | |
555 | |
556 if (record.mediaType.endsWith(CHARSET_UTF16)) return "UTF-16LE"; | |
557 | |
558 Log.w(TAG, "Unknown charset, defaulting to UTF-8."); | |
559 return "UTF-8"; | |
560 } | |
561 | |
562 /** | |
563 * Converts mojo NfcRecord to android.nfc.NdefRecord. | |
564 * | |
565 * @param record mojo NfcRecord | |
566 * @return NdefRecord | |
567 * @see android.nfc.NdefRecord | |
568 */ | |
569 private NdefRecord toNdefRecord(NfcRecord record) | |
570 throws InvalidMessageException, IllegalArgumentException, Unsupporte dEncodingException { | |
571 switch (record.recordType) { | |
572 case NfcRecordType.URL: | |
573 return NdefRecord.createUri(new String(record.data, getCharset(r ecord))); | |
574 case NfcRecordType.TEXT: | |
575 if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { | |
576 return NdefRecord.createTextRecord( | |
577 "en-US", new String(record.data, getCharset(record)) ); | |
578 } else { | |
579 return NdefRecord.createMime(TEXT_MIME, record.data); | |
580 } | |
581 case NfcRecordType.JSON: | |
582 case NfcRecordType.OPAQUE_RECORD: | |
583 return NdefRecord.createMime(record.mediaType, record.data); | |
584 default: | |
585 throw new InvalidMessageException(); | |
586 } | |
587 } | |
588 | |
589 /** | |
590 * Completes pending push operation. On error, invalidates #mTagWriter. | |
591 * | |
592 * @param error | |
Ted C
2016/04/28 17:27:22
same...you can drop all of these empty javadoc par
shalamov
2016/05/11 14:09:58
Done.
| |
593 */ | |
594 private void pendingPushOperationCompleted(NfcError error) { | |
595 if (mPendingPushOperation != null) { | |
596 mPendingPushOperation.complete(error); | |
597 mPendingPushOperation = null; | |
598 } | |
599 | |
600 if (error != null) mTagWriter = null; | |
601 } | |
602 | |
603 /** | |
604 * Checks whether there is a #mPendingPushOperation and writes data to NFC t ag. | |
605 * In case of exception calls pendingPushOperationCompleted() with appropria te | |
606 * error object. | |
607 */ | |
608 private void processPendingPushOperation() { | |
609 if (mTagWriter == null || mPendingPushOperation == null) return; | |
610 | |
611 if (mTagWriter.isTagOutOfRange()) { | |
612 mTagWriter = null; | |
613 return; | |
614 } | |
615 | |
616 try { | |
617 mTagWriter.connect(); | |
618 mTagWriter.write(toNdefMessage(mPendingPushOperation.message())); | |
619 pendingPushOperationCompleted(null); | |
620 mTagWriter.close(); | |
621 } catch (InvalidMessageException e) { | |
622 Log.w(TAG, "Cannot write data to NFC tag. Invalid NfcMessage."); | |
623 pendingPushOperationCompleted(createError(NfcErrorType.INVALID_MESSA GE)); | |
624 } catch (TagLostException e) { | |
625 Log.w(TAG, "Cannot write data to NFC tag. Tag is lost."); | |
626 pendingPushOperationCompleted(createError(NfcErrorType.IO_ERROR)); | |
627 } catch (FormatException | IOException e) { | |
628 Log.w(TAG, "Cannot write data to NFC tag. IO_ERROR."); | |
629 pendingPushOperationCompleted(createError(NfcErrorType.IO_ERROR)); | |
630 } | |
631 } | |
632 | |
633 /** | |
634 * Called by ReaderCallbackHandler when NFC tag is in proximity. | |
635 * calls processPendingPushOperation() that will write data to a tag. | |
636 * | |
637 * @param tag | |
638 */ | |
639 public void onTagDiscovered(Tag tag) { | |
640 mTagWriter = NfcTagWriter.create(tag); | |
641 processPendingPushOperation(); | |
642 } | |
643 } | |
OLD | NEW |