• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2015 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.android.tv.onboarding;
18 
19 import android.app.Fragment;
20 import android.content.ActivityNotFoundException;
21 import android.content.ComponentName;
22 import android.content.Context;
23 import android.content.Intent;
24 import android.content.pm.PackageManager;
25 import android.media.tv.TvInputInfo;
26 import android.os.Bundle;
27 import android.support.annotation.NonNull;
28 import android.widget.Toast;
29 import com.android.tv.R;
30 import com.android.tv.SetupPassthroughActivity;
31 import com.android.tv.TvSingletons;
32 import com.android.tv.common.ui.setup.SetupActivity;
33 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
34 import com.android.tv.common.util.CommonUtils;
35 import com.android.tv.common.util.PermissionUtils;
36 import com.android.tv.data.ChannelDataManager;
37 import com.android.tv.util.OnboardingUtils;
38 import com.android.tv.util.SetupUtils;
39 import com.android.tv.util.TvInputManagerHelper;
40 
41 public class OnboardingActivity extends SetupActivity {
42     private static final String KEY_INTENT_AFTER_COMPLETION = "key_intent_after_completion";
43 
44     private static final int PERMISSIONS_REQUEST_READ_TV_LISTINGS = 1;
45 
46     private static final int SHOW_RIPPLE_DURATION_MS = 266;
47 
48     private static final int REQUEST_CODE_START_SETUP_ACTIVITY = 1;
49 
50     private ChannelDataManager mChannelDataManager;
51     private TvInputManagerHelper mInputManager;
52     private SetupUtils mSetupUtils;
53     private final ChannelDataManager.Listener mChannelListener =
54             new ChannelDataManager.Listener() {
55                 @Override
56                 public void onLoadFinished() {
57                     mChannelDataManager.removeListener(this);
58                     mSetupUtils.markNewChannelsBrowsable();
59                 }
60 
61                 @Override
62                 public void onChannelListUpdated() {}
63 
64                 @Override
65                 public void onChannelBrowsableChanged() {}
66             };
67 
68     /**
69      * Returns an intent to start {@link OnboardingActivity}.
70      *
71      * @param context context to create an intent. Should not be {@code null}.
72      * @param intentAfterCompletion intent which will be used to start a new activity when this
73      *     activity finishes. Should not be {@code null}.
74      */
buildIntent( @onNull Context context, @NonNull Intent intentAfterCompletion)75     public static Intent buildIntent(
76             @NonNull Context context, @NonNull Intent intentAfterCompletion) {
77         return new Intent(context, OnboardingActivity.class)
78                 .putExtra(OnboardingActivity.KEY_INTENT_AFTER_COMPLETION, intentAfterCompletion);
79     }
80 
81     @Override
onCreate(Bundle savedInstanceState)82     protected void onCreate(Bundle savedInstanceState) {
83         super.onCreate(savedInstanceState);
84         TvSingletons singletons = TvSingletons.getSingletons(this);
85         mInputManager = singletons.getTvInputManagerHelper();
86         mSetupUtils = singletons.getSetupUtils();
87         if (PermissionUtils.hasAccessAllEpg(this) || PermissionUtils.hasReadTvListings(this)) {
88             mChannelDataManager = singletons.getChannelDataManager();
89             // Make the channels of the new inputs which have been setup outside Live TV
90             // browsable.
91             if (mChannelDataManager.isDbLoadFinished()) {
92                 mSetupUtils.markNewChannelsBrowsable();
93             } else {
94                 mChannelDataManager.addListener(mChannelListener);
95             }
96         } else {
97             requestPermissions(
98                     new String[] {PermissionUtils.PERMISSION_READ_TV_LISTINGS},
99                     PERMISSIONS_REQUEST_READ_TV_LISTINGS);
100         }
101     }
102 
103     @Override
onDestroy()104     protected void onDestroy() {
105         if (mChannelDataManager != null) {
106             mChannelDataManager.removeListener(mChannelListener);
107         }
108         super.onDestroy();
109     }
110 
111     @Override
onCreateInitialFragment()112     protected Fragment onCreateInitialFragment() {
113         if (PermissionUtils.hasAccessAllEpg(this) || PermissionUtils.hasReadTvListings(this)) {
114             return OnboardingUtils.isFirstRunWithCurrentVersion(this)
115                     ? new WelcomeFragment()
116                     : new SetupSourcesFragment();
117         }
118         return null;
119     }
120 
121     @Override
onRequestPermissionsResult( int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults)122     public void onRequestPermissionsResult(
123             int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
124         if (requestCode == PERMISSIONS_REQUEST_READ_TV_LISTINGS) {
125             if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
126                 finish();
127                 Intent intentForNextActivity =
128                         getIntent().getParcelableExtra(KEY_INTENT_AFTER_COMPLETION);
129                 startActivity(buildIntent(this, intentForNextActivity));
130             } else {
131                 Toast.makeText(
132                                 this,
133                                 R.string.msg_read_tv_listing_permission_denied,
134                                 Toast.LENGTH_LONG)
135                         .show();
136                 finish();
137             }
138         }
139     }
140 
finishActivity()141     private void finishActivity() {
142         Intent intentForNextActivity = getIntent().getParcelableExtra(KEY_INTENT_AFTER_COMPLETION);
143         if (intentForNextActivity != null) {
144             startActivity(intentForNextActivity);
145         }
146         finish();
147     }
148 
showMerchantCollection()149     private void showMerchantCollection() {
150         executeActionWithDelay(
151                 new Runnable() {
152                     @Override
153                     public void run() {
154                         startActivity(OnboardingUtils.ONLINE_STORE_INTENT);
155                     }
156                 },
157                 SHOW_RIPPLE_DURATION_MS);
158     }
159 
160     @Override
executeAction(String category, int actionId, Bundle params)161     protected boolean executeAction(String category, int actionId, Bundle params) {
162         switch (category) {
163             case WelcomeFragment.ACTION_CATEGORY:
164                 switch (actionId) {
165                     case WelcomeFragment.ACTION_NEXT:
166                         OnboardingUtils.setFirstRunWithCurrentVersionCompleted(
167                                 OnboardingActivity.this);
168                         showFragment(new SetupSourcesFragment(), false);
169                         return true;
170                 }
171                 break;
172             case SetupSourcesFragment.ACTION_CATEGORY:
173                 switch (actionId) {
174                     case SetupSourcesFragment.ACTION_ONLINE_STORE:
175                         showMerchantCollection();
176                         return true;
177                     case SetupSourcesFragment.ACTION_SETUP_INPUT:
178                         {
179                             String inputId =
180                                     params.getString(
181                                             SetupSourcesFragment.ACTION_PARAM_KEY_INPUT_ID);
182                             TvInputInfo input = mInputManager.getTvInputInfo(inputId);
183                             Intent intent = CommonUtils.createSetupIntent(input);
184                             if (intent == null) {
185                                 Toast.makeText(
186                                                 this,
187                                                 R.string.msg_no_setup_activity,
188                                                 Toast.LENGTH_SHORT)
189                                         .show();
190                                 return true;
191                             }
192                             // Even though other app can handle the intent, the setup launched by
193                             // Live
194                             // channels should go through Live channels SetupPassthroughActivity.
195                             intent.setComponent(
196                                     new ComponentName(this, SetupPassthroughActivity.class));
197                             try {
198                                 // Now we know that the user intends to set up this input. Grant
199                                 // permission for writing EPG data.
200                                 SetupUtils.grantEpgPermission(
201                                         this, input.getServiceInfo().packageName);
202                                 startActivityForResult(intent, REQUEST_CODE_START_SETUP_ACTIVITY);
203                             } catch (ActivityNotFoundException e) {
204                                 Toast.makeText(
205                                                 this,
206                                                 getString(
207                                                         R.string.msg_unable_to_start_setup_activity,
208                                                         input.loadLabel(this)),
209                                                 Toast.LENGTH_SHORT)
210                                         .show();
211                             }
212                             return true;
213                         }
214                     case SetupMultiPaneFragment.ACTION_DONE:
215                         {
216                             ChannelDataManager manager =
217                                     TvSingletons.getSingletons(OnboardingActivity.this)
218                                             .getChannelDataManager();
219                             if (manager.getChannelCount() == 0) {
220                                 finish();
221                             } else {
222                                 finishActivity();
223                             }
224                             return true;
225                         }
226                 }
227                 break;
228         }
229         return false;
230     }
231 }
232