package com.distantfuture.videos.mainactivity; import android.app.ActionBar; import android.app.ActivityOptions; import android.app.Fragment; import android.content.Intent; import android.content.res.Configuration; import android.net.Uri; import android.os.Bundle; import android.view.Menu; import android.view.MenuItem; import android.widget.Toast; import com.distantfuture.iconicdroid.IconicActivity; import com.distantfuture.videos.R; import com.distantfuture.videos.activities.SettingsActivity; import com.distantfuture.videos.activities.ViewServerActivity; import com.distantfuture.videos.cast.CastActivity; import com.distantfuture.videos.channellookup.ChannelLookupActivity; import com.distantfuture.videos.content.Content; import com.distantfuture.videos.donate.DonateActivity; import com.distantfuture.videos.introactivity.IntroActivity; import com.distantfuture.videos.misc.ActionBarSpinnerAdapter; import com.distantfuture.videos.misc.AppUtils; import com.distantfuture.videos.misc.BusEvents; import com.distantfuture.videos.misc.ColorPickerFragment; import com.distantfuture.videos.misc.Constants; import com.distantfuture.videos.misc.MainApplication; import com.distantfuture.videos.misc.Utils; import com.distantfuture.videos.youtube.VideoPlayer; import com.distantfuture.videos.youtube.YouTubeAPI; import com.google.android.youtube.player.YouTubeInitializationResult; import com.google.android.youtube.player.YouTubeStandalonePlayer; import com.inscription.WhatsNewDialog; import org.codechimp.apprater.AppRater; import de.greenrobot.event.EventBus; public class DrawerActivity extends ViewServerActivity implements DrawerActivitySupport { VideoPlayer mPlayer; private int mCurrentSection = -1; private DrawerManager mDrawerMgr; private Toast backButtonToast; private long lastBackPressTime = 0; private Content mContent; private ActionBarSpinnerAdapter mActionBarSpinnerAdapter; private boolean mSpinnerSucksBalls; @Override public void onCreate(Bundle savedInstanceState) { // we set the activity to NoActionBar in the manifest to avoid the title flickering in the actionbar setTheme(R.style.DrawerActivityTheme); super.onCreate(savedInstanceState); setContentView(R.layout.activity_drawer); mContent = Content.instance(this); if (mContent.needsChannelSwitcher()) { mActionBarSpinnerAdapter = new ActionBarSpinnerAdapter(this, mContent); ActionBar.OnNavigationListener listener = new ActionBar.OnNavigationListener() { @Override public boolean onNavigationItemSelected(int position, long itemId) { // be aware that this call back gets called when the spinner contents are built // we need to ignore that one, so not going to do anything if channel not changing if (!mSpinnerSucksBalls) { mSpinnerSucksBalls = true; // ## taking advantage of this feature/bug to set the real value of the actionbar spinner // if we don't do this, the spinner defaults to value 0, so selecting the first item // in the list will not work since it doesn't respond when selecting the same index as the current value getActionBar().setSelectedNavigationItem(mContent.currentChannelIndex()); } else { if (mContent.changeChannel(position)) updateSectionForChannel(); } return true; } }; getActionBar().setDisplayShowTitleEnabled(false); getActionBar().setNavigationMode(ActionBar.NAVIGATION_MODE_LIST); getActionBar().setListNavigationCallbacks(mActionBarSpinnerAdapter, listener); } setupDrawer(); // enable ActionBar app icon to behave as action to toggle nav drawer getActionBar().setDisplayHomeAsUpEnabled(true); selectSection(mContent.savedSectionIndex(), false); if (Constants.showAppRater) { AppRater.app_launched(this); } // general app tweaks // Debug.activateStrictMode(); Utils.ignoreObsoleteCapacitiveMenuButton(this); // show player if activity was destroyed and recreated if (savedInstanceState != null) { VideoPlayer.PlayerParams params = savedInstanceState.getParcelable("player_params"); if (params != null) playVideo(params); } WhatsNewDialog.showWhatsNew(this, false); // only show intro for multi channels if (mContent.needsChannelSwitcher()) IntroActivity.showIntroDelayed(this, false); } @Override public void onStop() { super.onStop(); // for AppUtils.THEME_CHANGED EventBus.getDefault().unregister(this); } @Override public void onStart() { super.onStart(); // for AppUtils.THEME_CHANGED EventBus.getDefault().register(this); } @Override protected void onSaveInstanceState(Bundle outState) { super.onSaveInstanceState(outState); if (mPlayer != null) { if (mPlayer.visible()) { VideoPlayer.PlayerParams params = mPlayer.playerParams(); if (params != null) { outState.putParcelable("player_params", params); } } } } @Override public boolean onCreateOptionsMenu(Menu menu) { MenuItem item; getMenuInflater().inflate(R.menu.main, menu); MainApplication.getCastManager(this).addMediaRouterButton(menu, R.id.action_cast, this, true); if (!mContent.supportsDonate()) { item = menu.findItem(R.id.action_donate); item.setVisible(false); } if (!mContent.supportsChannelEditing()) { item = menu.findItem(R.id.action_channel_lookup); item.setVisible(false); } return super.onCreateOptionsMenu(menu); } private boolean closePlayerIfOpen() { if (mPlayer != null && mPlayer.visible()) { mPlayer.close(); return true; } return false; } public void onEventMainThread(BusEvents.ThemeChanged event) { // animate doesn't work, puts new activity in the background. use recreate instead boolean animate = false; if (animate) { ActivityOptions opts = ActivityOptions.makeCustomAnimation(this, android.R.anim.fade_in, android.R.anim.fade_out); startActivity(getIntent(), opts.toBundle()); finish(); } else { // not sure how to to get recreate to animate, so we use the above code when animating which is like a recreate recreate(); } } // FragmentActivity uses some supportFragment garbage // backbutton will close the activity rather than popBack a fragment public void superOnBackPressedHack() { if (!getFragmentManager().popBackStackImmediate()) { finish(); } } @Override public void onBackPressed() { // hides the video player if visible if (!closePlayerIfOpen()) { if (getFragmentManager().getBackStackEntryCount() == 0) { if (this.lastBackPressTime < System.currentTimeMillis() - 4000) { backButtonToast = Toast.makeText(this, "Press back again to exit", Toast.LENGTH_SHORT); backButtonToast.show(); this.lastBackPressTime = System.currentTimeMillis(); } else { if (backButtonToast != null) { backButtonToast.cancel(); } // this works around FragmentActivity incorrect behavior superOnBackPressedHack(); } } else { // this works around FragmentActivity incorrect behavior superOnBackPressedHack(); } } } @Override public void onActivityResult(int requestCode, int resultCode, Intent data) { switch (requestCode) { // called when playing a movie, could fail and this dialog shows the user how to fix it case YouTubeAPI.REQ_PLAYER_CODE: if (resultCode != RESULT_OK) { YouTubeInitializationResult errorReason = YouTubeStandalonePlayer.getReturnedInitializationResult(data); if (errorReason.isUserRecoverableError()) { errorReason.getErrorDialog(this, 0).show(); } else { String errorMessage = String.format("PLAYER ERROR!! - %s", errorReason.toString()); Utils.toast(this, errorMessage); } } break; default: super.onActivityResult(requestCode, resultCode, data); } } @Override public boolean onPrepareOptionsMenu(Menu menu) { MenuItem item = menu.findItem(R.id.action_show_hidden); if (item != null) { boolean showHidden = AppUtils.instance(this).showHiddenItems(); item.setTitle((showHidden ? R.string.action_hide_hidden : R.string.action_show_hidden)); } boolean showDevTools = AppUtils.instance(this).showDevTools(); menu.setGroupVisible(R.id.dev_tools_group, showDevTools); return super.onPrepareOptionsMenu(menu); } @Override public boolean onOptionsItemSelected(MenuItem item) { Intent intent; // close player if open if (item.getItemId() == android.R.id.home) { // close player if back button in action bar hit if (closePlayerIfOpen()) return true; } // The action bar home/up action should open or close the drawer. // ActionBarDrawerToggle will take care of this. if (mDrawerMgr.onOptionsItemSelected(item)) { return true; } // Handle action buttons switch (item.getItemId()) { case R.id.action_settings: SettingsActivity.show(DrawerActivity.this); return true; case R.id.action_show_hidden: { boolean toggle = AppUtils.instance(this).showHiddenItems(); AppUtils.instance(this).setShowHiddenItems(!toggle); YouTubeGridFragment fragment = currentYouTubeFragment(); if (fragment != null) fragment.reloadForPrefChange(); return true; } case R.id.action_more_apps: Utils.openWebPage(this, Utils.getCompanyPlayStoreUri()); return true; case R.id.action_switch_view: AppUtils.pickViewStyleDialog(this); return true; // for development only, hide for release case R.id.action_show_icons: intent = new Intent(); intent.setClass(DrawerActivity.this, IconicActivity.class); startActivity(intent); return true; // this is only used for the debug tools menu, so no need to hide if (!Constants.showAppRater) case R.id.action_show_rate_dialog: AppRater.showRateDialog(this); return true; case R.id.action_show_cast: intent = new Intent(); intent.setClass(DrawerActivity.this, CastActivity.class); startActivity(intent); return true; case R.id.action_donate: DonateActivity.show(this); return true; case R.id.action_channel_lookup: ChannelLookupActivity.show(this); return true; case R.id.action_whats_new: WhatsNewDialog.showWhatsNew(this, true); return true; case R.id.action_color_picker: { Fragment fragment = new ColorPickerFragment(); Utils.showFragment(this, fragment, R.id.fragment_holder, 0, true); return true; } } return super.onOptionsItemSelected(item); } private void updateSectionForChannel() { mCurrentSection = -1; // force it to reload fragment if same position selectSection(mContent.savedSectionIndex(), true); } private void setupDrawer() { mDrawerMgr = new DrawerManager(this, mContent, new DrawerManager.DrawerManagerListener() { @Override public void onChannelClick() { updateSectionForChannel(); } @Override public void onDrawerClick(int position) { selectSection(position, true); } @Override public void onDrawerOpen(boolean opened) { invalidateOptionsMenu(); // creates call to onPrepareOptionsMenu() } }); // open on first launch? // mDrawerMgr.openDrawer(); } private void selectSection(int position, boolean animate) { // short curcuit trying to select the same position if (mCurrentSection == position) return; mCurrentSection = position; mDrawerMgr.setItemChecked(position, true); // clear back stack when using drawer getFragmentManager().popBackStack(); Utils.showFragment(this, mContent.fragmentForIndex(position), R.id.fragment_holder, animate ? 3 : 0, false); } /** * When using the ActionBarDrawerToggle, you must call it during * onPostCreate() and onConfigurationChanged()... */ @Override protected void onPostCreate(Bundle savedInstanceState) { super.onPostCreate(savedInstanceState); // Sync the toggle state after onRestoreInstanceState has occurred. mDrawerMgr.syncState(); } @Override public void onConfigurationChanged(Configuration newConfig) { super.onConfigurationChanged(newConfig); // Pass any configuration change to the drawer toggles mDrawerMgr.onConfigurationChanged(newConfig); // the spinners title and subtitle change on different orientations // must tell the adaptor it's views need to be refreshed if (mActionBarSpinnerAdapter != null) { mActionBarSpinnerAdapter.notifyDataSetChanged(); } } private void syncActionBarTitle() { YouTubeGridFragment fragment = currentYouTubeFragment(); if (fragment != null) fragment.syncActionBarTitle(); } private YouTubeGridFragment currentYouTubeFragment() { YouTubeGridFragment result = null; Fragment fragment = getFragmentManager().findFragmentById(R.id.fragment_holder); if (fragment instanceof YouTubeGridFragment) result = (YouTubeGridFragment) fragment; return result; } private VideoPlayer videoPlayer(boolean createIfNeeded) { if (createIfNeeded) { if (mPlayer == null) { mPlayer = new VideoPlayer(this, R.id.youtube_fragment, new VideoPlayer.VideoPlayerStateListener() { // called when the video player opens or closes, adjust the action bar title @Override public void stateChanged() { syncActionBarTitle(); } }); } } return mPlayer; } // DrawerActivitySupport @Override public void showDefaultFragment() { selectSection(1, true); } // DrawerActivitySupport @Override public void installFragment(Fragment fragment, boolean animate) { Utils.showFragment(this, fragment, R.id.fragment_holder, animate ? 1 : 0, true); } // DrawerActivitySupport @Override public void setActionBarTitle(CharSequence title, CharSequence subtitle) { if (mActionBarSpinnerAdapter != null) { mActionBarSpinnerAdapter.setTitleAndSubtitle(title, subtitle); } else { ActionBar bar = getActionBar(); if (bar != null) { bar.setTitle(title); bar.setSubtitle(subtitle); } } } // DrawerActivitySupport @Override public boolean actionBarTitleHandled() { // if video player is up, show the video title VideoPlayer player = videoPlayer(false); if (player != null && player.visible()) { setActionBarTitle(getResources().getString(R.string.now_playing), player.title()); return true; } return false; } // DrawerActivitySupport @Override public boolean isPlayerVisible() { VideoPlayer player = videoPlayer(false); return (player != null && player.visible()); } // DrawerActivitySupport @Override public void playVideo(VideoPlayer.PlayerParams params) { // could use this, but we have no control for mute commericals and play next automatically etc. // YouTubeAPI.playMovie(this, videoId, true); videoPlayer(true).open(params); } }