diff --git a/CleanSpec.mk b/CleanSpec.mk index 0dba18b4256a3..e6c4183ed3b1c 100644 --- a/CleanSpec.mk +++ b/CleanSpec.mk @@ -107,6 +107,7 @@ $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/R/com/android/systemui/R. $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.P) $(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/media/java/android/media/IAudioService.P) $(call add-clean-step, rm -rf $(PRODUCT_OUT)/system/media/audio/) +$(call add-clean-step, rm -rf $(OUT_DIR)/target/common/obj/JAVA_LIBRARIES/framework_intermediates/src/core/java/android/nfc/) # ************************************************ # NEWER CLEAN STEPS MUST BE AT THE END OF THE LIST # ************************************************ diff --git a/api/current.txt b/api/current.txt index bfe1f853cf3be..c8cebced3a9aa 100644 --- a/api/current.txt +++ b/api/current.txt @@ -12413,13 +12413,15 @@ package android.nfc { public final class NfcAdapter { method public void disableForegroundDispatch(android.app.Activity); - method public void disableForegroundNdefPush(android.app.Activity); + method public deprecated void disableForegroundNdefPush(android.app.Activity); method public void enableForegroundDispatch(android.app.Activity, android.app.PendingIntent, android.content.IntentFilter[], java.lang.String[][]); - method public void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage); - method public void enableForegroundNdefPush(android.app.Activity, android.nfc.NfcAdapter.NdefPushCallback); + method public deprecated void enableForegroundNdefPush(android.app.Activity, android.nfc.NdefMessage); method public static android.nfc.NfcAdapter getDefaultAdapter(android.content.Context); method public static deprecated android.nfc.NfcAdapter getDefaultAdapter(); method public boolean isEnabled(); + method public void setNdefPushMessage(android.nfc.NdefMessage, android.app.Activity...); + method public void setNdefPushMessageCallback(android.nfc.NfcAdapter.CreateNdefMessageCallback, android.app.Activity...); + method public void setOnNdefPushCompleteCallback(android.nfc.NfcAdapter.OnNdefPushCompleteCallback, android.app.Activity...); field public static final java.lang.String ACTION_NDEF_DISCOVERED = "android.nfc.action.NDEF_DISCOVERED"; field public static final java.lang.String ACTION_TAG_DISCOVERED = "android.nfc.action.TAG_DISCOVERED"; field public static final java.lang.String ACTION_TECH_DISCOVERED = "android.nfc.action.TECH_DISCOVERED"; @@ -12428,9 +12430,16 @@ package android.nfc { field public static final java.lang.String EXTRA_TAG = "android.nfc.extra.TAG"; } - public static abstract interface NfcAdapter.NdefPushCallback { - method public abstract android.nfc.NdefMessage createMessage(); - method public abstract void onMessagePushed(); + public static abstract interface NfcAdapter.CreateNdefMessageCallback { + method public abstract android.nfc.NdefMessage createNdefMessage(android.nfc.NfcEvent); + } + + public static abstract interface NfcAdapter.OnNdefPushCompleteCallback { + method public abstract void onNdefPushComplete(android.nfc.NfcEvent); + } + + public final class NfcEvent { + field public final android.nfc.NfcAdapter nfcAdapter; } public final class NfcManager { diff --git a/core/java/android/nfc/INdefPushCallback.aidl b/core/java/android/nfc/INdefPushCallback.aidl index 80ba2ed09fc5b..e60a5b0a4031d 100644 --- a/core/java/android/nfc/INdefPushCallback.aidl +++ b/core/java/android/nfc/INdefPushCallback.aidl @@ -23,6 +23,6 @@ import android.nfc.NdefMessage; */ interface INdefPushCallback { - NdefMessage onConnect(); - void onMessagePushed(); + NdefMessage createMessage(); + void onNdefPushComplete(); } diff --git a/core/java/android/nfc/INfcAdapter.aidl b/core/java/android/nfc/INfcAdapter.aidl index 4fc248f6c3c02..016af58da74a9 100644 --- a/core/java/android/nfc/INfcAdapter.aidl +++ b/core/java/android/nfc/INfcAdapter.aidl @@ -23,8 +23,8 @@ import android.nfc.NdefMessage; import android.nfc.Tag; import android.nfc.TechListParcel; import android.nfc.INdefPushCallback; -import android.nfc.INfcTag; import android.nfc.INfcAdapterExtras; +import android.nfc.INfcTag; /** * @hide @@ -34,19 +34,14 @@ interface INfcAdapter INfcTag getNfcTagInterface(); INfcAdapterExtras getNfcAdapterExtrasInterface(); - // NfcAdapter-class related methods int getState(); - void enableForegroundDispatch(in ComponentName activity, in PendingIntent intent, - in IntentFilter[] filters, in TechListParcel techLists); - void disableForegroundDispatch(in ComponentName activity); - void enableForegroundNdefPush(in ComponentName activity, in NdefMessage msg); - void enableForegroundNdefPushWithCallback(in ComponentName activity, in INdefPushCallback callback); - void disableForegroundNdefPush(in ComponentName activity); - - // Non-public methods boolean disable(); boolean enable(); - boolean enableZeroClick(); - boolean disableZeroClick(); - boolean isZeroClickEnabled(); + boolean enableNdefPush(); + boolean disableNdefPush(); + boolean isNdefPushEnabled(); + + void setForegroundDispatch(in PendingIntent intent, + in IntentFilter[] filters, in TechListParcel techLists); + void setForegroundNdefPush(in NdefMessage msg, in INdefPushCallback callback); } diff --git a/core/java/android/nfc/NfcActivityManager.java b/core/java/android/nfc/NfcActivityManager.java new file mode 100644 index 0000000000000..3cc6820356128 --- /dev/null +++ b/core/java/android/nfc/NfcActivityManager.java @@ -0,0 +1,217 @@ +/* + * Copyright (C) 2011 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.nfc; + +import android.app.Activity; +import android.os.RemoteException; +import android.util.Log; + +import java.util.HashMap; + +/** + * Manages NFC API's that are coupled to the life-cycle of an Activity. + * + *
Uses a fragment to hook into onPause() and onResume() of the host + * activities. + * + *
Ideally all of this management would be done in the NFC Service,
+ * but right now it is much easier to do it in the application process.
+ *
+ * @hide
+ */
+public final class NfcActivityManager extends INdefPushCallback.Stub {
+ static final String TAG = NfcAdapter.TAG;
+ static final Boolean DBG = false;
+
+ final NfcAdapter mAdapter;
+ final HashMap
- * Always contains the extra field
- * {@link android.nfc.NfcAdapter#EXTRA_LLCP_LINK_STATE_CHANGED}.
- * @hide
- */
- @SdkConstant(SdkConstantType.BROADCAST_INTENT_ACTION)
- public static final String ACTION_LLCP_LINK_STATE_CHANGED =
- "android.nfc.action.LLCP_LINK_STATE_CHANGED";
-
- /**
- * Used as int extra field in
- * {@link android.nfc.NfcAdapter#ACTION_LLCP_LINK_STATE_CHANGED}.
- *
- * It contains the new state of the LLCP link.
- * @hide
- */
- public static final String EXTRA_LLCP_LINK_STATE_CHANGED = "android.nfc.extra.LLCP_LINK_STATE";
-
- /**
- * Tag Reader Discovery mode
- * @hide
- */
- private static final int DISCOVERY_MODE_TAG_READER = 0;
-
- /**
- * NFC-IP1 Peer-to-Peer mode Enables the manager to act as a peer in an
- * NFC-IP1 communication. Implementations should not assume that the
- * controller will end up behaving as an NFC-IP1 target or initiator and
- * should handle both cases, depending on the type of the remote peer type.
- * @hide
- */
- private static final int DISCOVERY_MODE_NFCIP1 = 1;
-
- /**
- * Card Emulation mode Enables the manager to act as an NFC tag. Provided
- * that a Secure Element (an UICC for instance) is connected to the NFC
- * controller through its SWP interface, it can be exposed to the outside
- * NFC world and be addressed by external readers the same way they would
- * with a tag.
- *
- * Which Secure Element is exposed is implementation-dependent.
- *
- * @hide
- */
- private static final int DISCOVERY_MODE_CARD_EMULATION = 2;
-
- /**
- * Callback passed into {@link #enableForegroundNdefPush(Activity,NdefPushCallback)}. This
- */
- public interface NdefPushCallback {
- /**
- * Called when a P2P connection is created.
- */
- NdefMessage createMessage();
- /**
- * Called when the message is pushed.
- */
- void onMessagePushed();
- }
-
- private static class NdefPushCallbackWrapper extends INdefPushCallback.Stub {
- private NdefPushCallback mCallback;
-
- public NdefPushCallbackWrapper(NdefPushCallback callback) {
- mCallback = callback;
- }
-
- @Override
- public NdefMessage onConnect() {
- return mCallback.createMessage();
- }
-
- @Override
- public void onMessagePushed() {
- mCallback.onMessagePushed();
- }
- }
-
// Guarded by NfcAdapter.class
- private static boolean sIsInitialized = false;
+ static boolean sIsInitialized = false;
// Final after first constructor, except for
// attemptDeadServiceRecovery() when NFC crashes - we accept a best effort
// recovery
- private static INfcAdapter sService;
- private static INfcTag sTagService;
+ static INfcAdapter sService;
+ static INfcTag sTagService;
+
+ /**
+ * NfcAdapter is currently a singleton, and does not require a context.
+ * However all the public API's are future-proofed to require a context.
+ * If we start using that then we'll need to keep a HashMap of
+ * Context.getApplicationContext() -> NfcAdapter, such that NfcAdapter
+ * is a singleton within each application context.
+ */
+ static NfcAdapter sSingleton; // protected by NfcAdapter.class
+
+ final NfcActivityManager mNfcActivityManager;
+
+ /**
+ * @see {@link #setNdefPushMessageCallback}
+ */
+ public interface OnNdefPushCompleteCallback {
+ /**
+ * Called on successful NDEF push.
+ *
+ * This callback is usually made on a binder thread (not the UI thread).
+ *
+ * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
+ * @see {@link #setNdefPushMessageCallback}
+ */
+ public void onNdefPushComplete(NfcEvent event);
+ }
+
+ /**
+ * @see {@link #setCeateNdefMessageCallback}
+ */
+ public interface CreateNdefMessageCallback {
+ /**
+ * Called to provide a {@link NdefMessage} to push.
+ *
+ * This callback is usually made on a binder thread (not the UI thread).
+ *
+ * Called when this device is in range of another device
+ * that might support NDEF push. It allows the application to
+ * create the NDEF message only when it is required.
+ *
+ * NDEF push cannot occur until this method returns, so do not
+ * block for too long.
+ *
+ * The Android operating system will usually show a system UI
+ * on top of your activity during this time, so do not try to request
+ * input from the user to complete the callback, or provide custom NDEF
+ * push UI. The user probably will not see it.
+ *
+ * @param event {@link NfcEvent} with the {@link NfcEvent#nfcAdapter} field set
+ * @return NDEF message to push, or null to not provide a message
+ */
+ public NdefMessage createNdefMessage(NfcEvent event);
+ }
/**
* Helper to check if this device has FEATURE_NFC, but without using
@@ -308,29 +269,36 @@ public final class NfcAdapter {
}
}
- private static synchronized INfcAdapter setupService() {
+ /**
+ * Returns the singleton, or throws if NFC is not available.
+ */
+ static synchronized NfcAdapter getSingleton() {
if (!sIsInitialized) {
sIsInitialized = true;
/* is this device meant to have NFC */
if (!hasNfcFeature()) {
Log.v(TAG, "this device does not have NFC support");
- return null;
+ throw new UnsupportedOperationException();
}
sService = getServiceInterface();
if (sService == null) {
Log.e(TAG, "could not retrieve NFC service");
- return null;
+ throw new UnsupportedOperationException();
}
try {
sTagService = sService.getNfcTagInterface();
} catch (RemoteException e) {
Log.e(TAG, "could not retrieve NFC Tag service");
- return null;
+ throw new UnsupportedOperationException();
}
+ sSingleton = new NfcAdapter();
}
- return sService;
+ if (sSingleton == null) {
+ throw new UnsupportedOperationException();
+ }
+ return sSingleton;
}
/** get handle to NFC service interface */
@@ -376,13 +344,14 @@ public final class NfcAdapter {
public static NfcAdapter getDefaultAdapter() {
Log.w(TAG, "WARNING: NfcAdapter.getDefaultAdapter() is deprecated, use " +
"NfcAdapter.getDefaultAdapter(Context) instead", new Exception());
- return new NfcAdapter(null);
+ return getSingleton();
}
- /*package*/ NfcAdapter(Context context) {
- if (setupService() == null) {
- throw new UnsupportedOperationException();
- }
+ /**
+ * Does not currently need a context.
+ */
+ NfcAdapter() {
+ mNfcActivityManager = new NfcActivityManager(this);
}
/**
@@ -523,6 +492,87 @@ public final class NfcAdapter {
}
}
+ /**
+ * Set the {@link NdefMessage} to push over NFC during the specified activities.
+ *
+ * This method may be called at any time, but the NDEF message is
+ * only made available for NDEF push when one of the specified activities
+ * is in resumed (foreground) state.
+ *
+ * Only one NDEF message can be pushed by the currently resumed activity.
+ * If both {@link #setNdefPushMessage} and
+ * {@link #setNdefPushMessageCallback} are set then
+ * the callback will take priority.
+ *
+ * Pass a null NDEF message to disable foreground NDEF push in the
+ * specified activities.
+ *
+ * Requires the {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param message NDEF message to push over NFC, or null to disable
+ * @param activities one or more {@link Activity} to enable for NDEF push
+ */
+ public void setNdefPushMessage(NdefMessage message, Activity ... activities) {
+ if (activities.length == 0) {
+ throw new NullPointerException("Must specificy one or more activities");
+ }
+ for (Activity a : activities) {
+ mNfcActivityManager.setNdefPushMessage(a, message);
+ }
+ }
+
+ /**
+ * Set the callback to create a {@link NdefMessage} to push over NFC.
+ *
+ * This method may be called at any time, but this callback is
+ * only made if one of the specified activities
+ * is in resumed (foreground) state.
+ *
+ * Only one NDEF message can be pushed by the currently resumed activity.
+ * If both {@link #setNdefPushMessage} and
+ * {@link #setNdefPushMessageCallback} are set then
+ * the callback will take priority.
+ *
+ * Pass a null callback to disable the callback in the
+ * specified activities.
+ *
+ * Requires the {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param callback callback, or null to disable
+ * @param activities one or more {@link Activity} to enable for NDEF push
+ */
+ public void setNdefPushMessageCallback(CreateNdefMessageCallback callback,
+ Activity ... activities) {
+ if (activities.length == 0) {
+ throw new NullPointerException("Must specificy one or more activities");
+ }
+ for (Activity a : activities) {
+ mNfcActivityManager.setNdefPushMessageCallback(a, callback);
+ }
+ }
+
+ /**
+ * Set the callback on a successful NDEF push over NFC.
+ *
+ * This method may be called at any time, but NDEF push and this callback
+ * can only occur when one of the specified activities is in resumed
+ * (foreground) state.
+ *
+ * Requires the {@link android.Manifest.permission#NFC} permission.
+ *
+ * @param callback callback, or null to disable
+ * @param activities one or more {@link Activity} to enable the callback
+ */
+ public void setOnNdefPushCompleteCallback(OnNdefPushCompleteCallback callback,
+ Activity ... activities) {
+ if (activities.length == 0) {
+ throw new NullPointerException("Must specificy one or more activities");
+ }
+ for (Activity a : activities) {
+ mNfcActivityManager.setOnNdefPushCompleteCallback(a, callback);
+ }
+ }
+
/**
* Enable foreground dispatch to the given Activity.
*
@@ -562,7 +612,7 @@ public final class NfcAdapter {
throw new NullPointerException();
}
if (!activity.isResumed()) {
- throw new IllegalStateException("Foregorund dispatching can only be enabled " +
+ throw new IllegalStateException("Foreground dispatch can only be enabled " +
"when your activity is resumed");
}
try {
@@ -572,8 +622,7 @@ public final class NfcAdapter {
}
ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
mForegroundDispatchListener);
- sService.enableForegroundDispatch(activity.getComponentName(), intent, filters,
- parcel);
+ sService.setForegroundDispatch(intent, filters, parcel);
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
}
@@ -608,9 +657,9 @@ public final class NfcAdapter {
void disableForegroundDispatchInternal(Activity activity, boolean force) {
try {
- sService.disableForegroundDispatch(activity.getComponentName());
+ sService.setForegroundDispatch(null, null, null);
if (!force && !activity.isResumed()) {
- throw new IllegalStateException("You must disable forgeground dispatching " +
+ throw new IllegalStateException("You must disable foreground dispatching " +
"while your activity is still resumed");
}
} catch (RemoteException e) {
@@ -619,78 +668,38 @@ public final class NfcAdapter {
}
/**
- * Enable NDEF message push over P2P while this Activity is in the foreground.
+ * Enable NDEF message push over NFC while this Activity is in the foreground.
*
- * For this to function properly the other NFC device being scanned must
- * support the "com.android.npp" NDEF push protocol. Support for this
- * protocol is currently optional for Android NFC devices.
+ * You must explicitly call this method every time the activity is
+ * resumed, and you must call {@link #disableForegroundNdefPush} before
+ * your activity completes {@link Activity#onPause}.
+ *
+ * Strongly recommend to use the new {@link #setNdefPushMessage}
+ * instead: it automatically hooks into your activity life-cycle,
+ * so you do not need to call enable/disable in your onResume/onPause.
+ *
+ * For NDEF push to function properly the other NFC device must
+ * support either NFC Forum's SNEP (Simple Ndef Exchange Protocol), or
+ * Android's "com.android.npp" (Ndef Push Protocol). This was optional
+ * on Gingerbread level Android NFC devices, but SNEP is mandatory on
+ * Ice-Cream-Sandwich and beyond.
*
* This method must be called from the main thread.
*
- * NOTE: While foreground NDEF push is active standard tag dispatch is disabled.
- * Only the foreground activity may receive tag discovered dispatches via
- * {@link #enableForegroundDispatch}.
- *
* Requires the {@link android.Manifest.permission#NFC} permission.
*
- * @param activity the foreground Activity
- * @param msg a NDEF Message to push over P2P
- * @throws IllegalStateException if the Activity is not currently in the foreground
- * @throws OperationNotSupportedException if this Android device does not support NDEF push
+ * @param activity foreground activity
+ * @param message a NDEF Message to push over NFC
+ * @throws IllegalStateException if the activity is not currently in the foreground
+ * @deprecated use {@link #setNdefPushMessage} instead
*/
- public void enableForegroundNdefPush(Activity activity, NdefMessage msg) {
- if (activity == null || msg == null) {
+ @Deprecated
+ public void enableForegroundNdefPush(Activity activity, NdefMessage message) {
+ if (activity == null || message == null) {
throw new NullPointerException();
}
- if (!activity.isResumed()) {
- throw new IllegalStateException("Foregorund NDEF push can only be enabled " +
- "when your activity is resumed");
- }
- try {
- ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
- mForegroundNdefPushListener);
- sService.enableForegroundNdefPush(activity.getComponentName(), msg);
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- }
- }
-
- /**
- * Enable NDEF message push over P2P while this Activity is in the foreground.
- *
- * For this to function properly the other NFC device being scanned must
- * support the "com.android.npp" NDEF push protocol. Support for this
- * protocol is currently optional for Android NFC devices.
- *
- * This method must be called from the main thread.
- *
- * NOTE: While foreground NDEF push is active standard tag dispatch is disabled.
- * Only the foreground activity may receive tag discovered dispatches via
- * {@link #enableForegroundDispatch}.
- *
- * Requires the {@link android.Manifest.permission#NFC} permission.
- *
- * @param activity the foreground Activity
- * @param callback is called on when the P2P connection is established
- * @throws IllegalStateException if the Activity is not currently in the foreground
- * @throws OperationNotSupportedException if this Android device does not support NDEF push
- */
- public void enableForegroundNdefPush(Activity activity, NdefPushCallback callback) {
- if (activity == null || callback == null) {
- throw new NullPointerException();
- }
- if (!activity.isResumed()) {
- throw new IllegalStateException("Foregorund NDEF push can only be enabled " +
- "when your activity is resumed");
- }
- try {
- ActivityThread.currentActivityThread().registerOnActivityPausedListener(activity,
- mForegroundNdefPushListener);
- sService.enableForegroundNdefPushWithCallback(activity.getComponentName(),
- new NdefPushCallbackWrapper(callback));
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
- }
+ enforceResumed(activity);
+ mNfcActivityManager.setNdefPushMessage(activity, message);
}
/**
@@ -700,47 +709,91 @@ public final class NfcAdapter {
* must call this method before its {@link Activity#onPause} callback
* completes.
*
+ * Strongly recommend to use the new {@link #setNdefPushMessage}
+ * instead: it automatically hooks into your activity life-cycle,
+ * so you do not need to call enable/disable in your onResume/onPause.
+ *
* This method must be called from the main thread.
*
* Requires the {@link android.Manifest.permission#NFC} permission.
*
* @param activity the Foreground activity
* @throws IllegalStateException if the Activity has already been paused
- * @throws OperationNotSupportedException if this Android device does not support NDEF push
+ * @deprecated use {@link #setNdefPushMessage} instead
*/
public void disableForegroundNdefPush(Activity activity) {
- ActivityThread.currentActivityThread().unregisterOnActivityPausedListener(activity,
- mForegroundNdefPushListener);
- disableForegroundNdefPushInternal(activity, false);
+ if (activity == null) {
+ throw new NullPointerException();
+ }
+ enforceResumed(activity);
+ mNfcActivityManager.setNdefPushMessage(activity, null);
+ mNfcActivityManager.setNdefPushMessageCallback(activity, null);
+ mNfcActivityManager.setOnNdefPushCompleteCallback(activity, null);
}
- OnActivityPausedListener mForegroundNdefPushListener = new OnActivityPausedListener() {
+ /**
+ * TODO: Remove this once pre-built apk's (Maps, Youtube etc) are updated
+ * @deprecated use {@link CreateNdefMessageCallback} or {@link OnNdefPushCompleteCallback}
+ * @hide
+ */
+ @Deprecated
+ public interface NdefPushCallback {
+ /**
+ * @deprecated use {@link CreateNdefMessageCallback} instead
+ */
+ @Deprecated
+ NdefMessage createMessage();
+ /**
+ * @deprecated use{@link OnNdefPushCompleteCallback} instead
+ */
+ @Deprecated
+ void onMessagePushed();
+ }
+
+ /**
+ * TODO: Remove this
+ * Converts new callbacks to old callbacks.
+ */
+ static final class LegacyCallbackWrapper implements CreateNdefMessageCallback,
+ OnNdefPushCompleteCallback {
+ final NdefPushCallback mLegacyCallback;
+ LegacyCallbackWrapper(NdefPushCallback legacyCallback) {
+ mLegacyCallback = legacyCallback;
+ }
@Override
- public void onPaused(Activity activity) {
- disableForegroundNdefPushInternal(activity, true);
+ public void onNdefPushComplete(NfcEvent event) {
+ mLegacyCallback.onMessagePushed();
}
- };
-
- void disableForegroundNdefPushInternal(Activity activity, boolean force) {
- try {
- sService.disableForegroundNdefPush(activity.getComponentName());
- if (!force && !activity.isResumed()) {
- throw new IllegalStateException("You must disable forgeground NDEF push " +
- "while your activity is still resumed");
- }
- } catch (RemoteException e) {
- attemptDeadServiceRecovery(e);
+ @Override
+ public NdefMessage createNdefMessage(NfcEvent event) {
+ return mLegacyCallback.createMessage();
}
}
/**
- * Enable zero-click sharing.
- *
+ * TODO: Remove this once pre-built apk's (Maps, Youtube etc) are updated
+ * @deprecated use {@link #setNdefPushMessageCallback} instead
* @hide
*/
- public boolean enableZeroClick() {
+ @Deprecated
+ public void enableForegroundNdefPush(Activity activity, final NdefPushCallback callback) {
+ if (activity == null || callback == null) {
+ throw new NullPointerException();
+ }
+ enforceResumed(activity);
+ LegacyCallbackWrapper callbackWrapper = new LegacyCallbackWrapper(callback);
+ mNfcActivityManager.setNdefPushMessageCallback(activity, callbackWrapper);
+ mNfcActivityManager.setOnNdefPushCompleteCallback(activity, callbackWrapper);
+ }
+
+ /**
+ * Enable NDEF Push feature.
+ * This API is for the Settings application.
+ * @hide
+ */
+ public boolean enableNdefPush() {
try {
- return sService.enableZeroClick();
+ return sService.enableNdefPush();
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return false;
@@ -748,13 +801,13 @@ public final class NfcAdapter {
}
/**
- * Disable zero-click sharing.
- *
+ * Disable NDEF Push feature.
+ * This API is for the Settings application.
* @hide
*/
- public boolean disableZeroClick() {
+ public boolean disableNdefPush() {
try {
- return sService.disableZeroClick();
+ return sService.disableNdefPush();
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return false;
@@ -762,20 +815,20 @@ public final class NfcAdapter {
}
/**
- * Return true if zero-click sharing feature is enabled.
+ * Return true if NDEF Push feature is enabled.
* This function can return true even if NFC is currently turned-off.
- * This indicates that zero-click is not currently active, but it has
+ * This indicates that NDEF Push is not currently active, but it has
* been requested by the user and will be active as soon as NFC is turned
* on.
- * If you want to check if zero-click sharing is currently active, use
- * If you want to check if NDEF PUsh sharing is currently active, use
+ * Immutable object, with direct access to the (final) fields.
+ *
+ * An {@link NfcEvent} object is usually included in callbacks from
+ * {@link NfcAdapter}. Check the documentation of the callback to see
+ * which fields may be set.
+ *
+ * This wrapper object is used (instead of parameters
+ * in the callback) because it allows new fields to be added without breaking
+ * API compatibility.
+ *
+ * @see {@link NfcAdapter.OnNdefPushCompleteCallback#onNdefPushComplete}
+ * @see {@link NfcAdapter.CreateNdefMessageCallback#createNdefMessage}
+ */
+public final class NfcEvent {
+ /**
+ * The {@link NfcAdapter} associated with the NFC event.
+ */
+ public final NfcAdapter nfcAdapter;
+
+ NfcEvent(NfcAdapter nfcAdapter) {
+ this.nfcAdapter = nfcAdapter;
+ }
+}
diff --git a/core/java/android/nfc/NfcFragment.java b/core/java/android/nfc/NfcFragment.java
new file mode 100644
index 0000000000000..c48859b1c6e76
--- /dev/null
+++ b/core/java/android/nfc/NfcFragment.java
@@ -0,0 +1,83 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+import android.app.Activity;
+import android.app.Fragment;
+import android.app.FragmentManager;
+
+/**
+ * Used by {@link NfcActivityManager} to attach to activity life-cycle.
+ * @hide
+ */
+public final class NfcFragment extends Fragment {
+ static final String FRAGMENT_TAG = "android.nfc.NfcFragment";
+
+ // only used on UI thread
+ static boolean sIsInitialized = false;
+ static NfcActivityManager sNfcActivityManager;
+
+ /**
+ * Attach NfcFragment to an activity (if not already attached).
+ */
+ public static void attach(Activity activity) {
+ FragmentManager manager = activity.getFragmentManager();
+ if (manager.findFragmentByTag(FRAGMENT_TAG) == null) {
+ manager.beginTransaction().add(new NfcFragment(), FRAGMENT_TAG).commit();
+ }
+ }
+
+ /**
+ * Remove NfcFragment from activity.
+ */
+ public static void remove(Activity activity) {
+ FragmentManager manager = activity.getFragmentManager();
+ Fragment fragment = manager.findFragmentByTag(FRAGMENT_TAG);
+ if (fragment != null) {
+ manager.beginTransaction().remove(fragment).commit();
+ }
+ }
+
+ @Override
+ public void onAttach(Activity activity) {
+ super.onAttach(activity);
+ if (!sIsInitialized) {
+ sIsInitialized = true;
+ NfcAdapter adapter = NfcAdapter.getDefaultAdapter(
+ activity.getApplicationContext());
+ if (adapter != null) {
+ sNfcActivityManager = adapter.mNfcActivityManager;
+ }
+ }
+ }
+
+ @Override
+ public void onResume() {
+ super.onResume();
+ if (sNfcActivityManager != null) {
+ sNfcActivityManager.onResume(getActivity());
+ }
+ }
+
+ @Override
+ public void onPause() {
+ super.onPause();
+ if (sNfcActivityManager != null) {
+ sNfcActivityManager.onPause(getActivity());
+ }
+ }
+}
diff --git a/core/java/android/nfc/NfcManager.java b/core/java/android/nfc/NfcManager.java
index 5fa6483510230..300ab45460e2c 100644
--- a/core/java/android/nfc/NfcManager.java
+++ b/core/java/android/nfc/NfcManager.java
@@ -40,7 +40,7 @@ public final class NfcManager {
public NfcManager(Context context) {
NfcAdapter adapter;
try {
- adapter = new NfcAdapter(context);
+ adapter = NfcAdapter.getSingleton();
} catch (UnsupportedOperationException e) {
adapter = null;
}
{@link #isEnabled()} && {@link #isZeroClickEnabled()}
+ * {@link #isEnabled()} && {@link #isNdefPushEnabled()}
*
- * @return true if zero-click sharing is enabled
+ * @return true if NDEF Push feature is enabled
* @hide
*/
- public boolean isZeroClickEnabled() {
+ public boolean isNdefPushEnabled() {
try {
- return sService.isZeroClickEnabled();
+ return sService.isNdefPushEnabled();
} catch (RemoteException e) {
attemptDeadServiceRecovery(e);
return false;
@@ -793,4 +846,10 @@ public final class NfcAdapter {
return null;
}
}
+
+ void enforceResumed(Activity activity) {
+ if (!activity.isResumed()) {
+ throw new IllegalStateException("API cannot be called while activity is paused");
+ }
+ }
}
diff --git a/core/java/android/nfc/NfcEvent.java b/core/java/android/nfc/NfcEvent.java
new file mode 100644
index 0000000000000..b00d8b755b039
--- /dev/null
+++ b/core/java/android/nfc/NfcEvent.java
@@ -0,0 +1,44 @@
+/*
+ * Copyright (C) 2011 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package android.nfc;
+
+/**
+ * Wraps information associated with any NFC event.
+ *
+ *