[Android] [PATCH] Fragment with history to open Uris

Geoffrey Métais geoffrey.metais at gmail.com
Thu Dec 18 15:28:10 CET 2014


---
 vlc-android/build.gradle                           |   1 +
 vlc-android/res/layout/mrl_item.xml                |  21 +++++
 vlc-android/res/layout/mrl_panel.xml               |  20 ++++
 vlc-android/res/menu-v10/media_library.xml         |  48 ----------
 vlc-android/res/menu-v13/media_library.xml         |   8 ++
 vlc-android/res/menu-v7/media_library.xml          |   8 ++
 .../src/org/videolan/vlc/MediaDatabase.java        |  69 +++++++++++++-
 .../videolan/vlc/gui/DividerItemDecoration.java    | 105 +++++++++++++++++++++
 .../src/org/videolan/vlc/gui/MainActivity.java     |  55 ++---------
 .../src/org/videolan/vlc/gui/MrlAdapter.java       |  70 ++++++++++++++
 .../src/org/videolan/vlc/gui/MrlPanelFragment.java |  91 ++++++++++++++++++
 .../src/org/videolan/vlc/gui/SidebarAdapter.java   |  12 ++-
 vlc-android/src/org/videolan/vlc/util/Util.java    |  21 +++++
 .../gui/tv/audioplayer/DividerItemDecoration.java  | 105 ---------------------
 14 files changed, 427 insertions(+), 207 deletions(-)
 create mode 100644 vlc-android/res/layout/mrl_item.xml
 create mode 100644 vlc-android/res/layout/mrl_panel.xml
 delete mode 100644 vlc-android/res/menu-v10/media_library.xml
 create mode 100644 vlc-android/src/org/videolan/vlc/gui/DividerItemDecoration.java
 create mode 100644 vlc-android/src/org/videolan/vlc/gui/MrlAdapter.java
 create mode 100644 vlc-android/src/org/videolan/vlc/gui/MrlPanelFragment.java
 delete mode 100644 vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java

diff --git a/vlc-android/build.gradle b/vlc-android/build.gradle
index 6486850..6b0869a 100644
--- a/vlc-android/build.gradle
+++ b/vlc-android/build.gradle
@@ -127,5 +127,6 @@ dependencies {
     compile project(':libvlc')
     compile 'com.android.support:appcompat-v7:21.0.+'
     compile 'com.android.support:cardview-v7:21.0.+'
+    compile 'com.android.support:recyclerview-v7:21.0.+'
     tvCompile 'com.android.support:leanback-v17:21.0.+'
 }
