diff --git a/sample/build.gradle b/sample/build.gradle index 5876444..a6f69ee 100644 --- a/sample/build.gradle +++ b/sample/build.gradle @@ -36,6 +36,7 @@ apt { dependencies { // compile project(':library') + compile 'com.google.android.exoplayer:exoplayer:r2.3.1' compile 'com.android.support:support-v4:23.1.0' compile 'org.androidannotations:androidannotations-api:3.3.2' compile 'com.danikula:videocache:2.7.0' diff --git a/sample/src/main/AndroidManifest.xml b/sample/src/main/AndroidManifest.xml index 3ba1f44..7aa9115 100644 --- a/sample/src/main/AndroidManifest.xml +++ b/sample/src/main/AndroidManifest.xml @@ -22,7 +22,6 @@ - diff --git a/sample/src/main/java/com/danikula/videocache/sample/GalleryVideoFragment.java b/sample/src/main/java/com/danikula/videocache/sample/GalleryVideoFragment.java deleted file mode 100644 index 94a79ca..0000000 --- a/sample/src/main/java/com/danikula/videocache/sample/GalleryVideoFragment.java +++ /dev/null @@ -1,130 +0,0 @@ -package com.danikula.videocache.sample; - -import android.os.Handler; -import android.os.Message; -import android.support.v4.app.Fragment; -import android.widget.ProgressBar; -import android.widget.VideoView; - -import com.danikula.videocache.CacheListener; -import com.danikula.videocache.HttpProxyCacheServer; - -import org.androidannotations.annotations.AfterViews; -import org.androidannotations.annotations.EFragment; -import org.androidannotations.annotations.FragmentArg; -import org.androidannotations.annotations.InstanceState; -import org.androidannotations.annotations.SeekBarTouchStop; -import org.androidannotations.annotations.ViewById; - -import java.io.File; - -@EFragment(R.layout.fragment_video) -public class GalleryVideoFragment extends Fragment implements CacheListener { - - @FragmentArg String url; - - @InstanceState int position; - @InstanceState boolean playerStarted; - - @ViewById VideoView videoView; - @ViewById ProgressBar progressBar; - - private boolean visibleForUser; - - private final VideoProgressUpdater updater = new VideoProgressUpdater(); - - public static Fragment build(String url) { - return GalleryVideoFragment_.builder() - .url(url) - .build(); - } - - @AfterViews - void afterViewInjected() { - startProxy(); - - if (visibleForUser) { - startPlayer(); - } - } - - private void startPlayer() { - videoView.seekTo(position); - videoView.start(); - playerStarted = true; - } - - private void startProxy() { - HttpProxyCacheServer proxy = App.getProxy(getActivity()); - proxy.registerCacheListener(this, url); - videoView.setVideoPath(proxy.getProxyUrl(url)); - } - - @Override - public void setUserVisibleHint(boolean isVisibleToUser) { - super.setUserVisibleHint(isVisibleToUser); - - visibleForUser = isVisibleToUser; - if (videoView != null) { - if (visibleForUser) { - startPlayer(); - } else if (playerStarted) { - position = videoView.getCurrentPosition(); - videoView.pause(); - } - } - } - - @Override - public void onResume() { - super.onResume(); - updater.start(); - } - - @Override - public void onPause() { - super.onPause(); - updater.stop(); - } - - @Override - public void onDestroy() { - super.onDestroy(); - - videoView.stopPlayback(); - App.getProxy(getActivity()).unregisterCacheListener(this); - } - - @Override - public void onCacheAvailable(File file, String url, int percentsAvailable) { - progressBar.setSecondaryProgress(percentsAvailable); - } - - private void updateVideoProgress() { - int videoProgress = videoView.getCurrentPosition() * 100 / videoView.getDuration(); - progressBar.setProgress(videoProgress); - } - - @SeekBarTouchStop(R.id.progressBar) - void seekVideo() { - int videoPosition = videoView.getDuration() * progressBar.getProgress() / 100; - videoView.seekTo(videoPosition); - } - - private final class VideoProgressUpdater extends Handler { - - public void start() { - sendEmptyMessage(0); - } - - public void stop() { - removeMessages(0); - } - - @Override - public void handleMessage(Message msg) { - updateVideoProgress(); - sendEmptyMessageDelayed(0, 500); - } - } -} diff --git a/sample/src/main/java/com/danikula/videocache/sample/MenuActivity.java b/sample/src/main/java/com/danikula/videocache/sample/MenuActivity.java index 353ab4e..503cdf1 100644 --- a/sample/src/main/java/com/danikula/videocache/sample/MenuActivity.java +++ b/sample/src/main/java/com/danikula/videocache/sample/MenuActivity.java @@ -35,7 +35,6 @@ private List buildListData() { return Arrays.asList( new ListEntry("Single Video", SingleVideoActivity_.class), new ListEntry("Multiple Videos", MultipleVideosActivity_.class), - new ListEntry("Video Gallery with pre-caching", VideoGalleryActivity_.class), new ListEntry("Shared Cache", SharedCacheActivity_.class) ); } diff --git a/sample/src/main/java/com/danikula/videocache/sample/VideoFragment.java b/sample/src/main/java/com/danikula/videocache/sample/VideoFragment.java index 85c8086..cffa6ea 100644 --- a/sample/src/main/java/com/danikula/videocache/sample/VideoFragment.java +++ b/sample/src/main/java/com/danikula/videocache/sample/VideoFragment.java @@ -1,15 +1,33 @@ package com.danikula.videocache.sample; +import android.net.Uri; import android.os.Handler; import android.os.Message; import android.support.v4.app.Fragment; import android.util.Log; import android.widget.ImageView; import android.widget.ProgressBar; -import android.widget.VideoView; import com.danikula.videocache.CacheListener; import com.danikula.videocache.HttpProxyCacheServer; +import com.google.android.exoplayer2.DefaultLoadControl; +import com.google.android.exoplayer2.ExoPlayerFactory; +import com.google.android.exoplayer2.LoadControl; +import com.google.android.exoplayer2.SimpleExoPlayer; +import com.google.android.exoplayer2.extractor.DefaultExtractorsFactory; +import com.google.android.exoplayer2.extractor.ExtractorsFactory; +import com.google.android.exoplayer2.source.ExtractorMediaSource; +import com.google.android.exoplayer2.source.MediaSource; +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.ui.SimpleExoPlayerView; +import com.google.android.exoplayer2.upstream.BandwidthMeter; +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 org.androidannotations.annotations.AfterViews; import org.androidannotations.annotations.EFragment; @@ -27,8 +45,9 @@ public class VideoFragment extends Fragment implements CacheListener { @FragmentArg String url; @ViewById ImageView cacheStatusImageView; - @ViewById VideoView videoView; + @ViewById SimpleExoPlayerView simpleExoPlayerView; @ViewById ProgressBar progressBar; + private SimpleExoPlayer simpleExoPlayer; private final VideoProgressUpdater updater = new VideoProgressUpdater(); @@ -41,7 +60,8 @@ public static Fragment build(String url) { @AfterViews void afterViewInjected() { checkCachedState(); - startVideo(); + simpleExoPlayer = setupPlayer(); + simpleExoPlayer.setPlayWhenReady(true); } private void checkCachedState() { @@ -53,32 +73,57 @@ private void checkCachedState() { } } - private void startVideo() { + private SimpleExoPlayer setupPlayer() { + simpleExoPlayerView.setUseController(false); HttpProxyCacheServer proxy = App.getProxy(getActivity()); proxy.registerCacheListener(this, url); String proxyUrl = proxy.getProxyUrl(url); Log.d(LOG_TAG, "Use proxy url " + proxyUrl + " instead of original url " + url); - videoView.setVideoPath(proxyUrl); - videoView.start(); + + SimpleExoPlayer exoPlayer = newSimpleExoPlayer(); + simpleExoPlayerView.setPlayer(exoPlayer); + + MediaSource videoSource = newVideoSource(proxyUrl); + exoPlayer.prepare(videoSource); + + return exoPlayer; + } + + private SimpleExoPlayer newSimpleExoPlayer() { + BandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); + TrackSelection.Factory videoTrackSelectionFactory = new AdaptiveTrackSelection.Factory(bandwidthMeter); + TrackSelector trackSelector = new DefaultTrackSelector(videoTrackSelectionFactory); + LoadControl loadControl = new DefaultLoadControl(); + return ExoPlayerFactory.newSimpleInstance(getActivity(), trackSelector, loadControl); + } + + private MediaSource newVideoSource(String url) { + DefaultBandwidthMeter bandwidthMeter = new DefaultBandwidthMeter(); + String userAgent = Util.getUserAgent(getActivity(), "AndroidVideoCache sample"); + DataSource.Factory dataSourceFactory = new DefaultDataSourceFactory(getActivity(), userAgent, bandwidthMeter); + ExtractorsFactory extractorsFactory = new DefaultExtractorsFactory(); + return new ExtractorMediaSource(Uri.parse(url), dataSourceFactory, extractorsFactory, null, null); } @Override public void onResume() { super.onResume(); updater.start(); + simpleExoPlayer.setPlayWhenReady(true); } @Override public void onPause() { super.onPause(); updater.stop(); + simpleExoPlayer.setPlayWhenReady(false); } @Override public void onDestroy() { super.onDestroy(); - videoView.stopPlayback(); + simpleExoPlayer.release(); App.getProxy(getActivity()).unregisterCacheListener(this); } @@ -90,14 +135,14 @@ public void onCacheAvailable(File file, String url, int percentsAvailable) { } private void updateVideoProgress() { - int videoProgress = videoView.getCurrentPosition() * 100 / videoView.getDuration(); - progressBar.setProgress(videoProgress); + long videoProgress = simpleExoPlayer.getCurrentPosition() * 100 / simpleExoPlayer.getDuration(); + progressBar.setProgress((int) videoProgress); } @SeekBarTouchStop(R.id.progressBar) void seekVideo() { - int videoPosition = videoView.getDuration() * progressBar.getProgress() / 100; - videoView.seekTo(videoPosition); + long videoPosition = simpleExoPlayer.getDuration() * progressBar.getProgress() / 100; + simpleExoPlayer.seekTo(videoPosition); } private void setCachedState(boolean cached) { diff --git a/sample/src/main/java/com/danikula/videocache/sample/VideoGalleryActivity.java b/sample/src/main/java/com/danikula/videocache/sample/VideoGalleryActivity.java deleted file mode 100644 index 2a88bc0..0000000 --- a/sample/src/main/java/com/danikula/videocache/sample/VideoGalleryActivity.java +++ /dev/null @@ -1,49 +0,0 @@ -package com.danikula.videocache.sample; - -import android.support.v4.app.Fragment; -import android.support.v4.app.FragmentActivity; -import android.support.v4.app.FragmentStatePagerAdapter; -import android.support.v4.view.ViewPager; - -import com.viewpagerindicator.CirclePageIndicator; - -import org.androidannotations.annotations.AfterViews; -import org.androidannotations.annotations.EActivity; -import org.androidannotations.annotations.ViewById; - -@EActivity(R.layout.activity_video_gallery) -public class VideoGalleryActivity extends FragmentActivity { - - @ViewById ViewPager viewPager; - @ViewById CirclePageIndicator viewPagerIndicator; - - @AfterViews - void afterViewInjected() { - ViewsPagerAdapter viewsPagerAdapter = new ViewsPagerAdapter(this); - viewPager.setAdapter(viewsPagerAdapter); - viewPagerIndicator.setViewPager(viewPager); - } - - private static final class ViewsPagerAdapter extends FragmentStatePagerAdapter { - - public ViewsPagerAdapter(FragmentActivity activity) { - super(activity.getSupportFragmentManager()); - } - - @Override - public Fragment getItem(int position) { - Video video = Video.values()[position]; - return GalleryVideoFragment.build(video.url); - } - - @Override - public int getCount() { - return Video.values().length; - } - - @Override - public CharSequence getPageTitle(int position) { - return Video.values()[position].name(); - } - } -} diff --git a/sample/src/main/res/layout/fragment_video.xml b/sample/src/main/res/layout/fragment_video.xml index c153b69..ea6970a 100644 --- a/sample/src/main/res/layout/fragment_video.xml +++ b/sample/src/main/res/layout/fragment_video.xml @@ -5,8 +5,8 @@ android:layout_height="match_parent" tools:context=".VideoActivity"> -