mirror of
https://github.com/mediathekview/zapp.git
synced 2024-09-19 20:02:17 +02:00
Convert ChannelDetailActivity to kotlin
This commit is contained in:
parent
a24b863099
commit
48b43c96cb
@ -1,6 +1,8 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<project version="4">
|
||||
<component name="Encoding">
|
||||
<file url="file://$PROJECT_DIR$/../VideoTest/gradle.properties" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/../VideoTest/local.properties" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/../Zappelfinger/gradle.properties" charset="UTF-8" />
|
||||
<file url="file://$PROJECT_DIR$/../Zappelfinger/local.properties" charset="UTF-8" />
|
||||
<file url="PROJECT" charset="UTF-8" />
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
@ -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
|
||||
}
|
||||
}
|
||||
}
|
@ -46,6 +46,6 @@ internal class ChannelDetailAdapter(fragmentManager: FragmentManager,
|
||||
}
|
||||
|
||||
internal interface OnItemChangedListener {
|
||||
fun onItemSelected(model: ChannelModel)
|
||||
fun onItemSelected(channelModel: ChannelModel)
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user