\ No newline at end of file
diff --git a/vlc-android/res/layout/mrl_item.xml b/vlc-android/res/layout/mrl_item.xml
new file mode 100644
index 0000000..ea6f39c
--- /dev/null
+++ b/vlc-android/res/layout/mrl_item.xml
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    android:layout_width="match_parent" android:layout_height="50dp">
+    <TextView
+        android:id="@+id/mrl_item_uri"
+        android:layout_width="match_parent"
+        android:layout_height="match_parent"
+        android:paddingLeft="10dp"
+        android:clickable="true"
+        android:layout_toLeftOf="@+id/mrl_item_delete"
+        android:gravity="center_vertical"
+        android:layout_alignBottom="@+id/mrl_item_delete"
+        android:layout_alignTop="@+id/mrl_item_delete"/>
+    <ImageButton
+        android:id="@+id/mrl_item_delete"
+        android:layout_width="wrap_content"
+        android:layout_height="match_parent"
+        android:layout_alignParentTop="true"
+        android:layout_alignParentRight="true"
+        android:src="@drawable/ic_stat_vlc"/>
+</RelativeLayout>
\ No newline at end of file
diff --git a/vlc-android/res/layout/mrl_panel.xml b/vlc-android/res/layout/mrl_panel.xml
new file mode 100644
index 0000000..462885c
--- /dev/null
+++ b/vlc-android/res/layout/mrl_panel.xml
@@ -0,0 +1,20 @@
+<?xml version="1.0" encoding="utf-8"?>
+<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
+    xmlns:tools="http://schemas.android.com/tools"
+    android:layout_width="match_parent" android:layout_height="match_parent">
+    <EditText
+        android:id="@+id/mrl_edit"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_alignParentTop="true"
+        android:layout_margin="10dp"
+        android:hint="@string/open_mrl_dialog_msg"
+        android:inputType="textUri"
+        android:imeOptions="actionGo"/>
+    <android.support.v7.widget.RecyclerView
+        android:id="@+id/mrl_list"
+        android:layout_width="match_parent"
+        android:layout_height="wrap_content"
+        android:layout_below="@+id/mrl_edit"/>
+
+</RelativeLayout>
\ No newline at end of file
diff --git a/vlc-android/res/menu-v10/media_library.xml b/vlc-android/res/menu-v10/media_library.xml
deleted file mode 100644
index 76055da..0000000
--- a/vlc-android/res/menu-v10/media_library.xml
+++ /dev/null
@@ -1,48 +0,0 @@
-<?xml version="1.0" encoding="utf-8"?>
-<menu xmlns:android="http://schemas.android.com/apk/res/android"
-    xmlns:vlc="http://schemas.android.com/apk/res-auto" >
-
-    <item
-        android:id="@+id/ml_menu_search"
-        android:icon="@drawable/ic_menu_search_wb"
-        android:title="@string/searchable_hint"
-        android:nextFocusDown="@id/ml_menu_search"
-        vlc:showAsAction="ifRoom" />
-    <item
-        android:title="@string/sortby"
-        android:icon="@drawable/ic_menu_sortby_wb"
-        android:id="@+id/ml_menu_sortby">
-        <menu>
-            <item
-                android:id="@+id/ml_menu_sortby_name"
-                android:title="@string/sortby_name" />
-            <item
-                android:id="@+id/ml_menu_sortby_length"
-                android:title="@string/sortby_length" />
-        </menu>
-    </item>
-    <item
-        android:id="@+id/ml_menu_last_playlist"
-        android:icon="@drawable/ic_menu_revert_wb"
-        android:title="@string/last_playlist"
-        android:nextFocusDown="@id/ml_menu_last_playlist"
-        vlc:showAsAction="ifRoom" />
-    <item
-        android:id="@+id/ml_menu_refresh"
-        android:icon="@drawable/ic_menu_refresh_wb"
-        android:title="@string/refresh"
-        android:nextFocusDown="@id/ml_menu_refresh"/>
-    <item
-        android:id="@+id/ml_menu_equalizer"
-        android:icon="@drawable/ic_menu_equalizer_wb"
-        android:title="@string/equalizer" />
-    <item
-        android:id="@+id/ml_menu_about"
-        android:icon="@drawable/ic_menu_info_wb"
-        android:title="@string/about" />
-    <item
-        android:title="@string/clear_history"
-        android:visible="false"
-        android:icon="@android:drawable/ic_menu_close_clear_cancel"
-        android:id="@+id/search_clear_history" />
-</menu>
diff --git a/vlc-android/res/menu-v13/media_library.xml b/vlc-android/res/menu-v13/media_library.xml
index 6ff873c..0a2aa40 100644
--- a/vlc-android/res/menu-v13/media_library.xml
+++ b/vlc-android/res/menu-v13/media_library.xml
@@ -3,6 +3,14 @@
     xmlns:vlc="http://schemas.android.com/apk/res-auto" >
 
     <item
+        android:id="@+id/ml_menu_clean"
+        android:icon="@drawable/ic_stat_vlc"
+        android:title="@string/clear_history"
+        android:nextFocusDown="@id/ml_menu_search"
+        android:visible="false"
+        vlc:showAsAction="ifRoom" />
+
+    <item
         android:id="@+id/ml_menu_search"
         android:icon="@drawable/ic_menu_search"
         android:title="@string/searchable_hint"
diff --git a/vlc-android/res/menu-v7/media_library.xml b/vlc-android/res/menu-v7/media_library.xml
index ffe8c68..ebf2a49 100644
--- a/vlc-android/res/menu-v7/media_library.xml
+++ b/vlc-android/res/menu-v7/media_library.xml
@@ -3,6 +3,14 @@
     xmlns:vlc="http://schemas.android.com/apk/res-auto" >
 
     <item
+        android:id="@+id/ml_menu_clean"
+        android:icon="@drawable/ic_stat_vlc"
+        android:title="@string/clear_history"
+        android:nextFocusDown="@id/ml_menu_search"
+        android:visible="false"
+        vlc:showAsAction="ifRoom" />
+
+    <item
         android:id="@+id/ml_menu_search"
         android:icon="@drawable/ic_menu_search_wb"
         android:title="@string/searchable_hint"
