Home | History | Annotate | Download | only in onboarding
      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 
     30 import com.android.tv.ApplicationSingletons;
     31 import com.android.tv.R;
     32 import com.android.tv.SetupPassthroughActivity;
     33 import com.android.tv.TvApplication;
     34 import com.android.tv.common.TvCommonUtils;
     35 import com.android.tv.common.ui.setup.SetupActivity;
     36 import com.android.tv.common.ui.setup.SetupMultiPaneFragment;
     37 import com.android.tv.data.ChannelDataManager;
     38 import com.android.tv.util.OnboardingUtils;
     39 import com.android.tv.util.PermissionUtils;
     40 import com.android.tv.util.SetupUtils;
     41 import com.android.tv.util.TvInputManagerHelper;
     42 
     43 public 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