1 /*
2  * Copyright 2018 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 
17 package androidx.wear.activity;
18 
19 import android.app.Activity;
20 import android.content.Intent;
21 import android.os.Bundle;
22 import android.util.SparseIntArray;
23 
24 import androidx.wear.R;
25 import androidx.wear.widget.ConfirmationOverlay;
26 
27 /**
28  * This Activity is used to display confirmation animations after the user completes an action on
29  * the wearable. There are three types of confirmations: Success: the action was completed
30  * successfully on the wearable. Failure: the action failed to complete. Open on Phone: the action
31  * has caused something to display on the phone, or in order to complete the action, the user will
32  * need to go to their phone to continue.
33  *
34  * <p>It is the responsibility of the wearable application developer to determine whether the action
35  * has succeeded, failed, or requires the user to go to their phone, and trigger the appropriate
36  * confirmation.
37  *
38  * <p>To configure the confirmation according to the result of the action, set the extra {@link
39  * #EXTRA_ANIMATION_TYPE} to one of the following values:
40  *
41  * <dl>
42  * <dt>{@link #SUCCESS_ANIMATION}
43  * <dd>Displays a positive confirmation animation with an optional message.
44  * <dt>{@link #OPEN_ON_PHONE_ANIMATION}
45  * <dd>Displays an animation indicating an action has been sent to a paired device.
46  * <dt>{@link #FAILURE_ANIMATION}
47  * <dd>Displays a generic failure page with an optional message.
48  * </dl>
49  *
50  * <p>An optional message, included in the extra {@link #EXTRA_MESSAGE} will be displayed
51  * horizontally centered below the animation.
52  *
53  * <p>An optional duration in milliseconds to keep the confirmation activity visible for, included
54  * in the extra {@link #EXTRA_ANIMATION_DURATION_MILLIS}
55  */
56 public class ConfirmationActivity extends Activity {
57 
58     /**
59      * Used as a string extra field on an intent for this activity to define the message that
60      * should be displayed to the user while the activity is visible.
61      */
62     public static final String EXTRA_MESSAGE = "androidx.wear.activity.extra.MESSAGE";
63 
64     /**
65      * The lookup key for an optional int that defines the animation type that should be
66      * displayed. Should be one of  {@link #SUCCESS_ANIMATION}, {@link #OPEN_ON_PHONE_ANIMATION},
67      * or {@link #FAILURE_ANIMATION}
68      *
69      * <p>If no value is specified it will default to {@link #SUCCESS_ANIMATION}
70      */
71     public static final String EXTRA_ANIMATION_TYPE =
72             "androidx.wear.activity.extra.ANIMATION_TYPE";
73 
74     /**
75      * The lookup key for an optional int that defines the duration in milliseconds that the
76      * confirmation activity should be displayed.
77      *
78      * If no value is specified it will default to
79      * {@link ConfirmationOverlay#DEFAULT_ANIMATION_DURATION_MS}
80      */
81     public static final String EXTRA_ANIMATION_DURATION_MILLIS =
82             "androidx.wear.activity.extra.ANIMATION_DURATION_MILLIS";
83 
84     public static final int SUCCESS_ANIMATION = 1;
85     public static final int OPEN_ON_PHONE_ANIMATION = 2;
86     public static final int FAILURE_ANIMATION = 3;
87 
88     /** Default animation duration in milliseconds. */
89     static final int DEFAULT_ANIMATION_DURATION_MILLIS =
90             ConfirmationOverlay.DEFAULT_ANIMATION_DURATION_MS;
91 
92     private static final SparseIntArray CONFIRMATION_OVERLAY_TYPES = new SparseIntArray();
93 
94     static {
CONFIRMATION_OVERLAY_TYPES.append(SUCCESS_ANIMATION, ConfirmationOverlay.SUCCESS_ANIMATION)95         CONFIRMATION_OVERLAY_TYPES.append(SUCCESS_ANIMATION, ConfirmationOverlay.SUCCESS_ANIMATION);
CONFIRMATION_OVERLAY_TYPES.append( OPEN_ON_PHONE_ANIMATION, ConfirmationOverlay.OPEN_ON_PHONE_ANIMATION)96         CONFIRMATION_OVERLAY_TYPES.append(
97                 OPEN_ON_PHONE_ANIMATION, ConfirmationOverlay.OPEN_ON_PHONE_ANIMATION);
CONFIRMATION_OVERLAY_TYPES.append(FAILURE_ANIMATION, ConfirmationOverlay.FAILURE_ANIMATION)98         CONFIRMATION_OVERLAY_TYPES.append(FAILURE_ANIMATION, ConfirmationOverlay.FAILURE_ANIMATION);
99     }
100 
101     @Override
onCreate(Bundle savedInstanceState)102     public void onCreate(Bundle savedInstanceState) {
103         super.onCreate(savedInstanceState);
104         setTheme(R.style.ConfirmationActivity);
105 
106         Intent intent = getIntent();
107 
108         int requestedType = intent.getIntExtra(EXTRA_ANIMATION_TYPE, SUCCESS_ANIMATION);
109         int animationDurationMillis = intent.getIntExtra(EXTRA_ANIMATION_DURATION_MILLIS,
110                 DEFAULT_ANIMATION_DURATION_MILLIS);
111         if (CONFIRMATION_OVERLAY_TYPES.indexOfKey(requestedType) < 0) {
112             throw new IllegalArgumentException("Unknown type of animation: " + requestedType);
113         }
114 
115         @ConfirmationOverlay.OverlayType int type = CONFIRMATION_OVERLAY_TYPES.get(requestedType);
116         CharSequence message = intent.getStringExtra(EXTRA_MESSAGE);
117         if (message == null) {
118             message = "";
119         }
120 
121         new ConfirmationOverlay()
122                 .setType(type)
123                 .setMessage(message)
124                 .setDuration(animationDurationMillis)
125                 .setOnAnimationFinishedListener(
126                         new ConfirmationOverlay.OnAnimationFinishedListener() {
127                             @Override
128                             public void onAnimationFinished() {
129                                 ConfirmationActivity.this.onAnimationFinished();
130                             }
131                         })
132                 .showOn(this);
133     }
134 
135     /**
136      * Override this method if you wish to provide different than out-of-the-box behavior when the
137      * confirmation animation finishes. By default this method will finish the ConfirmationActivity.
138      */
onAnimationFinished()139     protected void onAnimationFinished() {
140         finish();
141     }
142 }
143