diff --git a/vlc-android/src/org/videolan/vlc/MediaDatabase.java b/vlc-android/src/org/videolan/vlc/MediaDatabase.java
index ee5ad1f..41a4694 100644
--- a/vlc-android/src/org/videolan/vlc/MediaDatabase.java
+++ b/vlc-android/src/org/videolan/vlc/MediaDatabase.java
@@ -51,7 +51,7 @@ public class MediaDatabase {
 
     private SQLiteDatabase mDb;
     private final String DB_NAME = "vlc_database";
-    private final int DB_VERSION = 10;
+    private final int DB_VERSION = 11;
     private final int CHUNK_SIZE = 50;
 
     private final String DIR_TABLE_NAME = "directories_table";
@@ -88,6 +88,11 @@ public class MediaDatabase {
     private final String SEARCHHISTORY_DATE = "date";
     private final String SEARCHHISTORY_KEY = "key";
 
+    private final String MRL_TABLE_NAME = "mrl_table";
+    private final String MRL_DATE = "date";
+    private final String MRL_URI = "uri";
+    private final String MRL_TABLE_SIZE = "100";
+
     public enum mediaColumn {
         MEDIA_TABLE_NAME, MEDIA_PATH, MEDIA_TIME, MEDIA_LENGTH,
         MEDIA_TYPE, MEDIA_PICTURE, MEDIA_TITLE, MEDIA_ARTIST, MEDIA_GENRE, MEDIA_ALBUM,
@@ -195,6 +200,25 @@ public class MediaDatabase {
             db.execSQL(createPlaylistMediaTableQuery);
         }
 
+        private void createMRLTableQuery(SQLiteDatabase db) {
+            String createMrlTableQuery = "CREATE TABLE IF NOT EXISTS " +
+                    MRL_TABLE_NAME + " (" +
+                    MRL_URI + " TEXT PRIMARY KEY NOT NULL,"+
+                    MRL_DATE + " DATETIME NOT NULL"
+                    +");";
+            createMrlTableQuery += "CREATE TRIGGER mrl_history_trigger AFTER INSERT ON "+
+                    MRL_TABLE_NAME+ "BEGIN "+
+                    "DELETE FROM "+MRL_TABLE_NAME+" where "+MRL_URI+" NOT IN (SELECT "+MRL_URI+
+                    " from "+MRL_TABLE_NAME+" ORDER BY insertion_date DESC LIMIT "+MRL_TABLE_SIZE+")"+
+                    "END";
+            db.execSQL(createMrlTableQuery);
+        }
+
+        public void dropMRLTableQuery(SQLiteDatabase db) {
+            String query = "DROP TABLE " + MRL_TABLE_NAME + ";";
+            db.execSQL(query);
+        }
+
         @Override
         public void onCreate(SQLiteDatabase db) {
 
@@ -220,6 +244,8 @@ public class MediaDatabase {
 
             // Create the searchhistory table
             db.execSQL(createSearchhistoryTabelQuery);
+
+            createMRLTableQuery(db);
         }
 
         @Override
@@ -237,6 +263,9 @@ public class MediaDatabase {
                     db.execSQL("DROP TABLE " + PLAYLIST_TABLE_NAME + ";");
                     createPlaylistTablesQuery(db);
                     break;
+                case 11:
+                    createMRLTableQuery(db);
+                    break;
                 default:
                     break;
                 }
@@ -865,6 +894,44 @@ public class MediaDatabase {
         mDb.delete(SEARCHHISTORY_TABLE_NAME, null, null);
     }
 
+    public synchronized void addMrlhistoryItem(String uri) {
+        // set the format to sql date time
+        SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss", Locale.US);
+        Date date = new Date();
+        ContentValues values = new ContentValues();
+        values.put(MRL_URI, uri);
+        values.put(MRL_DATE, dateFormat.format(date));
+
+        mDb.replace(MRL_TABLE_NAME, null, values);
+    }
+
+    public synchronized ArrayList<String> getMrlhistory() {
+        ArrayList<String> history = new ArrayList<String>();
+
+        Cursor cursor = mDb.query(MRL_TABLE_NAME,
+                new String[] { MRL_URI },
+                null, null, null, null,
+                MRL_DATE + " DESC",
+                MRL_TABLE_SIZE);
+
+        while (cursor.moveToNext()) {
+            history.add(cursor.getString(0));
+        }
+        cursor.close();
+
+        return history;
+    }
+
+    public synchronized void deleteMrlUri(String uri) {
+        ArrayList<String> history = new ArrayList<String>();
+        mDb.delete(MRL_TABLE_NAME, MRL_URI + "=?", new String[] { uri });
+
+    }
+
+    public synchronized void clearMrlHistory() {
+        mDb.delete(MRL_TABLE_NAME, null, null);
+    }
+
     /**
      * Empty the database for debugging purposes
      */
diff --git a/vlc-android/src/org/videolan/vlc/gui/DividerItemDecoration.java b/vlc-android/src/org/videolan/vlc/gui/DividerItemDecoration.java
new file mode 100644
index 0000000..bcb8bca
--- /dev/null
+++ b/vlc-android/src/org/videolan/vlc/gui/DividerItemDecoration.java
@@ -0,0 +1,105 @@
+/*
+ * Copyright (C) 2014 The Android Open Source Project
+ *
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */
+
+package org.videolan.vlc.gui;
+
+import android.content.Context;
+import android.content.res.TypedArray;
+import android.graphics.Canvas;
+import android.graphics.Rect;
+import android.graphics.drawable.Drawable;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.view.View;
+
+public class DividerItemDecoration extends RecyclerView.ItemDecoration {
+
+    private static final int[] ATTRS = new int[]{
+            android.R.attr.listDivider
+    };
+
+    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
+
+    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
+
+    private Drawable mDivider;
+
+    private int mOrientation;
+
+    public DividerItemDecoration(Context context, int orientation) {
+        final TypedArray a = context.obtainStyledAttributes(ATTRS);
+        mDivider = a.getDrawable(0);
+        a.recycle();
+        setOrientation(orientation);
+    }
+
+    public void setOrientation(int orientation) {
+        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
+            throw new IllegalArgumentException("invalid orientation");
+        }
+        mOrientation = orientation;
+    }
+
+    @Override
+    public void onDraw(Canvas c, RecyclerView parent) {
+        if (mOrientation == VERTICAL_LIST) {
+            drawVertical(c, parent);
+        } else {
+            drawHorizontal(c, parent);
+        }
+    }
+
+    public void drawVertical(Canvas c, RecyclerView parent) {
+        final int left = parent.getPaddingLeft();
+        final int right = parent.getWidth() - parent.getPaddingRight();
+
+        final int childCount = parent.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = parent.getChildAt(i);
+            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+                    .getLayoutParams();
+            final int top = child.getBottom() + params.bottomMargin;
+            final int bottom = top + mDivider.getIntrinsicHeight();
+            mDivider.setBounds(left, top, right, bottom);
+            mDivider.draw(c);
+        }
+    }
+
+    public void drawHorizontal(Canvas c, RecyclerView parent) {
+        final int top = parent.getPaddingTop();
+        final int bottom = parent.getHeight() - parent.getPaddingBottom();
+
+        final int childCount = parent.getChildCount();
+        for (int i = 0; i < childCount; i++) {
+            final View child = parent.getChildAt(i);
+            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
+                    .getLayoutParams();
+            final int left = child.getRight() + params.rightMargin;
+            final int right = left + mDivider.getIntrinsicHeight();
+            mDivider.setBounds(left, top, right, bottom);
+            mDivider.draw(c);
+        }
+    }
+
+    @Override
+    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
+        if (mOrientation == VERTICAL_LIST) {
+            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
+        } else {
+            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
+        }
+    }
+}
diff --git a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
index 14ea5e1..15ab9e9 100644
--- a/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
+++ b/vlc-android/src/org/videolan/vlc/gui/MainActivity.java
@@ -30,7 +30,6 @@ import org.videolan.vlc.MediaDatabase;
 import org.videolan.vlc.MediaLibrary;
 import org.videolan.vlc.R;
 import org.videolan.vlc.VLCApplication;
-import org.videolan.vlc.VLCCallbackTask;
 import org.videolan.vlc.audio.AudioService;
 import org.videolan.vlc.audio.AudioServiceController;
 import org.videolan.vlc.gui.SidebarAdapter.SidebarEntry;
@@ -50,10 +49,8 @@ import org.videolan.vlc.util.WeakHandler;
 import org.videolan.vlc.widget.SlidingPaneLayout;
 
 import android.annotation.TargetApi;
-import android.app.AlertDialog;
 import android.content.BroadcastReceiver;
 import android.content.Context;
-import android.content.DialogInterface;
 import android.content.Intent;
 import android.content.IntentFilter;
 import android.content.SharedPreferences;
@@ -76,7 +73,6 @@ import android.support.v4.widget.DrawerLayout;
 import android.support.v7.app.ActionBar;
 import android.support.v7.app.ActionBarActivity;
 import android.support.v7.app.ActionBarDrawerToggle;
-import android.text.InputType;
 import android.util.Log;
 import android.view.KeyEvent;
 import android.view.LayoutInflater;
@@ -88,7 +84,6 @@ import android.view.Window;
 import android.view.WindowManager;
 import android.widget.AdapterView;
 import android.widget.AdapterView.OnItemClickListener;
-import android.widget.EditText;
 import android.widget.ListView;
 import android.widget.ProgressBar;
 import android.widget.TextView;
@@ -276,7 +271,8 @@ public class MainActivity extends ActionBarActivity {
 
                 /* Switch the fragment */
                     Fragment fragment = getFragment(entry.id);
-                    ((IBrowser)fragment).setReadyToDisplay(false);
+                    if (fragment instanceof IBrowser)
+                        ((IBrowser)fragment).setReadyToDisplay(false);
                     FragmentTransaction ft = getSupportFragmentManager().beginTransaction();
                     ft.replace(R.id.fragment_placeholder, fragment, entry.id);
                     ft.commit();
@@ -296,8 +292,6 @@ public class MainActivity extends ActionBarActivity {
                     if (mFocusedPrior != 0)
                         findViewById(R.id.ml_menu_search).requestFocus();
                     mRootContainer.closeDrawer(mListView);
-                } else if (entry.attributeID == R.attr.ic_menu_openmrl){
-                    onOpenMRL();
                 }else if (entry.attributeID == R.attr.ic_menu_preferences){
                     startActivityForResult(new Intent(mContext, PreferencesActivity.class), ACTIVITY_RESULT_PREFERENCES);
                 }
@@ -613,6 +607,7 @@ public class MainActivity extends ActionBarActivity {
         if (mCurrentFragment != null && mCurrentFragment.equals("search"))
             menu.findItem(R.id.search_clear_history).setVisible(true);
 
+        menu.findItem(R.id.ml_menu_clean).setVisible(SidebarEntry.ID_MRL.equals(mCurrentFragment));
         menu.findItem(R.id.ml_menu_last_playlist).setVisible(SidebarEntry.ID_AUDIO.equals(mCurrentFragment));
 
         return super.onPrepareOptionsMenu(menu);
@@ -689,6 +684,10 @@ public class MainActivity extends ActionBarActivity {
                     return true;
                 }
                 break;
+            case R.id.ml_menu_clean:
+                if (getFragment(mCurrentFragment) instanceof MrlPanelFragment)
+                    ((MrlPanelFragment)getFragment(mCurrentFragment)).clearHistory();
+                break;
             case R.id.search_clear_history:
                 MediaDatabase.getInstance().clearSearchHistory();
                 break;
@@ -898,46 +897,6 @@ public class MainActivity extends ActionBarActivity {
         sendTextInfo(null, 0, 100);
     }
 
-    private void onOpenMRL() {
-        AlertDialog.Builder b = new AlertDialog.Builder(this);
-        final EditText input = new EditText(this);
-        input.setInputType(InputType.TYPE_CLASS_TEXT | InputType.TYPE_TEXT_VARIATION_URI);
-        b.setTitle(R.string.open_mrl_dialog_title);
-        b.setMessage(R.string.open_mrl_dialog_msg);
-        b.setView(input);
-        b.setPositiveButton(R.string.open, new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(DialogInterface dialog, int button) {
-
-                /* Start this in a new thread as to not block the UI thread */
-                VLCCallbackTask task = new VLCCallbackTask(MainActivity.this)
-                {
-                    @Override
-                    public void run() {
-                      AudioServiceController c = AudioServiceController.getInstance();
-                      String s = input.getText().toString();
-
-                      /* Use the audio player by default. If a video track is
-                       * detected, then it will automatically switch to the video
-                       * player. This allows us to support more types of streams
-                       * (for example, RTSP and TS streaming) where ES can be
-                       * dynamically adapted rather than a simple scan.
-                       */
-                      c.load(s, false);
-                    }
-                };
-                task.execute();
-            }
-        }
-        );
-        b.setNegativeButton(R.string.cancel, new DialogInterface.OnClickListener() {
-            @Override
-            public void onClick(DialogInterface arg0, int arg1) {
-                return;
-                }});
-        b.show();
-    }
-
     /**
      * Show the audio player.
      */
diff --git a/vlc-android/src/org/videolan/vlc/gui/MrlAdapter.java b/vlc-android/src/org/videolan/vlc/gui/MrlAdapter.java
new file mode 100644
index 0000000..398f79a
--- /dev/null
+++ b/vlc-android/src/org/videolan/vlc/gui/MrlAdapter.java
@@ -0,0 +1,70 @@
+package org.videolan.vlc.gui;
+
+import android.support.v7.widget.RecyclerView;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.widget.ImageButton;
+import android.widget.TextView;
+
+import org.videolan.vlc.MediaDatabase;
+import org.videolan.vlc.R;
+import org.videolan.vlc.util.Util;
+
+import java.util.ArrayList;
+
+public class MrlAdapter extends RecyclerView.Adapter<MrlAdapter.ViewHolder> {
+    private ArrayList<String> mDataset;
+    public static class ViewHolder extends RecyclerView.ViewHolder {
+        public TextView uriTv;
+        public ImageButton deleteButton;
+
+        public ViewHolder(View v) {
+            super(v);
+            uriTv = (TextView) v.findViewById(R.id.mrl_item_uri);
+            deleteButton = (ImageButton) v.findViewById(R.id.mrl_item_delete);
+        }
+    }
+
+    public MrlAdapter(ArrayList<String> myDataset) {
+        mDataset = myDataset;
+    }
+
+    @Override
+    public MrlAdapter.ViewHolder onCreateViewHolder(ViewGroup parent,
+                                                    int viewType) {
+        View v = LayoutInflater.from(parent.getContext())
+                .inflate(R.layout.mrl_item, parent, false);
+        ViewHolder vh = new ViewHolder(v);
+        return vh;
+    }
+
+    @Override
+    public void onBindViewHolder(ViewHolder holder, final int position) {
+        final String uri = mDataset.get(position);
+        holder.uriTv.setText(uri);
+        holder.uriTv.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                Util.openStream(v.getContext(), uri);
+            }
+        });
+        holder.deleteButton.setOnClickListener(new View.OnClickListener() {
+            @Override
+            public void onClick(View v) {
+                MediaDatabase.getInstance().deleteMrlUri(uri);
+                mDataset.remove(position);
+                notifyDataSetChanged(); //because position is not updated
+            }
+        });
+    }
+
+    public void setList(ArrayList<String> list){
+        mDataset = list;
+        notifyDataSetChanged();
+    }
+    @Override
+    public int getItemCount() {
+        return mDataset.size();
+    }
+}
diff --git a/vlc-android/src/org/videolan/vlc/gui/MrlPanelFragment.java b/vlc-android/src/org/videolan/vlc/gui/MrlPanelFragment.java
new file mode 100644
index 0000000..2f89723
--- /dev/null
+++ b/vlc-android/src/org/videolan/vlc/gui/MrlPanelFragment.java
@@ -0,0 +1,91 @@
+package org.videolan.vlc.gui;
+
+import android.os.Bundle;
+import android.support.v4.app.Fragment;
+import android.support.v7.app.ActionBarActivity;
+import android.support.v7.widget.LinearLayoutManager;
+import android.support.v7.widget.RecyclerView;
+import android.text.TextUtils;
+import android.view.KeyEvent;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+import android.view.inputmethod.EditorInfo;
+import android.widget.EditText;
+import android.widget.TextView;
+
+import org.videolan.vlc.MediaDatabase;
+import org.videolan.vlc.R;
+import org.videolan.vlc.util.Util;
+
+import java.util.ArrayList;
+
+public class MrlPanelFragment extends Fragment implements View.OnKeyListener, TextView.OnEditorActionListener {
+    private static final String TAG = "VLC/MrlPanelFragment";
+    private RecyclerView mRecyclerView;
+    private MrlAdapter mAdapter;
+    private RecyclerView.LayoutManager mLayoutManager;
+    ArrayList<String> mHistory;
+    EditText mEditText;
+
+    public MrlPanelFragment(){};
+
+    public void onCreate(Bundle savedInstanceState) {
+        super.onCreate(savedInstanceState);
+        mHistory = MediaDatabase.getInstance().getMrlhistory();
+    }
+
+    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState){
+        ((ActionBarActivity) getActivity()).getSupportActionBar().setTitle(R.string.open_mrl_dialog_title);
+        View v = inflater.inflate(R.layout.mrl_panel, container, false);
+        mEditText = (EditText) v.findViewById(R.id.mrl_edit);
+        mEditText.setOnKeyListener(this);
+        mEditText.setOnEditorActionListener(this);
+        mRecyclerView = (RecyclerView) v.findViewById(R.id.mrl_list);
+        mLayoutManager = new LinearLayoutManager(getActivity());
+        mRecyclerView.setLayoutManager(mLayoutManager);
+        mRecyclerView.addItemDecoration(new DividerItemDecoration(getActivity(), DividerItemDecoration.VERTICAL_LIST));
+        mAdapter = new MrlAdapter(mHistory);
+        mRecyclerView.setAdapter(mAdapter);
+
+        return v;
+    }
+
+    private void updateHistory() {
+        mHistory = MediaDatabase.getInstance().getMrlhistory();
+        mAdapter.setList(mHistory);
+    }
+
+    @Override
+    public boolean onKey(View v, int keyCode, KeyEvent event) {
+        if (keyCode == EditorInfo.IME_ACTION_DONE ||
+            keyCode == EditorInfo.IME_ACTION_GO ||
+            event.getAction() == KeyEvent.ACTION_DOWN &&
+            event.getKeyCode() == KeyEvent.KEYCODE_ENTER) {
+            return processUri();
+        }
+        return false;
+    }
+
+    private boolean processUri() {
+        if (!TextUtils.isEmpty(mEditText.getText().toString())){
+            Util.openStream(getActivity(), mEditText.getText().toString().trim());
+            MediaDatabase.getInstance().addMrlhistoryItem(mEditText.getText().toString().trim());
+            updateHistory();
+            mEditText.getText().clear();
+            return true;
+        }
+        return false;
+    }
+
+    public void clearHistory(){
+        MediaDatabase.getInstance().clearMrlHistory();
+        updateHistory();
+    }
+
+    @Override
+    public boolean onEditorAction(TextView v, int actionId, KeyEvent event) {
+
+        return false;
+    }
+}
diff --git a/vlc-android/src/org/videolan/vlc/gui/SidebarAdapter.java b/vlc-android/src/org/videolan/vlc/gui/SidebarAdapter.java
index 51fd369..deeec0d 100644
--- a/vlc-android/src/org/videolan/vlc/gui/SidebarAdapter.java
+++ b/vlc-android/src/org/videolan/vlc/gui/SidebarAdapter.java
@@ -81,11 +81,11 @@ public class SidebarAdapter extends BaseAdapter {
         entries.add(new SidebarEntry(SidebarEntry.ID_AUDIO, R.string.audio, R.attr.ic_menu_audio, SidebarEntry.TYPE_FRAGMENT));
         entries.add(new SidebarEntry(SidebarEntry.ID_DIRECTORIES, R.string.directories, R.attr.ic_menu_folder, SidebarEntry.TYPE_FRAGMENT));
         entries.add(new SidebarEntry(SidebarEntry.ID_HISTORY, R.string.history, R.attr.ic_menu_history, SidebarEntry.TYPE_FRAGMENT));
+        entries.add(new SidebarEntry(SidebarEntry.ID_MRL, R.string.open_mrl, R.attr.ic_menu_openmrl, SidebarEntry.TYPE_FRAGMENT));
         sidebarFragments = new ArrayList<String>();
         for(SidebarEntry e : entries) {
             sidebarFragments.add(e.id);
         }
-        entries.add(new SidebarEntry(SidebarEntry.ID_MRL, R.string.open_mrl, R.attr.ic_menu_openmrl, SidebarEntry.TYPE_ACTION));
         entries.add(new SidebarEntry(SidebarEntry.ID_PREFERENCES, R.string.preferences, R.attr.ic_menu_preferences, SidebarEntry.TYPE_ACTION));
     }
 
