• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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 com.example.android.leanback;
18 
19 import android.app.Activity;
20 import android.app.Fragment;
21 import android.app.FragmentManager;
22 import android.content.Context;
23 import android.content.res.Configuration;
24 import android.graphics.drawable.Drawable;
25 import android.os.Bundle;
26 import android.support.v17.leanback.app.GuidedStepFragment;
27 import android.support.v17.leanback.widget.GuidanceStylist;
28 import android.support.v17.leanback.widget.GuidanceStylist.Guidance;
29 import android.support.v17.leanback.widget.GuidedAction;
30 import android.support.v17.leanback.widget.GuidedActionsStylist;
31 import android.support.v17.leanback.widget.GuidedDatePickerAction;
32 import android.support.v4.content.res.ResourcesCompat;
33 import android.text.InputType;
34 import android.text.TextUtils;
35 import android.util.Log;
36 import android.view.LayoutInflater;
37 import android.view.View;
38 import android.view.ViewGroup;
39 import android.view.inputmethod.EditorInfo;
40 
41 import java.util.ArrayList;
42 import java.util.Calendar;
43 import java.util.List;
44 
45 /**
46  * Activity that showcases different aspects of GuidedStepFragments.
47  */
48 public class GuidedStepActivity extends Activity {
49 
50     private static final int BACK = 2;
51 
52     private static final int FIRST_NAME = 3;
53     private static final int LAST_NAME = 4;
54     private static final int PASSWORD = 5;
55     private static final int PAYMENT = 6;
56     private static final int NEW_PAYMENT = 7;
57     private static final int PAYMENT_EXPIRE = 8;
58 
59     private static final long RADIO_ID_BASE = 0;
60     private static final long CHECKBOX_ID_BASE = 100;
61 
62     private static final long DEFAULT_OPTION = RADIO_ID_BASE;
63 
64     private static final String[] OPTION_NAMES = { "Option A", "Option B", "Option C" };
65     private static final String[] OPTION_DESCRIPTIONS = { "Here's one thing you can do",
66             "Here's another thing you can do", "Here's one more thing you can do" };
67 
68     private static final String TAG = GuidedStepActivity.class.getSimpleName();
69 
70     @Override
onCreate(Bundle savedInstanceState)71     protected void onCreate(Bundle savedInstanceState) {
72         Log.v(TAG, "onCreate");
73         super.onCreate(savedInstanceState);
74         setContentView(R.layout.guided_step_activity);
75         if (savedInstanceState == null) {
76             GuidedStepFragment.addAsRoot(this, new FirstStepFragment(), R.id.lb_guidedstep_host);
77         }
78     }
79 
80     @Override
onConfigurationChanged(Configuration newConfig)81     public void onConfigurationChanged(Configuration newConfig) {
82         Log.v(TAG, "onConfigurationChanged");
83         super.onConfigurationChanged(newConfig);
84     }
85 
86     @Override
onSaveInstanceState(Bundle outState)87     protected void onSaveInstanceState(Bundle outState) {
88         Log.v(TAG, "onSaveInstanceState");
89         super.onSaveInstanceState(outState);
90     }
91 
92     @Override
onRestoreInstanceState(Bundle savedInstanceState)93     protected void onRestoreInstanceState(Bundle savedInstanceState) {
94         Log.v(TAG, "onRestoreInstanceState");
95         super.onRestoreInstanceState(savedInstanceState);
96     }
97 
addAction(List<GuidedAction> actions, long id, String title, String desc)98     private static GuidedAction addAction(List<GuidedAction> actions, long id, String title,
99             String desc) {
100         GuidedAction action;
101         actions.add(action = new GuidedAction.Builder(null)
102                 .id(id)
103                 .title(title)
104                 .description(desc)
105                 .build());
106         return action;
107     }
108 
addAction(List<GuidedAction> actions, long id, String title, String desc, List<GuidedAction> subActions)109     private static GuidedAction addAction(List<GuidedAction> actions, long id, String title,
110             String desc, List<GuidedAction> subActions) {
111         GuidedAction action;
112         actions.add(action = new GuidedAction.Builder(null)
113                 .id(id)
114                 .title(title)
115                 .description(desc)
116                 .subActions(subActions)
117                 .build());
118         return action;
119     }
120 
addEditableAction(Context context, List<GuidedAction> actions, long id, String title, String desc)121     private static GuidedAction addEditableAction(Context context, List<GuidedAction> actions,
122             long id, String title, String desc) {
123         GuidedAction action;
124         actions.add(action = new GuidedAction.Builder(context)
125                 .id(id)
126                 .title(title)
127                 .description(desc)
128                 .editable(true)
129                 .icon(R.drawable.lb_ic_search_mic)
130                 .build());
131         return action;
132     }
133 
addEditableAction(List<GuidedAction> actions, long id, String title, String editTitle, String desc)134     private static GuidedAction addEditableAction(List<GuidedAction> actions, long id, String title,
135             String editTitle, String desc) {
136         GuidedAction action;
137         actions.add(action = new GuidedAction.Builder(null)
138                 .id(id)
139                 .title(title)
140                 .editTitle(editTitle)
141                 .description(desc)
142                 .editable(true)
143                 .build());
144         return action;
145     }
146 
addEditableAction(List<GuidedAction> actions, long id, String title, String editTitle, int editInputType, String desc, String editDesc)147     private static GuidedAction addEditableAction(List<GuidedAction> actions, long id, String title,
148             String editTitle, int editInputType, String desc, String editDesc) {
149         GuidedAction action;
150         actions.add(action = new GuidedAction.Builder(null)
151                 .id(id)
152                 .title(title)
153                 .editTitle(editTitle)
154                 .editInputType(editInputType)
155                 .description(desc)
156                 .editDescription(editDesc)
157                 .editable(true)
158                 .build());
159         return action;
160     }
161 
addDatePickerAction(List<GuidedAction> actions, long id, String title)162     private static GuidedDatePickerAction addDatePickerAction(List<GuidedAction> actions, long id,
163             String title) {
164         GuidedDatePickerAction action;
165         actions.add(action = new GuidedDatePickerAction.Builder(null)
166                 .id(id)
167                 .title(title)
168                 .datePickerFormat("MY")
169                 .build());
170         return action;
171     }
172 
addEditableDescriptionAction(List<GuidedAction> actions, long id, String title, String desc, String editDescription, int descriptionEditInputType)173     private static GuidedAction addEditableDescriptionAction(List<GuidedAction> actions, long id,
174             String title, String desc, String editDescription, int descriptionEditInputType) {
175         GuidedAction action;
176         actions.add(action = new GuidedAction.Builder(null)
177                 .id(id)
178                 .title(title)
179                 .description(desc)
180                 .editDescription(editDescription)
181                 .descriptionEditInputType(descriptionEditInputType)
182                 .descriptionEditable(true)
183                 .build());
184         return action;
185     }
186 
addCheckedAction(List<GuidedAction> actions, long id, String title, String desc, int checkSetId)187     private static GuidedAction addCheckedAction(List<GuidedAction> actions, long id,
188             String title, String desc, int checkSetId) {
189         GuidedAction action;
190         actions.add(action = new GuidedAction.Builder(null)
191                 .id(id)
192                 .title(title)
193                 .description(desc)
194                 .checkSetId(checkSetId)
195                 .build());
196         return action;
197     }
198 
199     public static class FirstStepFragment extends GuidedStepFragment {
200 
201         @Override
onProvideTheme()202         public int onProvideTheme() {
203             return R.style.Theme_Example_Leanback_GuidedStep_First;
204         }
205 
206         @Override
onCreateGuidance(Bundle savedInstanceState)207         public Guidance onCreateGuidance(Bundle savedInstanceState) {
208             String title = getString(R.string.guidedstep_first_title);
209             String breadcrumb = getString(R.string.guidedstep_first_breadcrumb);
210             String description = getString(R.string.guidedstep_first_description);
211             final Context context = getActivity();
212             Drawable icon = ResourcesCompat.getDrawable(context.getResources(),
213                     R.drawable.ic_main_icon, context.getTheme());
214             return new Guidance(title, description, breadcrumb, icon);
215         }
216 
217         @Override
onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState)218         public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
219             Context context = getActivity();
220             actions.add(new GuidedAction.Builder(context)
221                     .clickAction(GuidedAction.ACTION_ID_CONTINUE)
222                     .description("Let's do it")
223                     .build());
224             actions.add(new GuidedAction.Builder(context)
225                     .clickAction(GuidedAction.ACTION_ID_CANCEL)
226                     .description("Never mind")
227                     .build());
228         }
229 
230         @Override
onGuidedActionClicked(GuidedAction action)231         public void onGuidedActionClicked(GuidedAction action) {
232             FragmentManager fm = getFragmentManager();
233             if (action.getId() == GuidedAction.ACTION_ID_CONTINUE) {
234                 GuidedStepFragment.add(fm, new SecondStepFragment(), R.id.lb_guidedstep_host);
235             } else if (action.getId() == GuidedAction.ACTION_ID_CANCEL){
236                 finishGuidedStepFragments();
237             }
238         }
239     }
240 
241     public interface NewPaymentFragmentTarget {
onNewPaymentFragmentStarted()242         void onNewPaymentFragmentStarted();
onNewPaymentAdded(int selection)243         void onNewPaymentAdded(int selection);
244     }
245 
246     static ArrayList<String> sCards = new ArrayList<String>();
247     static int sSelectedCard = -1;
248     static {
249         sCards.add("Visa-1234");
250         sCards.add("Master-4321");
251     }
252 
253     public static class NewPaymentStepFragment extends GuidedStepFragment {
254 
255         NewPaymentFragmentTarget mNewPaymentTarget;
256 
257         @Override
onCreate(Bundle savedInstance)258         public void onCreate(Bundle savedInstance) {
259             super.onCreate(savedInstance);
260             Fragment targetFragment = getTargetFragment();
261             if (targetFragment instanceof NewPaymentFragmentTarget) {
262                 mNewPaymentTarget = ((NewPaymentFragmentTarget) targetFragment);
263                 mNewPaymentTarget.onNewPaymentFragmentStarted();
264             }
265         }
266 
267         @Override
onCreateGuidance(Bundle savedInstanceState)268         public Guidance onCreateGuidance(Bundle savedInstanceState) {
269             String title = getString(R.string.guidedstep_newpayment_title);
270             String breadcrumb = getString(R.string.guidedstep_newpayment_breadcrumb);
271             String description = getString(R.string.guidedstep_newpayment_description);
272             final Context context = getActivity();
273             Drawable icon = ResourcesCompat.getDrawable(context.getResources(),
274                     R.drawable.ic_main_icon, context.getTheme());
275             return new Guidance(title, description, breadcrumb, icon);
276         }
277 
278         @Override
onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState)279         public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
280             addEditableAction(actions, NEW_PAYMENT, "Input credit card number", "",
281                     InputType.TYPE_CLASS_NUMBER,
282                     "Input credit card number", "Input credit card number");
283             addDatePickerAction(actions, PAYMENT_EXPIRE, "Exp:");
284         }
285 
286         @Override
onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState)287         public void onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) {
288             Context context = getActivity();
289             actions.add(new GuidedAction.Builder(context).clickAction(GuidedAction.ACTION_ID_OK)
290                     .build());
291             actions.get(actions.size() - 1).setEnabled(false);
292         }
293 
294         @Override
onGuidedActionClicked(GuidedAction action)295         public void onGuidedActionClicked(GuidedAction action) {
296             if (action.getId() == GuidedAction.ACTION_ID_OK) {
297                 CharSequence desc = findActionById(NEW_PAYMENT).getDescription();
298                 String cardNumber = desc.subSequence(desc.length() - 4, desc.length()).toString();
299                 String card;
300                 if ((Integer.parseInt(cardNumber) & 1) == 0) {
301                     card = "Visa "+cardNumber;
302                 } else {
303                     card = "Master "+cardNumber;
304                 }
305                 int selection = sCards.size();
306                 sCards.add(card);
307                 if (mNewPaymentTarget != null) {
308                     mNewPaymentTarget.onNewPaymentAdded(selection);
309                 }
310                 popBackStackToGuidedStepFragment(NewPaymentStepFragment.class,
311                         FragmentManager.POP_BACK_STACK_INCLUSIVE);
312             }
313         }
314 
315         @Override
onGuidedActionEditedAndProceed(GuidedAction action)316         public long onGuidedActionEditedAndProceed(GuidedAction action) {
317             if (action.getId() == NEW_PAYMENT) {
318                 CharSequence editTitle = action.getEditTitle();
319                 if (isCardNumberValid(editTitle)) {
320                     editTitle = editTitle.subSequence(editTitle.length() - 4, editTitle.length());
321                     action.setDescription("Visa XXXX-XXXX-XXXX-" + editTitle);
322                     updateOkButton(isExpDateValid(findActionById(PAYMENT_EXPIRE)));
323                     return GuidedAction.ACTION_ID_NEXT;
324                 } else if (editTitle.length() == 0) {
325                     action.setDescription("Input credit card number");
326                     updateOkButton(false);
327                     return GuidedAction.ACTION_ID_CURRENT;
328                 } else {
329                     action.setDescription("Error credit card number");
330                     updateOkButton(false);
331                     return GuidedAction.ACTION_ID_CURRENT;
332                 }
333             } else if (action.getId() == PAYMENT_EXPIRE) {
334                 updateOkButton(isExpDateValid(action) &&
335                         isCardNumberValid(findActionById(NEW_PAYMENT).getEditTitle()));
336             }
337             return GuidedAction.ACTION_ID_NEXT;
338         }
339 
isCardNumberValid(CharSequence number)340         boolean isCardNumberValid(CharSequence number) {
341             return TextUtils.isDigitsOnly(number) && number.length() == 16;
342         }
343 
isExpDateValid(GuidedAction action)344         boolean isExpDateValid(GuidedAction action) {
345             long date = ((GuidedDatePickerAction) action).getDate();
346             Calendar c = Calendar.getInstance();
347             c.setTimeInMillis(date);
348             return Calendar.getInstance().before(c);
349         }
350 
updateOkButton(boolean enabled)351         void updateOkButton(boolean enabled) {
352             findButtonActionById(GuidedAction.ACTION_ID_OK).setEnabled(enabled);
353             notifyButtonActionChanged(findButtonActionPositionById(GuidedAction.ACTION_ID_OK));
354         }
355     }
356 
357     public static class SecondStepFragment extends GuidedStepFragment
358             implements NewPaymentFragmentTarget {
359 
360 
361         boolean mExpandPaymentListInOnCreateView;
362 
363         @Override
onNewPaymentAdded(int selection)364         public void onNewPaymentAdded(int selection) {
365             // if a new payment is added, we dont need expand the sub actions list.
366             mExpandPaymentListInOnCreateView = false;
367             sSelectedCard = selection;
368             updatePaymentAction(findActionById(PAYMENT));
369             findButtonActionById(GuidedAction.ACTION_ID_CONTINUE).setEnabled(sSelectedCard != -1);
370         }
371 
372         @Override
onNewPaymentFragmentStarted()373         public void onNewPaymentFragmentStarted() {
374             // if a new payment fragment is opened, when come back we should expand the payment
375             // sub actions list unless user created a new payment in onNewPaymentAdded
376             mExpandPaymentListInOnCreateView = true;
377         }
378 
379         @Override
onCreateActionsStylist()380         public GuidedActionsStylist onCreateActionsStylist() {
381             return new GuidedActionsStylist() {
382                 @Override
383                 protected void setupImeOptions(GuidedActionsStylist.ViewHolder vh,
384                         GuidedAction action) {
385                     if (action.getId() == PASSWORD) {
386                         vh.getEditableDescriptionView().setImeActionLabel("Confirm!",
387                                 EditorInfo.IME_ACTION_DONE);
388                     } else {
389                         super.setupImeOptions(vh, action);
390                     }
391                 }
392             };
393         }
394 
395         @Override
396         public Guidance onCreateGuidance(Bundle savedInstanceState) {
397             String title = getString(R.string.guidedstep_second_title);
398             String breadcrumb = getString(R.string.guidedstep_second_breadcrumb);
399             String description = getString(R.string.guidedstep_second_description);
400             final Context context = getActivity();
401             Drawable icon = ResourcesCompat.getDrawable(context.getResources(),
402                     R.drawable.ic_main_icon, context.getTheme());
403             return new Guidance(title, description, breadcrumb, icon);
404         }
405 
406         @Override
407         public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
408             addEditableAction(getActivity(), actions, FIRST_NAME, "Pat", "Your first name");
409             addEditableAction(getActivity(), actions, LAST_NAME, "Smith", "Your last name");
410             List<GuidedAction> subActions = new ArrayList<GuidedAction>();
411             updatePaymentAction(addAction(actions, PAYMENT, "Select Payment", "", subActions));
412             addEditableDescriptionAction(actions, PASSWORD, "Password", "", "",
413                     InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_PASSWORD);
414         }
415 
416         @Override
417         public void onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) {
418             actions.add(new GuidedAction.Builder(getActivity())
419                     .clickAction(GuidedAction.ACTION_ID_CONTINUE)
420                     .description("Continue")
421                     .enabled(isPasswordValid() && isPaymentValid())
422                     .build());
423         }
424 
425         @Override
426         public void onGuidedActionClicked(GuidedAction action) {
427             if (action.getId() == GuidedAction.ACTION_ID_CONTINUE) {
428                 FragmentManager fm = getFragmentManager();
429                 GuidedStepFragment.add(fm, new ThirdStepFragment(), R.id.lb_guidedstep_host);
430             }
431         }
432 
433         void updatePaymentAction(GuidedAction paymentAction) {
434             List<GuidedAction> subActions = paymentAction.getSubActions();
435             subActions.clear();
436             for (int i = 0; i < sCards.size(); i++) {
437                 addCheckedAction(subActions, -1, sCards.get(i), "",
438                         GuidedAction.DEFAULT_CHECK_SET_ID);
439                 if (i == sSelectedCard) {
440                     subActions.get(i).setChecked(true);
441                 }
442             }
443             addAction(subActions, NEW_PAYMENT, "Add New Card", "");
444             paymentAction.setDescription(sSelectedCard == -1 ? "" : sCards.get(sSelectedCard));
445         }
446 
447         @Override
448         public long onGuidedActionEditedAndProceed(GuidedAction action) {
449             if (action.getId() == PASSWORD) {
450                 CharSequence password = action.getEditDescription();
451                 if (password.length() > 0) {
452                     if (isPaymentValid()) {
453                         updateContinue(true);
454                         return GuidedAction.ACTION_ID_NEXT;
455                     } else {
456                         updateContinue(false);
457                         return GuidedAction.ACTION_ID_CURRENT;
458                     }
459                 } else {
460                     updateContinue(false);
461                     return GuidedAction.ACTION_ID_CURRENT;
462                 }
463             }
464             return GuidedAction.ACTION_ID_NEXT;
465         }
466 
467         @Override
468         public boolean onSubGuidedActionClicked(GuidedAction action) {
469             if (action.isChecked()) {
470                 String payment = action.getTitle().toString();
471                 for (int i = 0; i < sCards.size(); i++) {
472                     if (payment.equals(sCards.get(i))) {
473                         sSelectedCard = i;
474                         findActionById(PAYMENT).setDescription(payment);
475                         notifyActionChanged(findActionPositionById(PAYMENT));
476                         updateContinue(isPasswordValid());
477                         break;
478                     }
479                 }
480                 return true;
481             } else {
482                 FragmentManager fm = getFragmentManager();
483                 NewPaymentStepFragment newPaymentFragment = new NewPaymentStepFragment();
484                 newPaymentFragment.setTargetFragment(this, 0);
485                 GuidedStepFragment.add(fm, newPaymentFragment, R.id.lb_guidedstep_host);
486                 return false;
487             }
488         }
489 
490         @Override
491         public View onCreateView(LayoutInflater inflater, ViewGroup container,
492                 Bundle savedInstanceState) {
493             View view = super.onCreateView(inflater, container, savedInstanceState);
494             if (mExpandPaymentListInOnCreateView) {
495                 expandAction(findActionById(PAYMENT), false);
496             }
497             return view;
498         }
499 
500         boolean isPaymentValid() {
501             CharSequence paymentType = findActionById(PAYMENT).getDescription();
502             return (paymentType.length() >= 4 &&
503                     paymentType.subSequence(0, 4).toString().equals("Visa")) ||
504                     (paymentType.length() >= 6 &&
505                     paymentType.subSequence(0, 6).toString().equals("Master"));
506         }
507 
508         boolean isPasswordValid() {
509             return findActionById(PASSWORD).getEditDescription().length() > 0;
510         }
511 
512         void updateContinue(boolean enabled) {
513             findButtonActionById(GuidedAction.ACTION_ID_CONTINUE).setEnabled(enabled);
514             notifyButtonActionChanged(findButtonActionPositionById(
515                     GuidedAction.ACTION_ID_CONTINUE));
516         }
517     }
518 
519     public static class ThirdStepFragment extends GuidedStepFragment {
520 
521         private long mSelectedOption = DEFAULT_OPTION;
522 
523         @Override
524         public Guidance onCreateGuidance(Bundle savedInstanceState) {
525             String title = getString(R.string.guidedstep_third_title);
526             String breadcrumb = getString(R.string.guidedstep_third_breadcrumb);
527             String description = getString(R.string.guidedstep_third_description);
528             final Context context = getActivity();
529             Drawable icon = ResourcesCompat.getDrawable(context.getResources(),
530                     R.drawable.ic_main_icon, context.getTheme());
531             return new Guidance(title, description, breadcrumb, icon);
532         }
533 
534         @Override
535         public GuidanceStylist onCreateGuidanceStylist() {
536             return new GuidanceStylist() {
537                 @Override
538                 public int onProvideLayoutId() {
539                     return R.layout.guidedstep_second_guidance;
540                 }
541             };
542         }
543 
544         @Override
545         public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
546             String desc = "The description can be quite long as well.  " +
547                     "Just be sure to set multilineDescription to true in the GuidedAction.";
548             actions.add(new GuidedAction.Builder(getActivity())
549                     .title("Note that Guided Actions can have titles that are quite long.")
550                     .description(desc)
551                     .multilineDescription(true)
552                     .infoOnly(true)
553                     .enabled(true)
554                     .focusable(false)
555                     .build());
556             for (int i = 0; i < OPTION_NAMES.length; i++) {
557                 addCheckedAction(actions, RADIO_ID_BASE + i, OPTION_NAMES[i],
558                         OPTION_DESCRIPTIONS[i], GuidedAction.DEFAULT_CHECK_SET_ID);
559                 if (i == DEFAULT_OPTION) {
560                     actions.get(actions.size() -1).setChecked(true);
561                 }
562             }
563             for (int i = 0; i < OPTION_NAMES.length; i++) {
564                 addCheckedAction(actions, CHECKBOX_ID_BASE + i, OPTION_NAMES[i],
565                         OPTION_DESCRIPTIONS[i], GuidedAction.CHECKBOX_CHECK_SET_ID);
566             }
567         }
568 
569         @Override
570         public void onCreateButtonActions(List<GuidedAction> actions, Bundle savedInstanceState) {
571             actions.add(new GuidedAction.Builder(getActivity())
572                     .clickAction(GuidedAction.ACTION_ID_CONTINUE)
573                     .build());
574         }
575 
576         @Override
577         public void onGuidedActionClicked(GuidedAction action) {
578             if (action.getId() == GuidedAction.ACTION_ID_CONTINUE) {
579                 FragmentManager fm = getFragmentManager();
580                 FourthStepFragment f = new FourthStepFragment();
581                 Bundle arguments = new Bundle();
582                 arguments.putLong(FourthStepFragment.EXTRA_OPTION, mSelectedOption);
583                 f.setArguments(arguments);
584                 GuidedStepFragment.add(fm, f, R.id.lb_guidedstep_host);
585             } else if (action.getCheckSetId() == GuidedAction.DEFAULT_CHECK_SET_ID) {
586                 mSelectedOption = action.getId();
587             }
588         }
589 
590     }
591 
592     public static class FourthStepFragment extends GuidedStepFragment {
593         public static final String EXTRA_OPTION = "extra_option";
594 
595         public FourthStepFragment() {
596         }
597 
598         public long getOption() {
599             Bundle b = getArguments();
600             if (b == null) return 0;
601             return b.getLong(EXTRA_OPTION, 0);
602         }
603 
604         @Override
605         public Guidance onCreateGuidance(Bundle savedInstanceState) {
606             String title = getString(R.string.guidedstep_fourth_title);
607             String breadcrumb = getString(R.string.guidedstep_fourth_breadcrumb);
608             String description = "You chose: " + OPTION_NAMES[(int) getOption()];
609             final Context context = getActivity();
610             Drawable icon = ResourcesCompat.getDrawable(context.getResources(),
611                     R.drawable.ic_main_icon, context.getTheme());
612             return new Guidance(title, description, breadcrumb, icon);
613         }
614 
615         @Override
616         public void onCreateActions(List<GuidedAction> actions, Bundle savedInstanceState) {
617             actions.add(new GuidedAction.Builder(getActivity())
618                     .clickAction(GuidedAction.ACTION_ID_FINISH)
619                     .description("All Done...")
620                     .build());
621             addAction(actions, BACK, "Start Over", "Let's try this again...");
622         }
623 
624         @Override
625         public void onGuidedActionClicked(GuidedAction action) {
626             if (action.getId() == GuidedAction.ACTION_ID_FINISH) {
627                 finishGuidedStepFragments();
628             } else if (action.getId() == BACK) {
629                 // pop 4, 3, 2
630                 popBackStackToGuidedStepFragment(SecondStepFragment.class,
631                         FragmentManager.POP_BACK_STACK_INCLUSIVE);
632             }
633         }
634 
635     }
636 
637 }
638