diff --git a/.idea/encodings.xml b/.idea/encodings.xml index 7c77d9fd..1bc1410f 100644 --- a/.idea/encodings.xml +++ b/.idea/encodings.xml @@ -1,6 +1,8 @@ + + diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailActivity.java b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailActivity.java deleted file mode 100644 index 76a71801..00000000 --- a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailActivity.java +++ /dev/null @@ -1,422 +0,0 @@ -package de.christinecoenen.code.zapp.app.livestream.ui.detail; - -import android.content.Context; -import android.content.Intent; -import android.content.SharedPreferences; -import android.content.pm.ActivityInfo; -import android.graphics.PorterDuff; -import android.graphics.drawable.Drawable; -import android.net.Uri; -import android.os.Build; -import android.os.Bundle; -import android.os.Handler; -import android.preference.PreferenceManager; -import android.support.v4.view.ViewPager; -import android.support.v7.widget.Toolbar; -import android.view.KeyEvent; -import android.view.Menu; -import android.view.MenuItem; -import android.view.View; -import android.view.Window; -import android.widget.ProgressBar; - -import com.google.android.exoplayer2.ExoPlayerFactory; -import com.google.android.exoplayer2.SimpleExoPlayer; -import com.google.android.exoplayer2.source.MediaSource; -import com.google.android.exoplayer2.source.hls.HlsMediaSource; -import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection; -import com.google.android.exoplayer2.trackselection.DefaultTrackSelector; -import com.google.android.exoplayer2.trackselection.TrackSelection; -import com.google.android.exoplayer2.trackselection.TrackSelector; -import com.google.android.exoplayer2.upstream.DataSource; -import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter; -import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory; -import com.google.android.exoplayer2.util.Util; - -import butterknife.BindDrawable; -import butterknife.BindInt; -import butterknife.BindView; -import butterknife.OnTouch; -import de.christinecoenen.code.zapp.R; -import de.christinecoenen.code.zapp.app.livestream.ui.views.ProgramInfoViewBase; -import de.christinecoenen.code.zapp.app.settings.ui.SettingsActivity; -import de.christinecoenen.code.zapp.model.ChannelModel; -import de.christinecoenen.code.zapp.model.IChannelList; -import de.christinecoenen.code.zapp.model.json.SortableJsonChannelList; -import de.christinecoenen.code.zapp.utils.system.MultiWindowHelper; -import de.christinecoenen.code.zapp.utils.system.NetworkConnectionHelper; -import de.christinecoenen.code.zapp.utils.system.ShortcutHelper; -import de.christinecoenen.code.zapp.utils.video.SwipeablePlayerView; -import de.christinecoenen.code.zapp.utils.video.VideoBufferingHandler; -import de.christinecoenen.code.zapp.utils.video.VideoErrorHandler; -import de.christinecoenen.code.zapp.utils.view.ClickableViewPager; -import de.christinecoenen.code.zapp.utils.view.ColorHelper; -import de.christinecoenen.code.zapp.utils.view.FullscreenActivity; -import timber.log.Timber; - -public class ChannelDetailActivity extends FullscreenActivity implements - VideoErrorHandler.IVideoErrorListener, VideoBufferingHandler.IVideoBufferingListener { - - private static final String EXTRA_CHANNEL_ID = "de.christinecoenen.code.zapp.EXTRA_CHANNEL_ID"; - - - @BindView(R.id.toolbar) - protected Toolbar toolbar; - - @BindView(R.id.viewpager_channels) - protected ClickableViewPager viewPager; - - @BindView(R.id.video) - protected SwipeablePlayerView videoView; - - @BindView(R.id.progressbar_video) - protected ProgressBar progressView; - - @BindView(R.id.program_info) - protected ProgramInfoViewBase programInfoView; - - - @BindDrawable(android.R.drawable.ic_media_pause) - protected Drawable pauseIcon; - - @BindDrawable(android.R.drawable.ic_media_play) - protected Drawable playIcon; - - @BindInt(R.integer.activity_channel_detail_play_stream_delay_millis) - protected int playStreamDelayMillis; - - private final Handler playHandler = new Handler(); - private final VideoErrorHandler videoErrorHandler = new VideoErrorHandler(this); - private final VideoBufferingHandler bufferingHandler = new VideoBufferingHandler(this); - private final NetworkConnectionHelper networkConnectionHelper = new NetworkConnectionHelper(this); - private SimpleExoPlayer player; - private DataSource.Factory dataSourceFactory; - private ChannelDetailAdapter channelDetailAdapter; - private ChannelModel currentChannel; - private boolean isPlaying = false; - private Window window; - private IChannelList channelList; - - private final Runnable playRunnable = this::play; - - private final ChannelDetailAdapter.OnItemChangedListener onItemChangedListener = - new ChannelDetailAdapter.OnItemChangedListener() { - @Override - public void onItemSelected(ChannelModel channel) { - currentChannel = channel; - setTitle(channel.getName()); - setColor(channel.getColor()); - - playDelayed(); - programInfoView.setChannel(channel); - - ShortcutHelper.reportShortcutUsageGuarded(ChannelDetailActivity.this, channel.getId()); - } - }; - - private final ViewPager.OnPageChangeListener onPageChangeListener = - new ViewPager.SimpleOnPageChangeListener() { - @Override - public void onPageScrolled(int position, float positionOffset, int positionOffsetPixels) { - int color1 = channelDetailAdapter.getChannel(position).getColor(); - - if (positionOffset == 0) { - setColor(color1); - } else { - int color2 = channelDetailAdapter.getChannel(position + 1).getColor(); - int color = ColorHelper.interpolate(positionOffset, color1, color2); - setColor(color); - } - } - }; - - public static Intent getStartIntent(Context context, String channelId) { - Intent intent = new Intent(context, ChannelDetailActivity.class); - intent.setAction(Intent.ACTION_VIEW); - intent.putExtra(EXTRA_CHANNEL_ID, channelId); - return intent; - } - - @Override - protected void onCreate(Bundle savedInstanceState) { - super.onCreate(savedInstanceState); - - setSupportActionBar(toolbar); - window = getWindow(); - - if (getSupportActionBar() != null) { - getSupportActionBar().setDisplayHomeAsUpEnabled(true); - } - - channelList = new SortableJsonChannelList(this); - - // player - DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); - TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); - TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); - dataSourceFactory = new DefaultDataSourceFactory(this, - Util.getUserAgent(this, getString(R.string.app_name)), bandwidthMeter); - player = ExoPlayerFactory.newSimpleInstance(this, trackSelector); - player.addListener(bufferingHandler); - player.addListener(videoErrorHandler); - - videoView.setPlayer(player); - videoView.setTouchOverlay(viewPager); - - // pager - channelDetailAdapter = new ChannelDetailAdapter( - getSupportFragmentManager(), channelList, onItemChangedListener); - viewPager.setAdapter(channelDetailAdapter); - viewPager.addOnPageChangeListener(onPageChangeListener); - viewPager.setOnClickListener(view -> mContentView.performClick()); - - parseIntent(getIntent()); - - networkConnectionHelper.startListenForNetworkChanges(this::onNetworkConnectionChanged); - } - - @Override - protected void onNewIntent(Intent intent) { - super.onNewIntent(intent); - // called when coming back from picture in picture mode - isPlaying = false; - parseIntent(intent); - } - - @Override - protected void onStart() { - super.onStart(); - if (MultiWindowHelper.isInsideMultiWindow(this)) { - resumeActivity(); - } - } - - @Override - protected void onResume() { - super.onResume(); - if (!MultiWindowHelper.isInsideMultiWindow(this)) { - resumeActivity(); - } - - SharedPreferences preferences = PreferenceManager.getDefaultSharedPreferences(this); - boolean lockScreen = preferences.getBoolean("pref_detail_landscape", true); - if (lockScreen) { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE); - } else { - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_SENSOR); - } - } - - @Override - protected void onPause() { - super.onPause(); - if (!MultiWindowHelper.isInsideMultiWindow(this)) { - pauseActivity(); - } - } - - @Override - protected void onStop() { - super.onStop(); - if (MultiWindowHelper.isInsideMultiWindow(this)) { - pauseActivity(); - } - } - - @Override - protected void onDestroy() { - super.onDestroy(); - - player.removeListener(bufferingHandler); - player.removeListener(videoErrorHandler); - player.release(); - - networkConnectionHelper.endListenForNetworkChanges(); - } - - @Override - public void onPictureInPictureModeChanged(boolean isInPictureInPictureMode) { - super.onPictureInPictureModeChanged(isInPictureInPictureMode); - if (isInPictureInPictureMode) { - hide(); - } - } - - @Override - public boolean onCreateOptionsMenu(Menu menu) { - getMenuInflater().inflate(R.menu.activity_channel_detail, menu); - return super.onCreateOptionsMenu(menu); - } - - @Override - public boolean onOptionsItemSelected(MenuItem item) { - switch (item.getItemId()) { - case R.id.menu_share: - startActivity(currentChannel.getVideoShareIntent()); - return true; - case R.id.menu_settings: - Intent settingsIntent = SettingsActivity.getStartIntent(this); - startActivity(settingsIntent); - return true; - case android.R.id.home: - finish(); - return true; - default: - return super.onOptionsItemSelected(item); - } - } - - @Override - public boolean onKeyUp(int keyCode, KeyEvent event) { - boolean handled = false; - - switch (keyCode) { - case KeyEvent.KEYCODE_DPAD_LEFT: - handled = prevChannel(); - break; - case KeyEvent.KEYCODE_DPAD_RIGHT: - handled = nextChannel(); - break; - } - - return handled || super.onKeyUp(keyCode, event); - } - - @Override - public void onVideoError(int messageResourceId) { - player.stop(); - progressView.setVisibility(View.GONE); - - if (channelDetailAdapter.getCurrentFragment() != null) { - channelDetailAdapter.getCurrentFragment().onVideoError(getString(messageResourceId)); - } - } - - @Override - public void onVideoErrorInvalid() { - - } - - @Override - public void onBufferingStarted() { - if (player.getBufferedPercentage() == 0) { - progressView.setVisibility(View.VISIBLE); - } - } - - @Override - public void onBufferingEnded() { - if (player.getBufferedPercentage() > 0 && progressView.getVisibility() == View.VISIBLE) { - progressView.setVisibility(View.GONE); - channelDetailAdapter.getCurrentFragment().onVideoStart(); - } - } - - @Override - protected int getViewId() { - return R.layout.activity_channel_detail; - } - - @SuppressWarnings("SameReturnValue") - @OnTouch(R.id.viewpager_channels) - public boolean onPagerTouch() { - delayHide(); - return false; - } - - private void onNetworkConnectionChanged() { - if (networkConnectionHelper.isVideoPlaybackAllowed()) { - play(); - } else { - onVideoError(R.string.error_stream_not_in_wifi); - } - } - - private void parseIntent(Intent intent) { - Bundle extras = intent.getExtras(); - //noinspection ConstantConditions - String channelId = extras.getString(EXTRA_CHANNEL_ID); - int channelPosition = channelList.indexOf(channelId); - - viewPager.removeOnPageChangeListener(onPageChangeListener); - viewPager.setCurrentItem(channelPosition); - viewPager.addOnPageChangeListener(onPageChangeListener); - } - - private void pauseActivity() { - programInfoView.pause(); - player.stop(); - } - - private void resumeActivity() { - programInfoView.resume(); - if (isPlaying) { - play(); - } - } - - private void playDelayed() { - player.setPlayWhenReady(false); - progressView.setVisibility(View.VISIBLE); - playHandler.removeCallbacks(playRunnable); - playHandler.postDelayed(playRunnable, playStreamDelayMillis); - } - - private void play() { - if (!networkConnectionHelper.isVideoPlaybackAllowed()) { - onVideoError(R.string.error_stream_not_in_wifi); - return; - } - - if (currentChannel == null) { - return; - } - - Timber.d("play: %s", currentChannel.getName()); - isPlaying = true; - progressView.setVisibility(View.VISIBLE); - - Uri videoUri = Uri.parse(currentChannel.getStreamUrl()); - MediaSource videoSource = new HlsMediaSource.Factory(dataSourceFactory) - .createMediaSource(videoUri, playHandler, videoErrorHandler); - player.prepare(videoSource); - player.setPlayWhenReady(true); - } - - private boolean prevChannel() { - int nextItemIndex = viewPager.getCurrentItem() - 1; - - if (nextItemIndex < 0) { - return false; - } else { - delayHide(); - viewPager.setCurrentItem(nextItemIndex, true); - return true; - } - } - - private boolean nextChannel() { - int nextItemIndex = viewPager.getCurrentItem() + 1; - - if (nextItemIndex == channelDetailAdapter.getCount()) { - return false; - } else { - delayHide(); - viewPager.setCurrentItem(nextItemIndex, true); - return true; - } - } - - private void setColor(int color) { - progressView.getIndeterminateDrawable().setColorFilter(color, PorterDuff.Mode.SRC_IN); - toolbar.setBackgroundColor(color); - - int colorDarker = ColorHelper.darker(color, 0.075f); - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - window.setStatusBarColor(colorDarker); - } - - int colorAlpha = ColorHelper.darker(ColorHelper.withAlpha(color, 150), 0.25f); - mControlsView.setBackgroundColor(colorAlpha); - } -} diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailActivity.kt b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailActivity.kt new file mode 100644 index 00000000..04e8c621 --- /dev/null +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailActivity.kt @@ -0,0 +1,373 @@ +package de.christinecoenen.code.zapp.app.livestream.ui.detail + +import android.content.Context +import android.content.Intent +import android.content.pm.ActivityInfo +import android.content.res.Configuration +import android.graphics.PorterDuff +import android.graphics.drawable.Drawable +import android.net.Uri +import android.os.Build +import android.os.Bundle +import android.os.Handler +import android.preference.PreferenceManager +import android.support.v4.view.ViewPager +import android.view.KeyEvent +import android.view.Menu +import android.view.MenuItem +import android.view.View +import android.widget.ProgressBar +import butterknife.BindDrawable +import butterknife.BindInt +import butterknife.OnTouch +import com.google.android.exoplayer2.ExoPlayerFactory +import com.google.android.exoplayer2.SimpleExoPlayer +import com.google.android.exoplayer2.source.hls.HlsMediaSource +import com.google.android.exoplayer2.trackselection.AdaptiveTrackSelection +import com.google.android.exoplayer2.trackselection.DefaultTrackSelector +import com.google.android.exoplayer2.upstream.DataSource +import com.google.android.exoplayer2.upstream.DefaultBandwidthMeter +import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory +import com.google.android.exoplayer2.util.Util +import de.christinecoenen.code.zapp.R +import de.christinecoenen.code.zapp.app.livestream.ui.views.ProgramInfoViewBase +import de.christinecoenen.code.zapp.app.settings.ui.SettingsActivity +import de.christinecoenen.code.zapp.model.ChannelModel +import de.christinecoenen.code.zapp.model.IChannelList +import de.christinecoenen.code.zapp.model.json.SortableJsonChannelList +import de.christinecoenen.code.zapp.utils.system.MultiWindowHelper +import de.christinecoenen.code.zapp.utils.system.NetworkConnectionHelper +import de.christinecoenen.code.zapp.utils.system.ShortcutHelper +import de.christinecoenen.code.zapp.utils.video.SwipeablePlayerView +import de.christinecoenen.code.zapp.utils.video.VideoBufferingHandler +import de.christinecoenen.code.zapp.utils.video.VideoErrorHandler +import de.christinecoenen.code.zapp.utils.view.ClickableViewPager +import de.christinecoenen.code.zapp.utils.view.ColorHelper +import de.christinecoenen.code.zapp.utils.view.FullscreenActivity +import kotlinx.android.synthetic.main.activity_channel_detail.* +import timber.log.Timber + +class ChannelDetailActivity : FullscreenActivity(), VideoErrorHandler.IVideoErrorListener, VideoBufferingHandler.IVideoBufferingListener { + + private val viewPager: ClickableViewPager by lazy { viewpager_channels } + private val videoView: SwipeablePlayerView by lazy { video } + private val progressView: ProgressBar by lazy { progressbar_video } + private val programInfoView: ProgramInfoViewBase by lazy { program_info } + + @BindDrawable(android.R.drawable.ic_media_pause) + var pauseIcon: Drawable? = null + + @BindDrawable(android.R.drawable.ic_media_play) + var playIcon: Drawable? = null + + @BindInt(R.integer.activity_channel_detail_play_stream_delay_millis) + var playStreamDelayMillis: Int = 0 + + private val playHandler = Handler() + private val videoErrorHandler = VideoErrorHandler(this) + private val bufferingHandler = VideoBufferingHandler(this) + private val networkConnectionHelper = NetworkConnectionHelper(this) + private lateinit var player: SimpleExoPlayer + private lateinit var dataSourceFactory: DataSource.Factory + private var currentChannel: ChannelModel? = null + private var isPlaying = false + private lateinit var channelDetailAdapter: ChannelDetailAdapter + private lateinit var channelList: IChannelList + + private val playRunnable = Runnable { this.play() } + + private val onItemChangedListener = object : ChannelDetailAdapter.OnItemChangedListener { + override fun onItemSelected(channelModel: ChannelModel) { + currentChannel = channelModel + title = channelModel.name + setColor(channelModel.color) + + playDelayed() + programInfoView.setChannel(channelModel) + + ShortcutHelper.reportShortcutUsageGuarded(this@ChannelDetailActivity, channelModel.id) + } + } + + private val onPageChangeListener = object : ViewPager.SimpleOnPageChangeListener() { + override fun onPageScrolled(position: Int, positionOffset: Float, positionOffsetPixels: Int) { + val color1 = channelDetailAdapter.getChannel(position).color + + if (positionOffset == 0f) { + setColor(color1) + } else { + val color2 = channelDetailAdapter.getChannel(position + 1).color + val color = ColorHelper.interpolate(positionOffset, color1, color2) + setColor(color) + } + } + } + + override fun onCreate(savedInstanceState: Bundle?) { + super.onCreate(savedInstanceState) + + setSupportActionBar(toolbar) + supportActionBar?.setDisplayHomeAsUpEnabled(true) + + channelList = SortableJsonChannelList(this) + + // player + val bandwidthMeter = DefaultBandwidthMeter() + val videoTrackSelectionFactory = AdaptiveTrackSelection.Factory(bandwidthMeter) + val trackSelector = DefaultTrackSelector(videoTrackSelectionFactory) + dataSourceFactory = DefaultDataSourceFactory(this, + Util.getUserAgent(this, getString(R.string.app_name)), bandwidthMeter) + player = ExoPlayerFactory.newSimpleInstance(this, trackSelector) + player.addListener(bufferingHandler) + player.addListener(videoErrorHandler) + + videoView.player = player + videoView.setTouchOverlay(viewPager) + + // pager + channelDetailAdapter = ChannelDetailAdapter(supportFragmentManager, channelList, onItemChangedListener) + viewPager.adapter = channelDetailAdapter + viewPager.addOnPageChangeListener(onPageChangeListener) + viewPager.setOnClickListener { _ -> mContentView.performClick() } + + parseIntent(intent) + + networkConnectionHelper.startListenForNetworkChanges(this::onNetworkConnectionChanged) + } + + override fun onNewIntent(intent: Intent) { + super.onNewIntent(intent) + // called when coming back from picture in picture mode + isPlaying = false + parseIntent(intent) + } + + override fun onStart() { + super.onStart() + if (MultiWindowHelper.isInsideMultiWindow(this)) { + resumeActivity() + } + } + + override fun onResume() { + super.onResume() + if (!MultiWindowHelper.isInsideMultiWindow(this)) { + resumeActivity() + } + + val preferences = PreferenceManager.getDefaultSharedPreferences(this) + val lockScreen = preferences.getBoolean("pref_detail_landscape", true) + + requestedOrientation = + if (lockScreen) { + ActivityInfo.SCREEN_ORIENTATION_SENSOR_LANDSCAPE + } else { + ActivityInfo.SCREEN_ORIENTATION_SENSOR + } + } + + override fun onPause() { + super.onPause() + if (!MultiWindowHelper.isInsideMultiWindow(this)) { + pauseActivity() + } + } + + override fun onStop() { + super.onStop() + if (MultiWindowHelper.isInsideMultiWindow(this)) { + pauseActivity() + } + } + + override fun onDestroy() { + super.onDestroy() + + player.removeListener(bufferingHandler) + player.removeListener(videoErrorHandler) + player.release() + + networkConnectionHelper.endListenForNetworkChanges() + } + + override fun onPictureInPictureModeChanged(isInPictureInPictureMode: Boolean, config: Configuration) { + super.onPictureInPictureModeChanged(isInPictureInPictureMode, config) + if (isInPictureInPictureMode) { + hide() + } + } + + override fun onCreateOptionsMenu(menu: Menu): Boolean { + menuInflater.inflate(R.menu.activity_channel_detail, menu) + return super.onCreateOptionsMenu(menu) + } + + override fun onOptionsItemSelected(item: MenuItem): Boolean { + return when (item.itemId) { + R.id.menu_share -> { + startActivity(currentChannel!!.videoShareIntent) + true + } + R.id.menu_settings -> { + val settingsIntent = SettingsActivity.getStartIntent(this) + startActivity(settingsIntent) + true + } + android.R.id.home -> { + finish() + true + } + else -> super.onOptionsItemSelected(item) + } + } + + override fun onKeyUp(keyCode: Int, event: KeyEvent): Boolean { + val handled = when (keyCode) { + KeyEvent.KEYCODE_DPAD_LEFT -> prevChannel() + KeyEvent.KEYCODE_DPAD_RIGHT -> nextChannel() + else -> false + } + + return handled || super.onKeyUp(keyCode, event) + } + + override fun onVideoError(messageResourceId: Int) { + player.stop() + progressView.visibility = View.GONE + channelDetailAdapter.currentFragment?.onVideoError(getString(messageResourceId)) + } + + override fun onVideoErrorInvalid() { + + } + + override fun onBufferingStarted() { + if (player.bufferedPercentage == 0) { + progressView.visibility = View.VISIBLE + } + } + + override fun onBufferingEnded() { + if (player.bufferedPercentage > 0 && progressView.visibility == View.VISIBLE) { + progressView.visibility = View.GONE + channelDetailAdapter.currentFragment?.onVideoStart() + } + } + + override fun getViewId(): Int { + return R.layout.activity_channel_detail + } + + @OnTouch(R.id.viewpager_channels) + fun onPagerTouch(): Boolean { + delayHide() + return false + } + + private fun onNetworkConnectionChanged() { + if (networkConnectionHelper.isVideoPlaybackAllowed) { + play() + } else { + onVideoError(R.string.error_stream_not_in_wifi) + } + } + + private fun parseIntent(intent: Intent) { + val channelId = intent.extras.getString(EXTRA_CHANNEL_ID) + val channelPosition = channelList.indexOf(channelId) + + viewPager.removeOnPageChangeListener(onPageChangeListener) + viewPager.currentItem = channelPosition + viewPager.addOnPageChangeListener(onPageChangeListener) + } + + private fun pauseActivity() { + programInfoView.pause() + player.stop() + } + + private fun resumeActivity() { + programInfoView.resume() + if (isPlaying) { + play() + } + } + + private fun playDelayed() { + player.playWhenReady = false + progressView.visibility = View.VISIBLE + playHandler.removeCallbacks(playRunnable) + playHandler.postDelayed(playRunnable, playStreamDelayMillis.toLong()) + } + + private fun play() { + if (!networkConnectionHelper.isVideoPlaybackAllowed) { + onVideoError(R.string.error_stream_not_in_wifi) + return + } + + if (currentChannel == null) { + return + } + + Timber.d("play: %s", currentChannel?.name) + isPlaying = true + progressView.visibility = View.VISIBLE + + val videoUri = Uri.parse(currentChannel!!.streamUrl) + val videoSource = HlsMediaSource.Factory(dataSourceFactory) + .createMediaSource(videoUri, playHandler, videoErrorHandler) + player.prepare(videoSource) + player.playWhenReady = true + } + + private fun prevChannel(): Boolean { + val nextItemIndex = viewPager.currentItem - 1 + + return if (nextItemIndex < 0) { + false + } else { + delayHide() + viewPager.setCurrentItem(nextItemIndex, true) + true + } + } + + private fun nextChannel(): Boolean { + val nextItemIndex = viewPager.currentItem + 1 + + return if (nextItemIndex == channelDetailAdapter.count) { + false + } else { + delayHide() + viewPager.setCurrentItem(nextItemIndex, true) + true + } + } + + private fun setColor(color: Int) { + progressView.indeterminateDrawable.setColorFilter(color, PorterDuff.Mode.SRC_IN) + toolbar.setBackgroundColor(color) + + val colorDarker = ColorHelper.darker(color, 0.075f) + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { + window?.statusBarColor = colorDarker + } + + val colorAlpha = ColorHelper.darker(ColorHelper.withAlpha(color, 150), 0.25f) + mControlsView.setBackgroundColor(colorAlpha) + } + + companion object { + + private const val EXTRA_CHANNEL_ID = "de.christinecoenen.code.zapp.EXTRA_CHANNEL_ID" + + @JvmStatic + fun getStartIntent(context: Context, channelId: String): Intent { + val intent = Intent(context, ChannelDetailActivity::class.java) + intent.action = Intent.ACTION_VIEW + intent.putExtra(EXTRA_CHANNEL_ID, channelId) + return intent + } + } +} diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailAdapter.kt b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailAdapter.kt index eb16fea6..bdeaa17d 100644 --- a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailAdapter.kt +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/ChannelDetailAdapter.kt @@ -46,6 +46,6 @@ internal class ChannelDetailAdapter(fragmentManager: FragmentManager, } internal interface OnItemChangedListener { - fun onItemSelected(model: ChannelModel) + fun onItemSelected(channelModel: ChannelModel) } } diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/StreamPageFragment.kt b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/StreamPageFragment.kt index c74f98e4..6e17d3e0 100644 --- a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/StreamPageFragment.kt +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/detail/StreamPageFragment.kt @@ -40,12 +40,12 @@ class StreamPageFragment : Fragment() { override fun onStop() { super.onStop() // don't use onPause to support multiwindow feature - view!!.visibility = View.VISIBLE + view?.visibility = View.VISIBLE errorText.visibility = View.GONE } fun onHide() { - view!!.visibility = View.VISIBLE + view?.visibility = View.VISIBLE errorText.visibility = View.GONE } @@ -54,25 +54,25 @@ class StreamPageFragment : Fragment() { } fun onVideoError(message: String) { - view!!.visibility = View.VISIBLE + view?.visibility = View.VISIBLE errorText.visibility = View.VISIBLE errorText.text = message } private fun fadeOutLogo() { - if (view!!.visibility == View.VISIBLE) { + if (view?.visibility == View.VISIBLE) { val fadeOutAnimation = AnimationUtils.loadAnimation(context, android.R.anim.fade_out) fadeOutAnimation.setAnimationListener(object : Animation.AnimationListener { override fun onAnimationStart(animation: Animation) {} override fun onAnimationEnd(animation: Animation) { - view!!.visibility = View.GONE + view?.visibility = View.GONE } override fun onAnimationRepeat(animation: Animation) {} }) - view!!.startAnimation(fadeOutAnimation) + view?.startAnimation(fadeOutAnimation) } } diff --git a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/list/ChannelListFragment.kt b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/list/ChannelListFragment.kt index 5575004e..7a356f25 100644 --- a/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/list/ChannelListFragment.kt +++ b/app/src/main/java/de/christinecoenen/code/zapp/app/livestream/ui/list/ChannelListFragment.kt @@ -64,7 +64,7 @@ class ChannelListFragment : Fragment(), ChannelListAdapter.Listener { } override fun onItemClick(channel: ChannelModel) { - val intent = ChannelDetailActivity.getStartIntent(context, channel.id) + val intent = ChannelDetailActivity.getStartIntent(context!!, channel.id) startActivity(intent) }