[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