diff options
author | Martijn Coenen <maco@google.com> | 2013-03-05 18:56:27 +0000 |
---|---|---|
committer | Android (Google) Code Review <android-gerrit@google.com> | 2013-03-05 18:56:28 +0000 |
commit | 1f9744ddc418ae0d13dd2e71fe8442afe2222611 (patch) | |
tree | 3b89f24cd5c72ff4a0175460c3a8a04df0a38af8 | |
parent | 836c5dac9017af8cd41f232c50985ff2b3a21810 (diff) | |
parent | 1a158c7f354d1e1b031fba88928dbaa022e0d0df (diff) | |
download | android_packages_apps_Nfc-1f9744ddc418ae0d13dd2e71fe8442afe2222611.tar.gz android_packages_apps_Nfc-1f9744ddc418ae0d13dd2e71fe8442afe2222611.tar.bz2 android_packages_apps_Nfc-1f9744ddc418ae0d13dd2e71fe8442afe2222611.zip |
Merge "Make Beam more forgiving." into jb-mr2-dev
-rw-r--r-- | res/layout/screenshot.xml | 33 | ||||
-rwxr-xr-x | res/values/strings.xml | 1 | ||||
-rw-r--r-- | src/com/android/nfc/P2pEventManager.java | 13 | ||||
-rwxr-xr-x | src/com/android/nfc/P2pLinkManager.java | 56 | ||||
-rw-r--r-- | src/com/android/nfc/SendUi.java | 59 |
5 files changed, 153 insertions, 9 deletions
diff --git a/res/layout/screenshot.xml b/res/layout/screenshot.xml index 24a3a71d..2523e500 100644 --- a/res/layout/screenshot.xml +++ b/res/layout/screenshot.xml @@ -49,5 +49,36 @@ android:layout_width="match_parent" android:layout_height="match_parent" android:gravity="center" - /> + /> + <ImageView android:id="@+id/blacklayer" + android:layout_width="match_parent" + android:layout_height="match_parent" + android:background="#ff000000" + android:visibility="gone" + /> + <LinearLayout + android:layout_width="match_parent" + android:layout_height="match_parent" + android:orientation="horizontal" + > + <View + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="0.25" + /> + <TextView android:id="@+id/retrytext" + android:layout_width="0dp" + android:layout_height="match_parent" + android:layout_weight="0.5" + android:gravity="center" + android:textAppearance="?android:attr/textAppearanceLarge" + android:background="@null" + android:textColor="@android:color/holo_blue_light" + /> + <View + android:layout_width="0dp" + android:layout_height="0dp" + android:layout_weight="0.25" + /> + </LinearLayout> </FrameLayout> diff --git a/res/values/strings.xml b/res/values/strings.xml index a4bda3b9..b9449376 100755 --- a/res/values/strings.xml +++ b/res/values/strings.xml @@ -27,6 +27,7 @@ <string name="cancel">Cancel</string> <string name="beam_touch_to_view">Touch to view</string> <string name="beam_handover_not_supported">The receiver\'s device doesn\'t support large file transfer via beam.</string> + <string name="beam_try_again">Bring devices together again</string> <string name="connecting_headset">Connecting</string> <string name="connected_headset">Connected</string> diff --git a/src/com/android/nfc/P2pEventManager.java b/src/com/android/nfc/P2pEventManager.java index 68f479b8..65e428ea 100644 --- a/src/com/android/nfc/P2pEventManager.java +++ b/src/com/android/nfc/P2pEventManager.java @@ -144,4 +144,17 @@ public class P2pEventManager implements P2pEventListener, SendUi.Callback { mSending = true; } + + @Override + public void onP2pSendDebounce() { + mNfcService.playSound(NfcService.SOUND_ERROR); + mSendUi.showSendHint(); + } + + @Override + public void onP2pResumeSend() { + mVibrator.vibrate(VIBRATION_PATTERN, -1); + mNfcService.playSound(NfcService.SOUND_START); + mSendUi.showStartSend(); + } } diff --git a/src/com/android/nfc/P2pLinkManager.java b/src/com/android/nfc/P2pLinkManager.java index 0b3fc736..b25b41d2 100755 --- a/src/com/android/nfc/P2pLinkManager.java +++ b/src/com/android/nfc/P2pLinkManager.java @@ -76,6 +76,20 @@ interface P2pEventListener { public void onP2pSendComplete(); /** + * + * Called to indicate the link has broken while we were trying to send + * a message. We'll start a debounce timer for the user to get the devices + * back together. UI may show a hint to achieve that + */ + public void onP2pSendDebounce(); + + /** + * Called to indicate a link has come back up after being temporarily + * broken, and sending is resuming + */ + public void onP2pResumeSend(); + + /** * Called to indicate the remote device does not support connection handover */ public void onP2pHandoverNotSupported(); @@ -124,8 +138,10 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba static final int NDEFPUSH_SAP = 0x10; static final int HANDOVER_SAP = 0x14; - static final int LINK_DEBOUNCE_MS = 750; - + static final int LINK_NOTHING_TO_SEND_DEBOUNCE_MS = 750; + static final int LINK_SEND_PENDING_DEBOUNCE_MS = 3000; + static final int LINK_SEND_CONFIRMED_DEBOUNCE_MS = 5000; + static final int LINK_SEND_COMPLETE_DEBOUNCE_MS = 250; static final int MSG_DEBOUNCE_TIMEOUT = 1; static final int MSG_RECEIVE_COMPLETE = 2; static final int MSG_RECEIVE_HANDOVER = 3; @@ -137,12 +153,13 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba // values for mLinkState static final int LINK_STATE_DOWN = 1; static final int LINK_STATE_UP = 2; - static final int LINK_STATE_DEBOUNCE =3; + static final int LINK_STATE_DEBOUNCE = 3; // values for mSendState static final int SEND_STATE_NOTHING_TO_SEND = 1; static final int SEND_STATE_NEED_CONFIRMATION = 2; static final int SEND_STATE_SENDING = 3; + static final int SEND_STATE_SEND_COMPLETE = 4; // return values for doSnepProtocol static final int SNEP_SUCCESS = 0; @@ -263,7 +280,6 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba if (mEchoServer != null) { mEchoServer.onLlcpActivated(); } - switch (mLinkState) { case LINK_STATE_DOWN: mLinkState = LINK_STATE_UP; @@ -442,7 +458,26 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba case LINK_STATE_UP: // Debounce mLinkState = LINK_STATE_DEBOUNCE; - mHandler.sendEmptyMessageDelayed(MSG_DEBOUNCE_TIMEOUT, LINK_DEBOUNCE_MS); + int debounceTimeout = 0; + switch (mSendState) { + case SEND_STATE_NOTHING_TO_SEND: + debounceTimeout = 0; + break; + case SEND_STATE_NEED_CONFIRMATION: + debounceTimeout = LINK_SEND_PENDING_DEBOUNCE_MS; + break; + case SEND_STATE_SENDING: + debounceTimeout = LINK_SEND_CONFIRMED_DEBOUNCE_MS; + break; + case SEND_STATE_SEND_COMPLETE: + debounceTimeout = LINK_SEND_COMPLETE_DEBOUNCE_MS; + break; + } + mHandler.sendEmptyMessageDelayed(MSG_DEBOUNCE_TIMEOUT, debounceTimeout); + if (mSendState == SEND_STATE_SENDING) { + Log.e(TAG, "onP2pSendDebounce()"); + mEventListener.onP2pSendDebounce(); + } cancelSendNdefMessage(); disconnectLlcpServices(); break; @@ -502,6 +537,7 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba mLlcpServicesConnected = true; if (mSendState == SEND_STATE_SENDING) { // Send was previously confirmed, we probably cycled through a debounce + mEventListener.onP2pResumeSend(); sendNdefMessage(); } else { // User still needs to confirm, or we may have received something already. @@ -840,7 +876,8 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba if (mLinkState == LINK_STATE_DOWN || mSendState != SEND_STATE_SENDING) { break; } - mSendState = SEND_STATE_NOTHING_TO_SEND; + mSendState = SEND_STATE_SEND_COMPLETE; + mHandler.removeMessages(MSG_DEBOUNCE_TIMEOUT); if (DBG) Log.d(TAG, "onP2pSendComplete()"); mEventListener.onP2pSendComplete(); if (mCallbackNdef != null) { @@ -924,6 +961,13 @@ public class P2pLinkManager implements Handler.Callback, P2pEventListener.Callba mSendState = SEND_STATE_SENDING; if (mLinkState == LINK_STATE_UP && mLlcpServicesConnected) { sendNdefMessage(); + } else if (mLinkState == LINK_STATE_DEBOUNCE) { + // Restart debounce timeout + mHandler.removeMessages(MSG_DEBOUNCE_TIMEOUT); + mHandler.sendEmptyMessageDelayed(MSG_DEBOUNCE_TIMEOUT, + LINK_SEND_CONFIRMED_DEBOUNCE_MS); + // Tell user to tap devices again + mEventListener.onP2pSendDebounce(); } } } diff --git a/src/com/android/nfc/SendUi.java b/src/com/android/nfc/SendUi.java index 7839ed62..d153a626 100644 --- a/src/com/android/nfc/SendUi.java +++ b/src/com/android/nfc/SendUi.java @@ -43,6 +43,7 @@ import android.view.View; import android.view.ViewGroup; import android.view.WindowManager; import android.view.animation.AccelerateDecelerateInterpolator; +import android.view.animation.AccelerateInterpolator; import android.view.animation.DecelerateInterpolator; import android.widget.ImageView; import android.widget.TextView; @@ -90,6 +91,9 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, static final int SLIDE_OUT_DURATION_MS = 300; + static final float[] BLACK_LAYER_ALPHA_DOWN_RANGE = {0.9f, 0.0f}; + static final float[] BLACK_LAYER_ALPHA_UP_RANGE = {0.0f, 0.9f}; + static final float[] TEXT_HINT_ALPHA_RANGE = {0.0f, 1.0f}; static final int TEXT_HINT_ALPHA_DURATION_MS = 500; static final int TEXT_HINT_ALPHA_START_DELAY_MS = 300; @@ -108,8 +112,10 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, final StatusBarManager mStatusBarManager; final View mScreenshotLayout; final ImageView mScreenshotView; + final ImageView mBlackLayer; final TextureView mTextureView; final TextView mTextHint; + final TextView mTextRetry; final Callback mCallback; // The mFrameCounter animation is purely used to count down a certain @@ -129,6 +135,8 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, final ObjectAnimator mFadeInAnimator; final ObjectAnimator mHintAnimator; final ObjectAnimator mScaleUpAnimator; + final ObjectAnimator mAlphaDownAnimator; + final ObjectAnimator mAlphaUpAnimator; final AnimatorSet mSuccessAnimatorSet; // Besides animating the screenshot, the Beam UI also renders @@ -177,7 +185,8 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mScreenshotLayout.setFocusable(true); mTextHint = (TextView) mScreenshotLayout.findViewById(R.id.calltoaction); - + mTextRetry = (TextView) mScreenshotLayout.findViewById(R.id.retrytext); + mBlackLayer = (ImageView) mScreenshotLayout.findViewById(R.id.blacklayer); mTextureView = (TextureView) mScreenshotLayout.findViewById(R.id.fireflies); mTextureView.setSurfaceTextureListener(this); @@ -245,6 +254,16 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mHintAnimator.setDuration(TEXT_HINT_ALPHA_DURATION_MS); mHintAnimator.setStartDelay(TEXT_HINT_ALPHA_START_DELAY_MS); + alphaDown = PropertyValuesHolder.ofFloat("alpha", BLACK_LAYER_ALPHA_DOWN_RANGE); + mAlphaDownAnimator = ObjectAnimator.ofPropertyValuesHolder(mBlackLayer, alphaDown); + mAlphaDownAnimator.setInterpolator(new DecelerateInterpolator()); + mAlphaDownAnimator.setDuration(400); + + alphaUp = PropertyValuesHolder.ofFloat("alpha", BLACK_LAYER_ALPHA_UP_RANGE); + mAlphaUpAnimator = ObjectAnimator.ofPropertyValuesHolder(mBlackLayer, alphaUp); + mAlphaUpAnimator.setInterpolator(new DecelerateInterpolator()); + mAlphaUpAnimator.setDuration(200); + mSuccessAnimatorSet = new AnimatorSet(); mSuccessAnimatorSet.playSequentially(mFastSendAnimator, mFadeInAnimator); @@ -271,6 +290,8 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, if (mScreenshotBitmap == null || mAttached) { return; } + mBlackLayer.setVisibility(View.GONE); + mBlackLayer.setAlpha(0f); mScreenshotView.setOnTouchListener(this); mScreenshotView.setImageBitmap(mScreenshotBitmap); mScreenshotView.setTranslationX(0f); @@ -279,6 +300,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mScreenshotLayout.requestFocus(); + mTextHint.setText(mContext.getResources().getString(R.string.touch)); mTextHint.setAlpha(0.0f); mTextHint.setVisibility(View.VISIBLE); mHintAnimator.start(); @@ -323,6 +345,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, public void showStartSend() { if (!mAttached) return; + mTextRetry.setVisibility(View.GONE); // Update the starting scale - touchscreen-mashers may trigger // this before the pre-animation completes. float currentScale = mScreenshotView.getScaleX(); @@ -332,6 +355,14 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, new float[] {currentScale, 0.0f}); mSlowSendAnimator.setValues(postX, postY); + + float currentAlpha = mBlackLayer.getAlpha(); + if (mBlackLayer.isShown() && currentAlpha > 0.0f) { + PropertyValuesHolder alphaDown = PropertyValuesHolder.ofFloat("alpha", + new float[] {currentAlpha, 0.0f}); + mAlphaDownAnimator.setValues(alphaDown); + mAlphaDownAnimator.start(); + } mSlowSendAnimator.start(); } @@ -352,11 +383,13 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, } mTextHint.setVisibility(View.GONE); + mTextRetry.setVisibility(View.GONE); float currentScale = mScreenshotView.getScaleX(); float currentAlpha = mScreenshotView.getAlpha(); if (finishMode == FINISH_SCALE_UP) { + mBlackLayer.setVisibility(View.GONE); PropertyValuesHolder scaleUpX = PropertyValuesHolder.ofFloat("scaleX", new float[] {currentScale, 1.0f}); PropertyValuesHolder scaleUpY = PropertyValuesHolder.ofFloat("scaleY", @@ -373,7 +406,7 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, PropertyValuesHolder postY = PropertyValuesHolder.ofFloat("scaleY", new float[] {currentScale, 0.0f}); PropertyValuesHolder alpha = PropertyValuesHolder.ofFloat("alpha", - new float[] {1.0f, 0.0f}); + new float[] {currentAlpha, 0.0f}); mFastSendAnimator.setValues(postX, postY, alpha); // Reset the fadeIn parameters to start from alpha 1 @@ -399,6 +432,8 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, mFastSendAnimator.cancel(); mSuccessAnimatorSet.cancel(); mScaleUpAnimator.cancel(); + mAlphaUpAnimator.cancel(); + mAlphaDownAnimator.cancel(); mWindowManager.removeView(mScreenshotLayout); mStatusBarManager.disable(StatusBarManager.DISABLE_NONE); releaseScreenshot(); @@ -595,4 +630,24 @@ public class SendUi implements Animator.AnimatorListener, View.OnTouchListener, @Override public void onSurfaceTextureUpdated(SurfaceTexture surface) { } + public void showSendHint() { + if (mAlphaDownAnimator.isRunning()) { + mAlphaDownAnimator.cancel(); + } + if (mSlowSendAnimator.isRunning()) { + mSlowSendAnimator.cancel(); + } + mBlackLayer.setScaleX(mScreenshotView.getScaleX()); + mBlackLayer.setScaleY(mScreenshotView.getScaleY()); + mBlackLayer.setVisibility(View.VISIBLE); + mTextHint.setVisibility(View.GONE); + + mTextRetry.setText(mContext.getResources().getString(R.string.beam_try_again)); + mTextRetry.setVisibility(View.VISIBLE); + + PropertyValuesHolder alphaUp = PropertyValuesHolder.ofFloat("alpha", + new float[] {mBlackLayer.getAlpha(), 0.9f}); + mAlphaUpAnimator.setValues(alphaUp); + mAlphaUpAnimator.start(); + } } |