[Android] [PATCH 2/4] Handle media directories in browser
Geoffrey Métais
geoffrey.metais at gmail.com
Thu Apr 30 14:27:20 CEST 2015
---
vlc-android/res/layout/directory_view_item.xml | 7 +
.../vlc/gui/browser/BaseBrowserAdapter.java | 141 +++++++++++++++++++--
.../vlc/gui/browser/BaseBrowserFragment.java | 39 ++++--
.../vlc/gui/browser/FileBrowserFragment.java | 17 ++-
4 files changed, 172 insertions(+), 32 deletions(-)
diff --git a/vlc-android/res/layout/directory_view_item.xml b/vlc-android/res/layout/directory_view_item.xml
index 762d196..9a5e54f 100644
--- a/vlc-android/res/layout/directory_view_item.xml
+++ b/vlc-android/res/layout/directory_view_item.xml
@@ -8,6 +8,13 @@
android:clickable="true"
android:background="@drawable/background_item">
+ <CheckBox
+ android:id="@+id/browser_checkbox"
+ android:layout_width="wrap_content"
+ android:layout_height="match_parent"
+ android:paddingLeft="15dp"
+ android:visibility="gone"/>
+
<ImageView
android:id="@+id/dvi_icon"
android:layout_width="@dimen/directory_browser_item_size"
diff --git a/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.java b/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.java
index e4d4f0a..8c28031 100644
--- a/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.java
+++ b/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserAdapter.java
@@ -22,35 +22,44 @@
*/
package org.videolan.vlc.gui.browser;
+import android.os.Environment;
import android.support.v7.widget.RecyclerView;
import android.text.TextUtils;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
+import android.widget.CheckBox;
+import android.widget.CompoundButton;
import android.widget.ImageView;
import android.widget.TextView;
import org.videolan.libvlc.Media;
+import org.videolan.vlc.MediaDatabase;
import org.videolan.vlc.MediaWrapper;
import org.videolan.vlc.R;
import org.videolan.vlc.gui.audio.MediaComparators;
import org.videolan.vlc.util.Strings;
import org.videolan.vlc.util.Util;
+import java.io.File;
import java.util.ArrayList;
import java.util.Collections;
import java.util.LinkedList;
+import java.util.List;
public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewHolder> {
private static final String TAG = "VLC/BaseBrowserAdapter";
private static final int TYPE_MEDIA = 0;
private static final int TYPE_SEPARATOR = 1;
+ private static final int TYPE_STORAGE = 2;
protected int FOLDER_RES_ID = R.drawable.ic_menu_folder;
ArrayList<Object> mMediaList = new ArrayList<Object>();
BaseBrowserFragment fragment;
+ MediaDatabase mDbManager;
+ LinkedList<String> mMediaDirsLocation;
public BaseBrowserAdapter(BaseBrowserFragment fragment){
this.fragment = fragment;
@@ -60,7 +69,7 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
public RecyclerView.ViewHolder onCreateViewHolder(ViewGroup parent, int viewType) {
RecyclerView.ViewHolder vh;
View v;
- if (viewType == TYPE_MEDIA) {
+ if (viewType == TYPE_MEDIA || viewType == TYPE_STORAGE) {
v = LayoutInflater.from(parent.getContext())
.inflate(R.layout.directory_view_item, parent, false);
vh = new MediaViewHolder(v);
@@ -74,14 +83,16 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
@Override
public void onBindViewHolder(final RecyclerView.ViewHolder holder, int position) {
- if (holder instanceof MediaViewHolder) {
+ int viewType = getItemViewType(position);
+ if (viewType == TYPE_MEDIA) {
final MediaViewHolder vh = (MediaViewHolder) holder;
final MediaWrapper media = (MediaWrapper) getItem(position);
boolean hasContextMenu = (media.getType() == MediaWrapper.TYPE_AUDIO ||
- media.getType() == MediaWrapper.TYPE_VIDEO ||
- (media.getType() == MediaWrapper.TYPE_DIR && Util.canWrite(media.getLocation())));
+ media.getType() == MediaWrapper.TYPE_VIDEO ||
+ (media.getType() == MediaWrapper.TYPE_DIR && Util.canWrite(media.getLocation())));
+ vh.checkBox.setVisibility(View.GONE);
vh.title.setText(media.getTitle());
- if (media.getDescription() != null && !TextUtils.isEmpty(media.getDescription())) {
+ if (!TextUtils.isEmpty(media.getDescription())) {
vh.text.setVisibility(View.VISIBLE);
vh.text.setText(media.getDescription());
} else
@@ -91,7 +102,7 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
vh.itemView.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- MediaWrapper mw = (MediaWrapper) getItem(holder.getPosition());
+ MediaWrapper mw = (MediaWrapper) getItem(holder.getAdapterPosition());
if (mw.getType() == MediaWrapper.TYPE_DIR)
fragment.browse(mw, holder.getPosition());
else {
@@ -115,17 +126,62 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
vh.more.setOnClickListener(new View.OnClickListener() {
@Override
public void onClick(View v) {
- fragment.onPopupMenu(vh.more, holder.getPosition());
+ fragment.onPopupMenu(vh.more, holder.getAdapterPosition());
}
});
vh.itemView.setOnLongClickListener(new View.OnLongClickListener() {
@Override
public boolean onLongClick(View v) {
- fragment.mRecyclerView.openContextMenu(holder.getPosition());
+ fragment.mRecyclerView.openContextMenu(holder.getAdapterPosition());
return true;
}
});
}
+ } else if (viewType == TYPE_STORAGE) {
+ final MediaViewHolder vh = (MediaViewHolder) holder;
+ final Storage storage = (Storage) getItem(position);
+ vh.title.setText(storage.getName());
+ vh.icon.setVisibility(View.GONE);
+ vh.checkBox.setVisibility(View.VISIBLE);
+ vh.more.setVisibility(View.GONE);
+ String description = storage.getDescription();
+ if (!TextUtils.isEmpty(description)) {
+ vh.text.setVisibility(View.VISIBLE);
+ vh.text.setText(description);
+ } else
+ vh.text.setVisibility(View.INVISIBLE);
+
+ vh.itemView.setOnClickListener(new View.OnClickListener() {
+ @Override
+ public void onClick(View v) {
+ MediaWrapper mw = new MediaWrapper(((Storage)getItem(vh.getAdapterPosition())).getPath());
+ mw.setType(MediaWrapper.TYPE_DIR);
+ fragment.browse(mw, holder.getAdapterPosition());
+ }
+ });
+ vh.checkBox.setChecked(TextUtils.equals(storage.getPath(), Environment.getExternalStorageDirectory().getPath()) ||
+ mMediaDirsLocation == null || mMediaDirsLocation.isEmpty() ||
+ mMediaDirsLocation.contains(storage.getPath()));
+ vh.checkBox.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() {
+ @Override
+ public void onCheckedChanged(CompoundButton compoundButton, boolean isChecked) {
+ String path = ((Storage)getItem(vh.getAdapterPosition())).getPath();
+ updateMediaDirs();
+ if (isChecked)
+ mDbManager.addDir(path);
+ else {
+ if (mMediaDirsLocation == null || mMediaDirsLocation.isEmpty()){
+ String storagePath;
+ for (Object storage : mMediaList){
+ storagePath = ((Storage)storage).getPath();
+ if (!TextUtils.equals(storagePath, path))
+ mDbManager.addDir(storagePath);
+ }
+ } else
+ mDbManager.removeDir(path);
+ }
+ }
+ });
} else {
SeparatorViewHolder vh = (SeparatorViewHolder) holder;
vh.title.setText(getItem(position).toString());
@@ -139,6 +195,7 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
public class MediaViewHolder extends RecyclerView.ViewHolder {
public TextView title;
+ public CheckBox checkBox;
public TextView text;
public ImageView icon;
public ImageView more;
@@ -146,6 +203,7 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
public MediaViewHolder(View v) {
super(v);
title = (TextView) v.findViewById(R.id.title);
+ checkBox = (CheckBox) v.findViewById(R.id.browser_checkbox);
text = (TextView) v.findViewById(R.id.text);
icon = (ImageView) v.findViewById(R.id.dvi_icon);
more = (ImageView) v.findViewById(R.id.item_more);
@@ -161,6 +219,33 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
}
}
+ public static class Storage {
+ String path;
+ String name;
+ String description;
+
+ public Storage(String location){
+ path = location;
+ name = Strings.getName(path);
+ }
+
+ public String getName() {
+ return name;
+ }
+
+ public void setDescription(String description) {
+ this.description = description;
+ }
+
+ public String getDescription() {
+ return description;
+ }
+
+ public String getPath() {
+ return path;
+ }
+ }
+
public void clear(){
mMediaList.clear();
notifyDataSetChanged();
@@ -188,6 +273,30 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
notifyItemInserted(position);
}
+ public void setDescription(int position, String description){
+ Object item = getItem(position);
+ if (item instanceof MediaWrapper)
+ ((MediaWrapper) item).setDescription(description);
+ else if (item instanceof Storage)
+ ((Storage) item).setDescription(description);
+ else
+ return;
+ notifyItemChanged(position);
+ }
+
+ public void updateMediaDirs(){
+ if (mDbManager == null)
+ mDbManager = MediaDatabase.getInstance();
+ if (mMediaDirsLocation == null)
+ mMediaDirsLocation = new LinkedList<String>();
+ else
+ mMediaDirsLocation.clear();
+ List<File> mediaDirs = mDbManager.getMediaDirs();
+ for (File dir : mediaDirs){
+ mMediaDirsLocation.add(dir.getPath());
+ }
+ }
+
public void addAll(ArrayList<MediaWrapper> mediaList){
mMediaList.clear();
for (MediaWrapper mw : mediaList)
@@ -208,6 +317,8 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
public int getItemViewType(int position){
if (getItem(position) instanceof MediaWrapper)
return TYPE_MEDIA;
+ else if (getItem(position) instanceof Storage)
+ return TYPE_STORAGE;
else
return TYPE_SEPARATOR;
}
@@ -223,11 +334,17 @@ public class BaseBrowserAdapter extends RecyclerView.Adapter<RecyclerView.ViewH
files.add(media);
}
}
- Collections.sort(dirs, MediaComparators.byName);
- Collections.sort(files, MediaComparators.byName);
+ if (dirs.isEmpty() && files.isEmpty())
+ return;
mMediaList.clear();
- mMediaList.addAll(dirs);
- mMediaList.addAll(files);
+ if (!dirs.isEmpty()) {
+ Collections.sort(dirs, MediaComparators.byName);
+ mMediaList.addAll(dirs);
+ }
+ if (!files.isEmpty()) {
+ Collections.sort(files, MediaComparators.byName);
+ mMediaList.addAll(files);
+ }
notifyDataSetChanged();
}
diff --git a/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.java b/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.java
index a1ae077..dee0c1d 100644
--- a/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.java
+++ b/vlc-android/src/org/videolan/vlc/gui/browser/BaseBrowserFragment.java
@@ -92,7 +92,7 @@ public abstract class BaseBrowserFragment extends MediaBrowserFragment implement
protected boolean mRoot;
protected LibVLC mLibVLC;
- private SparseArray<ArrayList<MediaWrapper>> mMediaLists;
+ private SparseArray<ArrayList<MediaWrapper>> mMediaLists = new SparseArray<ArrayList<MediaWrapper>>();
private ArrayList<MediaWrapper> mediaList;
public int mCurrentParsedPosition = 0;
@@ -444,17 +444,23 @@ public abstract class BaseBrowserFragment extends MediaBrowserFragment implement
protected void parseSubDirectories() {
if (mCurrentParsedPosition == -1 || mAdapter.isEmpty())
return;
- mMediaLists = new SparseArray<ArrayList<MediaWrapper>>();
+ mMediaLists.clear();
mMediaBrowser.changeEventListener(mFoldersBrowserListener);
mCurrentParsedPosition = 0;
Object item;
MediaWrapper mw;
while (mCurrentParsedPosition <mAdapter.getItemCount()){
item = mAdapter.getItem(mCurrentParsedPosition);
- if (item instanceof MediaWrapper){
+ if (item instanceof BaseBrowserAdapter.Storage) {
+ mw = new MediaWrapper(((BaseBrowserAdapter.Storage) item).getPath());
+ mw.setType(MediaWrapper.TYPE_DIR);
+ } else if (item instanceof MediaWrapper){
mw = (MediaWrapper) item;
+ } else
+ mw = null;
+ if (mw != null){
if (mw.getType() == MediaWrapper.TYPE_DIR || mw.getType() == MediaWrapper.TYPE_PLAYLIST){
- mMediaBrowser.browse(((MediaWrapper) mAdapter.getItem(mCurrentParsedPosition)).getLocation());
+ mMediaBrowser.browse(mw.getLocation());
return;
}
}
@@ -486,27 +492,32 @@ public abstract class BaseBrowserFragment extends MediaBrowserFragment implement
return;
}
String holderText = getDescription(directories.size(), files.size());
- MediaWrapper mw = (MediaWrapper) mAdapter.getItem(mCurrentParsedPosition);
+ MediaWrapper mw = null;
if (!TextUtils.equals(holderText, "")) {
- mw.setDescription(holderText);
- mAdapter.notifyItemChanged(mCurrentParsedPosition);
+ mAdapter.setDescription(mCurrentParsedPosition, holderText);
directories.addAll(files);
mMediaLists.append(mCurrentParsedPosition, directories);
}
- while (++mCurrentParsedPosition < mAdapter.getItemCount()-1){ //skip media that are not browsable
+ while (++mCurrentParsedPosition < mAdapter.getItemCount()){ //skip media that are not browsable
if (mAdapter.getItem(mCurrentParsedPosition) instanceof MediaWrapper) {
mw = (MediaWrapper) mAdapter.getItem(mCurrentParsedPosition);
if (mw.getType() == MediaWrapper.TYPE_DIR || mw.getType() == MediaWrapper.TYPE_PLAYLIST)
break;
- }
+ } else if (mAdapter.getItem(mCurrentParsedPosition) instanceof BaseBrowserAdapter.Storage) {
+ mw = new MediaWrapper(((BaseBrowserAdapter.Storage) mAdapter.getItem(mCurrentParsedPosition)).getPath());
+ break;
+ } else
+ mw = null;
}
- if (mCurrentParsedPosition < mAdapter.getItemCount()) {
- mMediaBrowser.browse(((MediaWrapper) mAdapter.getItem(mCurrentParsedPosition)).getLocation());
- } else {
- mCurrentParsedPosition = -1;
- mMediaBrowser.release();
+ if (mw != null) {
+ if (mCurrentParsedPosition < mAdapter.getItemCount()) {
+ mMediaBrowser.browse(mw.getLocation());
+ } else {
+ mCurrentParsedPosition = -1;
+ mMediaBrowser.release();
+ }
}
directories .clear();
files.clear();
diff --git a/vlc-android/src/org/videolan/vlc/gui/browser/FileBrowserFragment.java b/vlc-android/src/org/videolan/vlc/gui/browser/FileBrowserFragment.java
index 1d48d91..34884f5 100644
--- a/vlc-android/src/org/videolan/vlc/gui/browser/FileBrowserFragment.java
+++ b/vlc-android/src/org/videolan/vlc/gui/browser/FileBrowserFragment.java
@@ -68,12 +68,10 @@ public class FileBrowserFragment extends BaseBrowserFragment {
@Override
protected void browseRoot() {
String storages[] = AndroidDevices.getMediaDirectories();
- MediaWrapper mw;
- for (String storage : storages) {
- mw = new MediaWrapper(storage);
- mw.setTitle(AndroidDevices.getStorageTitle(storage));
- mw.setType(MediaWrapper.TYPE_DIR);
- mAdapter.addItem(mw, false, false);
+ BaseBrowserAdapter.Storage storage;
+ for (String mediaDirLocation : storages) {
+ storage = new BaseBrowserAdapter.Storage(mediaDirLocation);
+ mAdapter.addItem(storage, false, false);
}
mHandler.sendEmptyMessage(BrowserFragmentHandler.MSG_HIDE_LOADING);
if (mReadyToDisplay) {
@@ -98,6 +96,13 @@ public class FileBrowserFragment extends BaseBrowserFragment {
}
@Override
+ protected void updateDisplay() {
+ super.updateDisplay();
+ if (isRootDirectory())
+ mAdapter.updateMediaDirs();
+ }
+
+ @Override
public void onStop() {
super.onStop();
getActivity().unregisterReceiver(storageReceiver);
--
2.1.4
More information about the Android
mailing list