|
package pune.university.engineering.gifutilstest; |
|
|
|
import android.content.ContentResolver; |
|
import android.content.Context; |
|
import android.net.Uri; |
|
import android.os.Handler; |
|
import android.support.annotation.AnyRes; |
|
import android.support.annotation.NonNull; |
|
import android.support.v7.app.AppCompatActivity; |
|
import android.os.Bundle; |
|
import android.support.v7.widget.LinearLayoutManager; |
|
import android.support.v7.widget.RecyclerView; |
|
import android.util.Log; |
|
import android.view.View; |
|
import android.widget.AbsListView; |
|
import android.widget.ImageView; |
|
|
|
import com.danikula.videocache.HttpProxyCacheServer; |
|
import com.klinker.android.simple_videoview.SimpleVideoView; |
|
import com.squareup.picasso.Picasso; |
|
|
|
import java.util.ArrayList; |
|
|
|
import butterknife.ButterKnife; |
|
import butterknife.InjectView; |
|
|
|
public class VideoListActivity extends AppCompatActivity { |
|
|
|
private static final String TAG = "VideoListActivity"; |
|
|
|
@InjectView(R.id.recyclerView) |
|
RecyclerView mRecyclerView; |
|
|
|
private LinearLayoutManager mLayoutManager; |
|
|
|
private int mScrollState = AbsListView.OnScrollListener.SCROLL_STATE_IDLE; |
|
|
|
private ArrayList<VideoModel> arrayList = new ArrayList<>(); |
|
|
|
MyVideoRecyclerViewAdapter videoRecyclerViewAdapter; |
|
|
|
// This Method returns the URI in string of the drawable passed as argument |
|
public static final String getUriToDrawable(@NonNull Context context, |
|
@AnyRes int drawableId) { |
|
Uri imageUri = Uri.parse(ContentResolver.SCHEME_ANDROID_RESOURCE + |
|
"://" + context.getResources().getResourcePackageName(drawableId) |
|
+ '/' + context.getResources().getResourceTypeName(drawableId) |
|
+ '/' + context.getResources().getResourceEntryName(drawableId)); |
|
return imageUri.toString(); |
|
} |
|
|
|
@Override |
|
protected void onPause() { |
|
super.onPause(); |
|
|
|
// We need to pause any playback when the application is minimised |
|
|
|
try { |
|
int firstCompletelyVisibleItemPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition(); |
|
SimpleVideoView video_view = (SimpleVideoView) mLayoutManager.findViewByPosition(firstCompletelyVisibleItemPosition).findViewById(R.id.video_view); |
|
|
|
video_view.release(); |
|
|
|
} catch (NullPointerException e) { |
|
// Sometimes you scroll so fast that the views are not attached so it gives a NullPointerException |
|
} catch (ArrayIndexOutOfBoundsException e) { |
|
|
|
} |
|
|
|
} |
|
|
|
@Override |
|
protected void onCreate(Bundle savedInstanceState) { |
|
super.onCreate(savedInstanceState); |
|
setContentView(R.layout.activity_video_list); |
|
|
|
ButterKnife.inject(this); |
|
|
|
mRecyclerView.setHasFixedSize(true); |
|
mLayoutManager = new LinearLayoutManager(this); |
|
mRecyclerView.setLayoutManager(mLayoutManager); |
|
|
|
// String array of URL of some sample Videos |
|
String[] video_urls = new String[]{"http://clips.vorwaerts-gmbh.de/VfE_html5.mp4", |
|
"http://techslides.com/demos/sample-videos/small.webm", |
|
"http://mirrors.standaloneinstaller.com/video-sample/TRA3106.flv", |
|
"http://mirrors.standaloneinstaller.com/video-sample/lion-sample.3gp", |
|
"http://mirrors.standaloneinstaller.com/video-sample/dolbycanyon.mp4" |
|
}; |
|
|
|
// Double array of Width to Height Ratio of the above videos manually pre calculated by me |
|
Double[] video_width_to_height_ratio = new Double[]{1.777, |
|
1.75, |
|
1.451612, |
|
1.2222, |
|
1.2222 |
|
}; |
|
// Will be used to change the height of the Row Layout according to the height of the Video |
|
// we use ratio of width and height and not only height because different devices have different dimensions |
|
|
|
|
|
// String[] of Uris of the Thumbnails of the videos manually extracted by me |
|
final String[] thumbnails_string = new String[]{ |
|
getUriToDrawable(this, R.drawable.vfe_html5), |
|
getUriToDrawable(this, R.drawable.small), |
|
getUriToDrawable(this, R.drawable.tra3106), |
|
getUriToDrawable(this, R.drawable.lion_sample), |
|
getUriToDrawable(this, R.drawable.dolbycanyon), |
|
}; |
|
|
|
// Now putting that data in an ArrayList |
|
for (int i = 0; i < video_urls.length; i++) { |
|
|
|
// Object from the Video caching library com.danikula:videocache |
|
HttpProxyCacheServer httpProxyCacheServer = new HttpProxyCacheServer(this); |
|
|
|
// Passing the url of videos from the string[] video_urls to com.danikula:videocache |
|
String proxy_url = httpProxyCacheServer.getProxyUrl(video_urls[i]); |
|
// com.danikula:videocache will cache the video from the Url and save it in phone memory |
|
// the proxy_url will be the local path to the video and look something like this |
|
// file:///data/data/<Your Package Name>/cache/video-cache/0228e681cad575e5352b203922b5229b.m4v |
|
|
|
// Now put this proxy_url in your arrayList instead of the video _url |
|
arrayList.add(new VideoModel(proxy_url, video_width_to_height_ratio[i], thumbnails_string[i])); |
|
// and we are done with the Video caching |
|
|
|
} |
|
|
|
videoRecyclerViewAdapter = new MyVideoRecyclerViewAdapter(arrayList, this); |
|
mRecyclerView.setAdapter(videoRecyclerViewAdapter); |
|
|
|
mRecyclerView.addOnScrollListener(new RecyclerView.OnScrollListener() { |
|
|
|
// Position of the row that is active |
|
int activeAdapter = 0; |
|
|
|
@Override |
|
public void onScrolled(RecyclerView recyclerView, int dx, int dy) { |
|
super.onScrolled(recyclerView, dx, dy); |
|
|
|
// Get the index of the first Completely visible item |
|
int firstCompletelyVisibleItemPosition = mLayoutManager.findFirstCompletelyVisibleItemPosition(); |
|
Log.d(TAG, "onScrolled: firstCompletelyVisibleItemPosition : " + firstCompletelyVisibleItemPosition); |
|
|
|
// Even if we scroll by a few millimeters the video will start playing from the beginning |
|
// So we need to check if the new Active row layout position is equal to the current active row layout position |
|
|
|
if (activeAdapter != firstCompletelyVisibleItemPosition) { |
|
|
|
try { |
|
VideoModel videoModel = (VideoModel) arrayList.get(firstCompletelyVisibleItemPosition); |
|
String video_url = videoModel.getVideo_url(); |
|
SimpleVideoView video_view = (SimpleVideoView) mLayoutManager.findViewByPosition(firstCompletelyVisibleItemPosition).findViewById(R.id.video_view); |
|
final ImageView iv_cover = (ImageView) mLayoutManager.findViewByPosition(firstCompletelyVisibleItemPosition).findViewById(R.id.iv_cover); |
|
|
|
// Start playing the video in Active row layout |
|
video_view.start(Uri.parse(video_url)); |
|
|
|
// assign this row layout position as active row Layout |
|
activeAdapter = firstCompletelyVisibleItemPosition; |
|
Log.d(TAG, "onScrolled: activeAdapter : " + activeAdapter); |
|
|
|
|
|
// Hide the thumbnail ImageView with a delay of 300 millisecond or else there will be black |
|
// screen before a video plays |
|
new Handler().postDelayed(new Runnable() { |
|
@Override |
|
public void run() { |
|
iv_cover.setVisibility(View.INVISIBLE); |
|
} |
|
}, 300); |
|
|
|
|
|
} catch (NullPointerException e) { |
|
// Sometimes you scroll so fast that the views are not attached so it gives a NullPointerException |
|
} catch (ArrayIndexOutOfBoundsException e) { |
|
|
|
} |
|
|
|
/* Get the Video Surface directly above the fully visible Row Layout so that you may stop the playback |
|
when a new row Layout is fully visible |
|
*/ |
|
if (firstCompletelyVisibleItemPosition >= 1) { |
|
|
|
try { |
|
SimpleVideoView video_view_above = (SimpleVideoView) mLayoutManager.findViewByPosition(firstCompletelyVisibleItemPosition - 1).findViewById(R.id.video_view); |
|
video_view_above.release(); |
|
|
|
VideoModel videoModel = (VideoModel) arrayList.get(firstCompletelyVisibleItemPosition - 1); |
|
String thumbnail_string = videoModel.getThumbnail(); |
|
// video_view_above.start(Uri.parse(thumbnail_string)); |
|
|
|
ImageView iv_cover_above = (ImageView) mLayoutManager.findViewByPosition(firstCompletelyVisibleItemPosition - 1).findViewById(R.id.iv_cover); |
|
|
|
// Show the cover Thumbnail ImageView |
|
iv_cover_above.setVisibility(View.VISIBLE); |
|
|
|
Picasso.with(VideoListActivity.this) |
|
.load((Uri.parse(thumbnail_string))) |
|
.into(iv_cover_above); |
|
|
|
// video_view_above.setBackground(Uri.parse(thumbnail_string)); |
|
|
|
} catch (NullPointerException e) { |
|
} catch (ArrayIndexOutOfBoundsException e) { |
|
} |
|
} |
|
|
|
/* Get the Video Surface directly Below the fully visible Row Layout so that you may stop the playback |
|
when a new row Layout is fully visible |
|
*/ |
|
if (firstCompletelyVisibleItemPosition + 1 < arrayList.size()) { |
|
|
|
try { |
|
SimpleVideoView video_view_below = (SimpleVideoView) mLayoutManager.findViewByPosition(firstCompletelyVisibleItemPosition + 1).findViewById(R.id.video_view); |
|
video_view_below.release(); |
|
|
|
VideoModel videoModel = (VideoModel) arrayList.get(firstCompletelyVisibleItemPosition + 1); |
|
String thumbnail_string = videoModel.getThumbnail(); |
|
// video_view_below.start(Uri.parse(thumbnail_string)); |
|
|
|
ImageView iv_cover_below = (ImageView) mLayoutManager.findViewByPosition(firstCompletelyVisibleItemPosition + 1).findViewById(R.id.iv_cover); |
|
|
|
iv_cover_below.setVisibility(View.VISIBLE); |
|
|
|
Picasso.with(VideoListActivity.this) |
|
.load((Uri.parse(thumbnail_string))) |
|
.into(iv_cover_below); |
|
|
|
} catch (NullPointerException e) { |
|
} catch (ArrayIndexOutOfBoundsException e) { |
|
} |
|
|
|
} |
|
|
|
} |
|
|
|
} |
|
}); |
|
|
|
|
|
} |
|
} |
c