@@ -148,14 +148,16 @@ public class SidebarAdapter extends BaseAdapter {
         }
 
         Fragment f;
-        if(id.equals("audio")) {
+        if(id.equals(SidebarEntry.ID_AUDIO)) {
             f = new AudioBrowserFragment();
-        } else if(id.equals("video")) {
+        } else if(id.equals(SidebarEntry.ID_VIDEO)) {
             f = new VideoGridFragment();
-        } else if(id.endsWith("directories")) {
+        } else if(id.endsWith(SidebarEntry.ID_DIRECTORIES)) {
             f = new DirectoryViewFragment();
-        } else if(id.equals("history")) {
+        } else if(id.equals(SidebarEntry.ID_HISTORY)) {
             f = new HistoryFragment();
+        } else if(id.equals(SidebarEntry.ID_MRL)) {
+            f = new MrlPanelFragment();
         }
         else {
             mCurrentFragmentId = prevFragmentId; // Restore the current fragment id.
diff --git a/vlc-android/src/org/videolan/vlc/util/Util.java b/vlc-android/src/org/videolan/vlc/util/Util.java
index 0b5665f..48deee0 100644
--- a/vlc-android/src/org/videolan/vlc/util/Util.java
+++ b/vlc-android/src/org/videolan/vlc/util/Util.java
@@ -30,6 +30,8 @@ import org.videolan.libvlc.LibVLC;
 import org.videolan.libvlc.Media;
 import org.videolan.vlc.MediaLibrary;
 import org.videolan.vlc.VLCApplication;
+import org.videolan.vlc.VLCCallbackTask;
+import org.videolan.vlc.audio.AudioServiceController;
 
 import android.content.Context;
 import android.content.Intent;
@@ -163,4 +165,23 @@ public class Util {
         intent.setAction(ACTION_SCAN_STOP);
         VLCApplication.getAppContext().sendBroadcast(intent);
     }
+
+
+    public static void openStream(Context context, final String uri){
+        VLCCallbackTask task = new VLCCallbackTask(context){
+            @Override
+            public void run() {
+                AudioServiceController c = AudioServiceController.getInstance();
+
+                      /* Use the audio player by default. If a video track is
+                       * detected, then it will automatically switch to the video
+                       * player. This allows us to support more types of streams
+                       * (for example, RTSP and TS streaming) where ES can be
+                       * dynamically adapted rather than a simple scan.
+                       */
+                c.load(uri, false);
+            }
+        };
+        task.execute();
+    }
 }
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java
deleted file mode 100644
index a9c9520..0000000
--- a/vlc-android/tv/src/org/videolan/vlc/gui/tv/audioplayer/DividerItemDecoration.java
+++ /dev/null
@@ -1,105 +0,0 @@
-/*
- * Copyright (C) 2014 The Android Open Source Project
- *
- * Licensed under the Apache License, Version 2.0 (the "License");
- * you may not use this file except in compliance with the License.
- * You may obtain a copy of the License at
- *
- *      http://www.apache.org/licenses/LICENSE-2.0
- *
- * Unless required by applicable law or agreed to in writing, software
- * distributed under the License is distributed on an "AS IS" BASIS,
- * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
- * See the License for the specific language governing permissions and
- * limitations under the License.
- */
-
-package org.videolan.vlc.gui.tv.audioplayer;
-
-import android.content.Context;
-import android.content.res.TypedArray;
-import android.graphics.Canvas;
-import android.graphics.Rect;
-import android.graphics.drawable.Drawable;
-import android.support.v7.widget.LinearLayoutManager;
-import android.support.v7.widget.RecyclerView;
-import android.view.View;
-
-public class DividerItemDecoration extends RecyclerView.ItemDecoration {
-
-    private static final int[] ATTRS = new int[]{
-            android.R.attr.listDivider
-    };
-
-    public static final int HORIZONTAL_LIST = LinearLayoutManager.HORIZONTAL;
-
-    public static final int VERTICAL_LIST = LinearLayoutManager.VERTICAL;
-
-    private Drawable mDivider;
-
-    private int mOrientation;
-
-    public DividerItemDecoration(Context context, int orientation) {
-        final TypedArray a = context.obtainStyledAttributes(ATTRS);
-        mDivider = a.getDrawable(0);
-        a.recycle();
-        setOrientation(orientation);
-    }
-
-    public void setOrientation(int orientation) {
-        if (orientation != HORIZONTAL_LIST && orientation != VERTICAL_LIST) {
-            throw new IllegalArgumentException("invalid orientation");
-        }
-        mOrientation = orientation;
-    }
-
-    @Override
-    public void onDraw(Canvas c, RecyclerView parent) {
-        if (mOrientation == VERTICAL_LIST) {
-            drawVertical(c, parent);
-        } else {
-            drawHorizontal(c, parent);
-        }
-    }
-
-    public void drawVertical(Canvas c, RecyclerView parent) {
-        final int left = parent.getPaddingLeft();
-        final int right = parent.getWidth() - parent.getPaddingRight();
-
-        final int childCount = parent.getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = parent.getChildAt(i);
-            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
-                    .getLayoutParams();
-            final int top = child.getBottom() + params.bottomMargin;
-            final int bottom = top + mDivider.getIntrinsicHeight();
-            mDivider.setBounds(left, top, right, bottom);
-            mDivider.draw(c);
-        }
-    }
-
-    public void drawHorizontal(Canvas c, RecyclerView parent) {
-        final int top = parent.getPaddingTop();
-        final int bottom = parent.getHeight() - parent.getPaddingBottom();
-
-        final int childCount = parent.getChildCount();
-        for (int i = 0; i < childCount; i++) {
-            final View child = parent.getChildAt(i);
-            final RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child
-                    .getLayoutParams();
-            final int left = child.getRight() + params.rightMargin;
-            final int right = left + mDivider.getIntrinsicHeight();
-            mDivider.setBounds(left, top, right, bottom);
-            mDivider.draw(c);
-        }
-    }
-
-    @Override
-    public void getItemOffsets(Rect outRect, int itemPosition, RecyclerView parent) {
-        if (mOrientation == VERTICAL_LIST) {
-            outRect.set(0, 0, 0, mDivider.getIntrinsicHeight());
-        } else {
-            outRect.set(0, 0, mDivider.getIntrinsicWidth(), 0);
-        }
-    }
-}
-- 
1.9.1



More information about the Android mailing list