Merge pull request #566 from alex-eyre/dev-exoplayer

Implement ExoPlayer
master
Florens 7 years ago committed by GitHub
commit f7c00e7c9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
  1. 3
      Clover/app/build.gradle
  2. 2
      Clover/app/src/main/java/org/floens/chan/core/settings/ChanSettings.java
  3. 4
      Clover/app/src/main/java/org/floens/chan/ui/controller/MediaSettingsController.java
  4. 54
      Clover/app/src/main/java/org/floens/chan/ui/view/MultiImageView.java
  5. 2
      Clover/app/src/main/res/values/strings.xml

@ -139,6 +139,9 @@ dependencies {
implementation "com.android.support:customtabs:${supportVersion}"
implementation 'com.android.support.constraint:constraint-layout:1.1.2'
implementation 'com.google.android.exoplayer:exoplayer-core:2.9.0'
implementation 'com.google.android.exoplayer:exoplayer-ui:2.9.0'
implementation 'com.squareup.okhttp3:okhttp:3.10.0'
//noinspection GradleDependency
implementation 'com.j256.ormlite:ormlite-core:4.48'

@ -102,6 +102,7 @@ public class ChanSettings {
public static final OptionsSetting<MediaAutoLoadMode> imageAutoLoadNetwork;
public static final OptionsSetting<MediaAutoLoadMode> videoAutoLoadNetwork;
public static final BooleanSetting videoOpenExternal;
public static final BooleanSetting videoUseExoplayer;
public static final BooleanSetting textOnly;
public static final BooleanSetting videoErrorIgnore;
public static final OptionsSetting<PostViewMode> boardViewMode;
@ -180,6 +181,7 @@ public class ChanSettings {
imageAutoLoadNetwork = new OptionsSetting<>(p, "preference_image_auto_load_network", MediaAutoLoadMode.class, MediaAutoLoadMode.WIFI);
videoAutoLoadNetwork = new OptionsSetting<>(p, "preference_video_auto_load_network", MediaAutoLoadMode.class, MediaAutoLoadMode.WIFI);
videoOpenExternal = new BooleanSetting(p, "preference_video_external", false);
videoUseExoplayer = new BooleanSetting(p, "preference_video_exoplayer", true);
textOnly = new BooleanSetting(p, "preference_text_only", false);
videoErrorIgnore = new BooleanSetting(p, "preference_video_error_ignore", false);
boardViewMode = new OptionsSetting<>(p, "preference_board_view_mode", PostViewMode.class, PostViewMode.LIST);

@ -109,6 +109,10 @@ public class MediaSettingsController extends SettingsController {
R.string.setting_video_open_external,
R.string.setting_video_open_external_description));
media.add(new BooleanSettingView(this, ChanSettings.videoUseExoplayer,
R.string.setting_video_exoplayer,
R.string.setting_video_exoplayer_description));
media.add(new BooleanSettingView(this,
ChanSettings.shareUrl,
R.string.setting_share_url, R.string.setting_share_url_description));

@ -36,12 +36,23 @@ import com.android.volley.VolleyError;
import com.android.volley.toolbox.ImageLoader;
import com.android.volley.toolbox.ImageLoader.ImageContainer;
import com.davemorrissey.labs.subscaleview.ImageSource;
import com.google.android.exoplayer2.ExoPlayer;
import com.google.android.exoplayer2.ExoPlayerFactory;
import com.google.android.exoplayer2.Player;
import com.google.android.exoplayer2.SimpleExoPlayer;
import com.google.android.exoplayer2.source.ExtractorMediaSource;
import com.google.android.exoplayer2.source.MediaSource;
import com.google.android.exoplayer2.ui.PlayerView;
import com.google.android.exoplayer2.upstream.DataSource;
import com.google.android.exoplayer2.upstream.DefaultDataSourceFactory;
import com.google.android.exoplayer2.util.Util;
import org.floens.chan.R;
import org.floens.chan.core.cache.FileCache;
import org.floens.chan.core.cache.FileCacheDownloader;
import org.floens.chan.core.cache.FileCacheListener;
import org.floens.chan.core.cache.FileCacheProvider;
import org.floens.chan.core.di.UserAgentProvider;
import org.floens.chan.core.model.PostImage;
import org.floens.chan.core.settings.ChanSettings;
import org.floens.chan.utils.AndroidUtils;
@ -70,11 +81,13 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
@Inject
ImageLoader imageLoader;
@Inject
UserAgentProvider userAgent;
private ImageView playView;
private PostImage postImage;
private Callback callback;
private Mode mode = Mode.UNLOADED;
private boolean hasContent = false;
@ -84,8 +97,10 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
private FileCacheDownloader videoRequest;
private VideoView videoView;
private PlayerView exoVideoView;
private boolean videoError = false;
private MediaPlayer mediaPlayer;
private SimpleExoPlayer exoPlayer;
public MultiImageView(Context context) {
this(context, null);
@ -166,9 +181,15 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
}
public void setVolume(boolean muted) {
if (mediaPlayer != null) {
final float volume = muted ? 0f : 1f;
mediaPlayer.setVolume(volume, volume);
final float volume = muted ? 0f : 1f;
if (ChanSettings.videoUseExoplayer.get()) {
if (exoPlayer != null) {
exoPlayer.getAudioComponent().setVolume(volume);
}
} else {
if (mediaPlayer != null) {
mediaPlayer.setVolume(volume, volume);
}
}
}
@ -391,6 +412,21 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
AndroidUtils.openIntent(intent);
onModeLoaded(Mode.MOVIE, videoView);
} else if (ChanSettings.videoUseExoplayer.get()) {
exoVideoView = new PlayerView(getContext());
exoPlayer = ExoPlayerFactory.newSimpleInstance(getContext());
exoVideoView.setPlayer(exoPlayer);
DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getContext(),
Util.getUserAgent(getContext(), userAgent.getUserAgent()));
MediaSource videoSource = new ExtractorMediaSource.Factory(dataSourceFactory)
.createMediaSource(android.net.Uri.fromFile(file));
exoPlayer.setRepeatMode(Player.REPEAT_MODE_ALL); //Repeat forever
exoPlayer.prepare(videoSource);
callback.onVideoLoaded(this, hasMediaPlayerAudioTracks(exoPlayer));
addView(exoVideoView);
exoPlayer.setPlayWhenReady(true);
} else {
Context proxyContext = new NoMusicServiceCommandContext(getContext());
@ -451,6 +487,10 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
}
}
private boolean hasMediaPlayerAudioTracks(ExoPlayer mediaPlayer) {
return mediaPlayer.getAudioComponent() != null;
}
private void onVideoError() {
if (!videoError) {
videoError = true;
@ -463,6 +503,10 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
mediaPlayer = null;
}
private void cleanupVideo(PlayerView videoView) {
videoView.getPlayer().release();
}
private void setBitImageFileInternal(File file, boolean tiling, final Mode forMode) {
final CustomScaleImageView image = new CustomScaleImageView(getContext());
image.setImage(ImageSource.uri(file.getAbsolutePath()).tiling(tiling));
@ -535,6 +579,8 @@ public class MultiImageView extends FrameLayout implements View.OnClickListener
if (child != view) {
if (child instanceof VideoView) {
cleanupVideo((VideoView) child);
} else if (child instanceof PlayerView) {
cleanupVideo((PlayerView) child);
}
removeViewAt(i);

@ -511,6 +511,8 @@ If disabled, save the image with the filename the uploader assigned."
<string name="setting_video_default_muted_description">If a video has audio, mute it by default.</string>
<string name="setting_video_open_external">Play videos with external player</string>
<string name="setting_video_open_external_description">Play videos in an external media player app</string>
<string name="setting_video_exoplayer">Enable new ExoPlayer</string>
<string name="setting_video_exoplayer_description">Use the new ExoPlayer for internal media player</string>
<string name="setting_share_url">Share URL to image</string>
<string name="setting_share_url_description">Share the URL to the image instead of the image itself</string>
<string name="settings_reveal_image_spoilers">Reveal image spoilers</string>

Loading…
Cancel
Save