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