diff --git a/Android.mk b/Android.mk index 2cfc9a220be11..b5907616f4d37 100644 --- a/Android.mk +++ b/Android.mk @@ -215,6 +215,7 @@ LOCAL_SRC_FILES += \ core/java/android/nfc/INfcCardEmulation.aidl \ core/java/android/nfc/INfcFCardEmulation.aidl \ core/java/android/nfc/INfcUnlockHandler.aidl \ + core/java/android/nfc/ITagRemovedCallback.aidl \ core/java/android/os/IBatteryPropertiesListener.aidl \ core/java/android/os/IBatteryPropertiesRegistrar.aidl \ core/java/android/os/ICancellationSignal.aidl \ diff --git a/api/current.txt b/api/current.txt index 6fdd1bcb9866f..f0657c0e88249 100644 --- a/api/current.txt +++ b/api/current.txt @@ -25011,6 +25011,7 @@ package android.nfc { method public deprecated void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage); method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); + method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler); method public boolean invokeBeam(android.app.Activity); method public boolean isEnabled(); method public boolean isNdefPushEnabled(); @@ -25053,6 +25054,10 @@ package android.nfc { method public abstract void onNdefPushComplete(android.nfc.NfcEvent); } + public static abstract interface NfcAdapter.OnTagRemovedListener { + method public abstract void onTagRemoved(); + } + public static abstract interface NfcAdapter.ReaderCallback { method public abstract void onTagDiscovered(android.nfc.Tag); } @@ -25069,7 +25074,6 @@ package android.nfc { public final class Tag implements android.os.Parcelable { method public int describeContents(); - method public boolean done(int); method public byte[] getId(); method public java.lang.String[] getTechList(); method public void writeToParcel(android.os.Parcel, int); diff --git a/api/system-current.txt b/api/system-current.txt index ddd9ad6dcc65f..ba43ee47240bb 100644 --- a/api/system-current.txt +++ b/api/system-current.txt @@ -27447,6 +27447,7 @@ package android.nfc { method public boolean enableNdefPush(); method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); + method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler); method public boolean invokeBeam(android.app.Activity); method public boolean isEnabled(); method public boolean isNdefPushEnabled(); @@ -27496,6 +27497,10 @@ package android.nfc { method public abstract void onNdefPushComplete(android.nfc.NfcEvent); } + public static abstract interface NfcAdapter.OnTagRemovedListener { + method public abstract void onTagRemoved(); + } + public static abstract interface NfcAdapter.ReaderCallback { method public abstract void onTagDiscovered(android.nfc.Tag); } @@ -27512,7 +27517,6 @@ package android.nfc { public final class Tag implements android.os.Parcelable { method public int describeContents(); - method public boolean done(int); method public byte[] getId(); method public java.lang.String[] getTechList(); method public void writeToParcel(android.os.Parcel, int); diff --git a/api/test-current.txt b/api/test-current.txt index d40d0b8d4e3db..2cbb566ae35ca 100644 --- a/api/test-current.txt +++ b/api/test-current.txt @@ -25079,6 +25079,7 @@ package android.nfc { method public deprecated void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage); method public void enableReaderMode(android.app.Activity, android.nfc.NfcAdapter.ReaderCallback, int, android.os.Bundle); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); + method public boolean ignore(android.nfc.Tag, int, android.nfc.NfcAdapter.OnTagRemovedListener, android.os.Handler); method public boolean invokeBeam(android.app.Activity); method public boolean isEnabled(); method public boolean isNdefPushEnabled(); @@ -25121,6 +25122,10 @@ package android.nfc { method public abstract void onNdefPushComplete(android.nfc.NfcEvent); } + public static abstract interface NfcAdapter.OnTagRemovedListener { + method public abstract void onTagRemoved(); + } + public static abstract interface NfcAdapter.ReaderCallback { method public abstract void onTagDiscovered(android.nfc.Tag); } @@ -25137,7 +25142,6 @@ package android.nfc { public final class Tag implements android.os.Parcelable { method public int describeContents(); - method public boolean done(int); method public byte[] getId(); method public java.lang.String[] getTechList(); method public void writeToParcel(android.os.Parcel, int); diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 940565f09c03c..f991efed07ebf 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -28,6 +28,7 @@ import android.nfc.INfcTag; import android.nfc.INfcCardEmulation; import android.nfc.INfcFCardEmulation; import android.nfc.INfcUnlockHandler; +import android.nfc.ITagRemovedCallback; import android.os.Bundle; /** @@ -55,6 +56,8 @@ interface INfcAdapter oneway void invokeBeam(); oneway void invokeBeamInternal(in BeamShareData shareData); + boolean ignore(int nativeHandle, int debounceMs, ITagRemovedCallback callback); + void dispatch(in Tag tag); void setReaderMode (IBinder b, IAppCallback callback, int flags, in Bundle extras); diff --git a/core/java/android/nfc/INfcTag.aidl b/core/java/android/nfc/INfcTag.aidl index 26d2bec761f8f..539fd4adb0a06 100644 --- a/core/java/android/nfc/INfcTag.aidl +++ b/core/java/android/nfc/INfcTag.aidl @@ -31,7 +31,6 @@ interface INfcTag boolean isNdef(int nativeHandle); boolean isPresent(int nativeHandle); TransceiveResult transceive(int nativeHandle, in byte[] data, boolean raw); - boolean done(int nativeHandle, int debounceMs); NdefMessage ndefRead(int nativeHandle); int ndefWrite(int nativeHandle, in NdefMessage msg); diff --git a/core/java/android/nfc/ITagRemovedCallback.aidl b/core/java/android/nfc/ITagRemovedCallback.aidl new file mode 100644 index 0000000000000..2a06ff314b22b --- /dev/null +++ b/core/java/android/nfc/ITagRemovedCallback.aidl @@ -0,0 +1,8 @@ +package android.nfc; + +/** + * @hide + */ +oneway interface ITagRemovedCallback { + void onTagRemoved(); +} diff --git a/core/java/android/nfc/NfcAdapter.java b/core/java/android/nfc/NfcAdapter.java index 6f911ceb4bedd..8406bcfa8184d 100644 --- a/core/java/android/nfc/NfcAdapter.java +++ b/core/java/android/nfc/NfcAdapter.java @@ -35,11 +35,14 @@ import android.nfc.tech.Ndef; import android.nfc.tech.NfcA; import android.nfc.tech.NfcF; import android.os.Bundle; +import android.os.Handler; import android.os.IBinder; import android.os.RemoteException; import android.os.ServiceManager; import android.util.Log; +import java.io.IOException; + /** * Represents the local NFC adapter. *

@@ -315,6 +318,8 @@ public final class NfcAdapter { final HashMap mNfcUnlockHandlers; final Object mLock; + ITagRemovedCallback mTagRemovedListener; // protected by mLock + /** * A callback to be invoked when the system finds a tag while the foreground activity is * operating in reader mode. @@ -385,6 +390,13 @@ public final class NfcAdapter { public Uri[] createBeamUris(NfcEvent event); } + /** + * A callback that is invoked when a tag is removed from the field. + */ + public interface OnTagRemovedListener { + void onTagRemoved(); + } + /** * A callback to be invoked when an application has registered as a * handler to unlock the device given an NFC tag at the lockscreen. @@ -541,6 +553,7 @@ public final class NfcAdapter { mContext = context; mNfcActivityManager = new NfcActivityManager(this); mNfcUnlockHandlers = new HashMap(); + mTagRemovedListener = null; mLock = new Object(); } @@ -1493,6 +1506,75 @@ public final class NfcAdapter { } } + /** + * Signals that you are no longer interested in communicating with an NFC tag + * for as long as it remains in range. + * + * All future attempted communication to this tag will fail with {@link IOException}. + * The NFC controller will be put in a low-power polling mode, allowing the device + * to save power in cases where it's "attached" to a tag all the time (e.g. a tag in + * car dock). + * + * Additionally the debounceMs parameter allows you to specify for how long the tag needs + * to have gone out of range, before it will be dispatched again. + * + * Note: the NFC controller typically polls at a pretty slow interval (100 - 500 ms). + * This means that if the tag repeatedly goes in and out of range (for example, in + * case of a flaky connection), and the controller happens to poll every time the + * tag is out of range, it *will* re-dispatch the tag after debounceMs, despite the tag + * having been "in range" during the interval. + * + * Note 2: if a tag with another UID is detected after this API is called, its effect + * will be cancelled; if this tag shows up before the amount of time specified in + * debounceMs, it will be dispatched again. + * + * Note 3: some tags have a random UID, in which case this API won't work reliably. + * + * @param tag the {@link android.nfc.Tag Tag} to ignore. + * @param debounceMs minimum amount of time the tag needs to be out of range before being + * dispatched again. + * @param tagRemovedListener listener to be called when the tag is removed from the field. + * Note that this will only be called if the tag has been out of range + * for at least debounceMs, or if another tag came into range before + * debounceMs. May be null in case you don't want a callback. + * @param handler the {@link android.os.Handler Handler} that will be used for delivering + * the callback. if the handler is null, then the thread used for delivering + * the callback is unspecified. + * @return false if the tag couldn't be found (or has already gone out of range), true otherwise + */ + public boolean ignore(final Tag tag, int debounceMs, + final OnTagRemovedListener tagRemovedListener, final Handler handler) { + ITagRemovedCallback.Stub iListener = null; + if (tagRemovedListener != null) { + iListener = new ITagRemovedCallback.Stub() { + @Override + public void onTagRemoved() throws RemoteException { + if (handler != null) { + handler.post(new Runnable() { + @Override + public void run() { + tagRemovedListener.onTagRemoved(); + } + }); + } else { + tagRemovedListener.onTagRemoved(); + } + synchronized (mLock) { + mTagRemovedListener = null; + } + } + }; + } + synchronized (mLock) { + mTagRemovedListener = iListener; + } + try { + return sService.ignore(tag.getServiceHandle(), debounceMs, iListener); + } catch (RemoteException e) { + return false; + } + } + /** * Inject a mock NFC tag.

* Used for testing purposes. diff --git a/core/java/android/nfc/Tag.java b/core/java/android/nfc/Tag.java index 40d5a8db83b41..154d5a11db9e4 100644 --- a/core/java/android/nfc/Tag.java +++ b/core/java/android/nfc/Tag.java @@ -214,42 +214,6 @@ public final class Tag implements Parcelable { return techIntList; } - /** - * Signals that you are no longer interested in communicating with this tag - * for as long as it remains in range. - * - * All future attempted communication to this tag will fail with {@link IOException}. - * The NFC controller will be put in a low-power polling mode, allowing the device - * to save power in cases where it's "attached" to a tag all the time (eg a tag in - * car dock). - * - * Additionally the debounceMs parameter allows you to specify for how long the tag needs - * to have gone out of range, before it will be dispatched again. - * - * Note: the NFC controller typically polls at a pretty slow interval (100 - 500 ms). - * This means that if the tag repeatedly goes in and out of range (for example, in - * case of a flaky connection), and the controller happens to poll every time the - * tag is out of range, it *will* re-dispatch the tag after debounceMs, despite the tag - * having been "in range" during the interval. - * - * Note 2: if a tag with another UID is detected after this API is called, its effect - * will be cancelled; if this tag shows up before the amount of time specified in - * debounceMs, it will be dispatched again. - * - * Note 3: some tags have a random UID, in which case this API won't work. - * - * @param debounceMs minimum amount of time the tag needs to be out of range before being - * dispatched again. - * @return false if the Tag couldn't be found (or has gone out of range), true otherwise - */ - public boolean done(int debounceMs) { - try { - return mTagService.done(getServiceHandle(), debounceMs); - } catch (RemoteException e) { - return false; - } - } - private static HashMap getTechStringToCodeMap() { HashMap techStringToCodeMap = new HashMap();