[Android] [PATCH] Extended browsing for videos WIP
Geoffrey Métais
geoffrey.metais at gmail.com
Wed Oct 1 19:22:52 CEST 2014
Only videos for now, will be adapted to other media soon
Need to find a batter 'grid launcher' too.
---
vlc-android/AndroidManifest.xml | 4 +
vlc-android/res/layout/tv_vertical_grid | 6 +
.../src/org/videolan/vlc/gui/tv/GridFragment.java | 189 +++++++++++++++++++++
.../org/videolan/vlc/gui/tv/MainTvActivity.java | 37 ++--
.../vlc/gui/tv/MediaItemDetailsFragment.java | 4 +-
.../videolan/vlc/gui/tv/VerticalGridActivity.java | 17 ++
6 files changed, 242 insertions(+), 15 deletions(-)
create mode 100644 vlc-android/res/layout/tv_vertical_grid
create mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
create mode 100644 vlc-android/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
diff --git a/vlc-android/AndroidManifest.xml b/vlc-android/AndroidManifest.xml
index cd95905..bb73720 100644
--- a/vlc-android/AndroidManifest.xml
+++ b/vlc-android/AndroidManifest.xml
@@ -54,6 +54,10 @@
android:exported="true"
android:theme="@style/Theme.Leanback"/>
+ <activity android:name="org.videolan.vlc.gui.tv.VerticalGridActivity"
+ android:exported="true"
+ android:theme="@style/Theme.Leanback"/>
+
<activity android:name=".gui.CompatErrorActivity" />
<activity android:name=".gui.PreferencesActivity" />
<activity
diff --git a/vlc-android/res/layout/tv_vertical_grid b/vlc-android/res/layout/tv_vertical_grid
new file mode 100644
index 0000000..7d58289
--- /dev/null
+++ b/vlc-android/res/layout/tv_vertical_grid
@@ -0,0 +1,6 @@
+<fragment xmlns:android="http://schemas.android.com/apk/res/android"
+ android:name="org.videolan.vlc.gui.tv.GridFragment"
+ android:id="@+id/vertical_grid_fragment"
+ android:layout_width="match_parent"
+ android:layout_height="match_parent"
+/>
\ No newline at end of file
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java b/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
new file mode 100644
index 0000000..e24f89b
--- /dev/null
+++ b/vlc-android/src/org/videolan/vlc/gui/tv/GridFragment.java
@@ -0,0 +1,189 @@
+package org.videolan.vlc.gui.tv;
+
+import java.util.ArrayList;
+import java.util.HashMap;
+import java.util.concurrent.BrokenBarrierException;
+import java.util.concurrent.CyclicBarrier;
+
+import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaDatabase;
+import org.videolan.vlc.MediaLibrary;
+import org.videolan.vlc.R;
+import org.videolan.vlc.Thumbnailer;
+import org.videolan.vlc.VLCApplication;
+import org.videolan.vlc.gui.video.VideoBrowserInterface;
+import org.videolan.vlc.gui.video.VideoPlayerActivity;
+import org.videolan.vlc.util.WeakHandler;
+
+import android.content.Context;
+import android.content.Intent;
+import android.graphics.Bitmap;
+import android.os.Bundle;
+import android.os.Handler;
+import android.os.Message;
+import android.support.v17.leanback.app.VerticalGridFragment;
+import android.support.v17.leanback.widget.ArrayObjectAdapter;
+import android.support.v17.leanback.widget.OnItemClickedListener;
+import android.support.v17.leanback.widget.OnItemSelectedListener;
+import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.VerticalGridPresenter;
+import android.util.Log;
+
+public class GridFragment extends VerticalGridFragment implements VideoBrowserInterface {
+ private static final String TAG = "VerticalGridFragment";
+
+ private static final int NUM_COLUMNS = 5;
+
+ protected final CyclicBarrier mBarrier = new CyclicBarrier(2);
+ protected Media mItemToUpdate;
+ private ArrayObjectAdapter mAdapter;
+ private MediaLibrary mMediaLibrary;
+ private Thumbnailer mThumbnailer;
+ HashMap<String, Integer> mVideoIndex;
+ Context mContext;
+
+ @Override
+ public void onCreate(Bundle savedInstanceState) {
+ Log.i(TAG, "onCreate");
+ super.onCreate(savedInstanceState);
+ mContext = getActivity();
+
+ setTitle(getString(R.string.app_name_full));
+
+ mMediaLibrary = MediaLibrary.getInstance();
+ mThumbnailer = new Thumbnailer(mContext, getActivity().getWindowManager().getDefaultDisplay());
+ setupFragment();
+ }
+
+ public void onResume() {
+ super.onResume();
+ if (mMediaLibrary.isWorking()) {
+ actionScanStart();
+ }
+
+ /* Start the thumbnailer */
+ if (mThumbnailer != null)
+ mThumbnailer.start(this);
+ }
+
+ public void onPause() {
+ super.onPause();
+ mMediaLibrary.removeUpdateHandler(mHandler);
+
+ /* Stop the thumbnailer */
+ if (mThumbnailer != null)
+ mThumbnailer.stop();
+ }
+
+ @Override
+ public void onDestroy() {
+ super.onDestroy();
+ if (mThumbnailer != null)
+ mThumbnailer.clearJobs();
+ mBarrier.reset();
+ }
+
+ private void setupFragment() {
+ int size;
+ Media media;
+ Bitmap picture;
+
+ MediaDatabase mediaDatabase = MediaDatabase.getInstance();
+ VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
+ mAdapter = new ArrayObjectAdapter(new CardPresenter());
+
+ gridPresenter.setNumberOfColumns(NUM_COLUMNS);
+ setGridPresenter(gridPresenter);
+
+
+ ArrayList<Media> videoList = mMediaLibrary.getVideoItems();
+ size = videoList.size();
+ mVideoIndex = new HashMap<String, Integer>(size);
+
+ for (int i = 0 ; i < size ; ++i){
+ media = videoList.get(i);
+ picture = mediaDatabase.getPicture(mContext, media.getLocation());
+ mAdapter.add(media);
+ mVideoIndex.put(media.getLocation(), i);
+ if (mThumbnailer != null){
+ if (picture== null) {
+ mThumbnailer.addJob(media);
+ } else {
+ MediaDatabase.setPicture(media, picture);
+ picture = null;
+ }
+ }
+ }
+
+ setAdapter(mAdapter);
+
+ /*setOnItemSelectedListener(new OnItemSelectedListener() {
+ @Override
+ public void onItemSelected(Object item, Row row) {
+ }
+ });*/
+
+ setOnItemClickedListener(new OnItemClickedListener() {
+ @Override
+ public void onItemClicked(Object item, Row row) {
+ Media media = (Media)item;
+ if (media.getType() == Media.TYPE_VIDEO){
+ VideoPlayerActivity.start(getActivity(), media.getLocation(), false);
+ }
+ }
+ });
+ }
+
+ public void await() throws InterruptedException, BrokenBarrierException {
+ mBarrier.await();
+ }
+
+ public void resetBarrier() {
+ mBarrier.reset();
+ }
+ @Override
+ public void setItemToUpdate(Media item) {
+ mItemToUpdate = item;
+ mHandler.sendEmptyMessage(UPDATE_ITEM);
+ }
+
+ private void updateItem() {
+ mAdapter.notifyArrayItemRangeChanged(mVideoIndex.get(mItemToUpdate.getLocation()), 1);
+ try {
+ mBarrier.await();
+ } catch (InterruptedException e) {
+ } catch (BrokenBarrierException e) {}
+ }
+
+ public static void actionScanStart() {
+ Intent intent = new Intent();
+ intent.setAction(ACTION_SCAN_START);
+ VLCApplication.getAppContext().sendBroadcast(intent);
+ }
+
+ public static void actionScanStop() {
+ Intent intent = new Intent();
+ intent.setAction(ACTION_SCAN_STOP);
+ VLCApplication.getAppContext().sendBroadcast(intent);
+ }
+
+ private Handler mHandler = new VideoListHandler(this);
+
+ private static class VideoListHandler extends WeakHandler<GridFragment> {
+ public VideoListHandler(GridFragment owner) {
+ super(owner);
+ }
+
+ @Override
+ public void handleMessage(Message msg) {
+ GridFragment owner = getOwner();
+ if(owner == null) return;
+
+ switch (msg.what) {
+ case UPDATE_ITEM:
+ owner.updateItem();
+ break;
+ }
+ }
+ };
+}
\ No newline at end of file
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java b/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
index 7650cf1..42ff0c4 100644
--- a/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
+++ b/vlc-android/src/org/videolan/vlc/gui/tv/MainTvActivity.java
@@ -17,15 +17,13 @@ import org.videolan.vlc.util.WeakHandler;
import android.app.Activity;
import android.app.FragmentManager;
-import android.content.ContentResolver;
import android.content.Intent;
-import android.content.res.Resources;
import android.graphics.Bitmap;
import android.graphics.drawable.Drawable;
-import android.net.Uri;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
+import android.os.Parcelable;
import android.support.v17.leanback.app.BackgroundManager;
import android.support.v17.leanback.app.BrowseFragment;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
@@ -34,9 +32,10 @@ import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
import android.support.v17.leanback.widget.OnItemClickedListener;
import android.support.v17.leanback.widget.Row;
-import android.support.v4.app.FragmentActivity;
-public class MainTvActivity extends FragmentActivity implements VideoBrowserInterface {
+public class MainTvActivity extends Activity implements VideoBrowserInterface {
+
+ private static final int NUM_VIDEOS_PREVIEW = 5;
public static final String TAG = "BrowseActivity";
@@ -55,14 +54,21 @@ public class MainTvActivity extends FragmentActivity implements VideoBrowserInte
OnItemClickedListener mItemClickListener = new OnItemClickedListener() {
@Override
public void onItemClicked(Object item, Row row) {
- VideoPlayerActivity.start(mContext, ((Media)item).getLocation(), false);
- //code to launch a DetailActivity
- // Intent intent = new Intent(MainTvActivity.this,
- // DetailsActivity.class);
- // // pass the item information
- // intent.putExtra("id", row.getId());
- // intent.putExtra("item", (Parcelable)item);
- // startActivity(intent);
+ Media media = (Media)item;
+ if (media.getType() == Media.TYPE_VIDEO){
+ VideoPlayerActivity.start(mContext, media.getLocation(), false);
+ } else if (media.getType() == Media.TYPE_AUDIO){
+
+ Intent intent = new Intent(MainTvActivity.this,
+ DetailsActivity.class);
+ // pass the item information
+ intent.putExtra("id", row.getId());
+ intent.putExtra("item", (Parcelable)new TvMedia(0, media.getTitle(), media.getDescription(), media.getArtworkURL(), media.getArtworkURL(), media.getLocation()));
+ startActivity(intent);
+ } else if (media.getType() == Media.TYPE_GROUP){
+ Intent intent = new Intent(mContext, VerticalGridActivity.class);
+ startActivity(intent);
+ }
}
};
@@ -163,7 +169,7 @@ public class MainTvActivity extends FragmentActivity implements VideoBrowserInte
mVideoIndex = new HashMap<String, Integer>(size);
videoAdapter = new ArrayObjectAdapter(
new CardPresenter());
- for (int i = 0 ; i < videoList.size() ; ++i) {
+ for (int i = 0 ; i < NUM_VIDEOS_PREVIEW ; ++i) {
item = videoList.get(i);
picture = mediaDatabase.getPicture(this, item.getLocation());
@@ -178,6 +184,9 @@ public class MainTvActivity extends FragmentActivity implements VideoBrowserInte
}
}
}
+ // Empty item to launch grid activity
+ videoAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
+
HeaderItem header = new HeaderItem(0, "Videos", null);
mRowsAdapter.add(new ListRow(header, videoAdapter));
}
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java b/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
index d02025a..7092b4a 100644
--- a/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
+++ b/vlc-android/src/org/videolan/vlc/gui/tv/MediaItemDetailsFragment.java
@@ -1,5 +1,7 @@
package org.videolan.vlc.gui.tv;
+import org.videolan.vlc.R;
+
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v17.leanback.app.DetailsFragment;
@@ -43,7 +45,7 @@ public class MediaItemDetailsFragment extends DetailsFragment {
DetailsOverviewRow detailsOverview = new DetailsOverviewRow(new MediaItemDetails(media.getTitle(), media.getDescription(), "Big body"));
// Add images and action buttons to the details view
- detailsOverview.setImageDrawable(res.getDrawable(media.getCardImageId()));
+ detailsOverview.setImageDrawable(res.getDrawable(R.drawable.cone));
detailsOverview.addAction(new Action(1, "Play"));
detailsOverview.addAction(new Action(2, "Delete"));
mRowsAdapter.add(detailsOverview);
diff --git a/vlc-android/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java b/vlc-android/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
new file mode 100644
index 0000000..64e96f1
--- /dev/null
+++ b/vlc-android/src/org/videolan/vlc/gui/tv/VerticalGridActivity.java
@@ -0,0 +1,17 @@
+package org.videolan.vlc.gui.tv;
+
+import org.videolan.vlc.R;
+
+import android.app.Activity;
+import android.os.Bundle;
+
+public class VerticalGridActivity extends Activity {
+
+ @Override
+ public void onCreate(Bundle savedInstanceState)
+ {
+ super.onCreate(savedInstanceState);
+ setContentView(R.layout.tv_vertical_grid);
+ getWindow().setBackgroundDrawableResource(R.drawable.background);
+ }
+}
--
1.9.1
More information about the Android
mailing list