Posted
almost 8 years
ago
DiffUtil is an AppCompat utility class developed to ease Recyclerview updates.
You just pass it the new dataset and current one and it automagically handles all the notifyItemRange* events to provide cool RecyclerView animations or subtle item
... [More]
updates (like a single progressbar update instead of the whole item layout rebinding).
DiffUtil steps
Principles
Basic usage
Finer items updates
DiffUtil process scheme
Moves detection
Going further
Principles
Provide your custom DiffUtil.Callback fed with the old and new datasets to the DiffUtil.calculateDiff method, and obtain a DiffUtil.DiffResult which contains all the necessary operations (additions, deletions and optionnally moves) to get from old list to the new one.
Update your dataset
Call diffResult.dispatchUpdatesTo(recyclerviewAdapter), your recyclerviewAdapter will receive all the corresponding notifyItemRange* events and benefit from shiny recyclerview animations!
It is strongly advised to run all dataset operations in the main thread, to ensure consistency. And for now (until next post), DiffUtil calculations will also be run in the main thread for consistency concern.
Basic usage
Here is a simple example of DiffUtil powered recyclerview update method in browsers adapter:
@MainThread
void update(final ArrayList<Item> newList) {
final DiffUtil.DiffResult result = DiffUtil.calculateDiff(
new MediaItemDiffCallback(mDataset, newList), false);
mDataset = newList;
result.dispatchUpdatesTo(MyAdapter.this);
}
You can see we only have these 3 basic steps.
With mDataset the current dataset, newList the new one, and false the parameter value for moves detection, we don’t handle it for now.
The base DiffUtil.Callback implementation we use:
public class MediaItemDiffCallback extends DiffUtil.Callback {
protected Item[] oldList, newList;
public MediaItemDiffCallback(Item[] oldList, Item[] newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList == null ? 0 : oldList.length;
}
@Override
public int getNewListSize() {
return newList == null ? 0 : newList.length;
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList[oldItemPosition].equals(newList[newItemPosition]);
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return true;
}
}
For now, areContentsTheSame always returns true, we’ll see later how to use it for smarter updates.
Let’s focus on areItemsTheSame: this is simply a equals-ish method to determine if two instances correspond to the same model view.
Now, with this diffResult, for every item insertion and deletion we get the precise adapter notification.
Typical application is list feeding, all new items are nicely inserted or removed which makes fancy animations to happen, like if we had set all the notifyItemInserted and notifyItemDeleted one by one.
A nicer use case is list/grid filtering. Here’s the result, with that simple update(newList) call:
Finer items updates
In video section, we want to update an item view if media progress or thumbnail has changed, but we don’t want to completely rebind its view.
Until VLC 2.0.6, you could experience a flicker of the video you were watching once getting back from video player.
That’s because media progress had changed and we blindly updated the whole view (which triggered thumbnail reloading).
Here is the DiffUtil.Callback specific to video grid which not only checks if items are the same, but if their content has changed also:
private class VideoItemDiffCallback extends DiffUtil.Callback {
List<Item> oldList, newList;
VideoItemDiffCallback(List<Item> oldList, List<Item> newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList == null ? 0 : oldList.size();
}
@Override
public int getNewListSize() {
return newList == null ? 0 : newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
Item oldItem = oldList.get(oldItemPosition);
Item newItem = newList.get(newItemPosition);
return oldItem.getTime() == newItem.getTime() &&
TextUtils.equals(oldItem.getArtworkMrl(), newItem.getArtworkMrl());
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
Item oldItem = oldList.get(oldItemPosition);
Item newItem = newList.get(newItemPosition);
if (oldItem.getTime() != newItem.getTime())
return UPDATE_TIME;
else
return UPDATE_THUMB;
}
}
If areItemsTheSame returns true, areContentsTheSame is called for the same items. areContentsTheSame returns false if we detect small changes we want to propagate to the UI without totally rebinding the concerned item view.
In our case this is two Item instances representing the same video file but artwork URL or time value has changed.
If areContentsTheSame returns false, getChangePayload is called for the same items. We define here the updated value and return it. The dispatch util will call notifyItemChanged(position, payload) with this value. Then it’s up to the adapter to manage the update:
In the adapter, we override onBindViewHolder(holder, position, payload) to achieve this:
@Override
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
} else {
MediaWrapper media = mVideos.get(position);
for (Object data : payloads) {
switch ((int) data) {
case UPDATE_THUMB:
AsyncImageLoader.loadPicture(holder.thumbView, media);
break;
case UPDATE_TIME:
fillView(holder, media);
break;
}
}
}
}
onBindViewHolder(holder, position, payloads) makes the smart move and updates the related view(s), instead of rebinding the whole item view. In our case, we load the thumb in the ImageView or we regenerate the progress string and update the progress bar with fillView().
As the dataSet is already updated, we don’t need to pass the values here, so I opted for constants refering to the different actions.
DiffUtil process scheme
Moves detection
The DiffUtil.calculateDiff algorithm can optionnally do a second pass to look for items movements between the old and new lists. If the sort order doesn’t change, it is useless to do it.
In VLC it’s only interesting in video grid for now, so we call:
DiffUtil.calculateDiff(new VideoItemDiffCallback(oldList, newList), detectMoves);
Where detectMoves variable is a boolean which is set to true only in case of video resorting call, in other cases we spare the second pass. Thanks to it, animations are fancier with only moving cards. Without this moves detection we’d get disappearing and reappearing cards.
Resorting videos with moves detection:
Without moves detection:
Going further
We now master diffutil, but we can do better and get calculation out of UI thread.
Rendez-vous to the second part of this post to check it out. [Less]
|
Posted
almost 8 years
ago
DiffUtil is an AppCompat utility class developed to calculate the delta between two different datasets of a recyclerview, and dispatch it to its adapter.
I.e. you pass it the current list and new one you want to display and it automagically handles
... [More]
all the notifyItemRange* events to provide cool RecyclerView animations or subtle item updates (like a single progressbar update instead of the whole item rebinding).
This is the perfect tool to easily manage recyclerview refresh and get dynamic animations or really discreet view updates for every dataset modification.
DiffUtil steps
Principles
Basic usage
Smarter items updates
Moves detection
Going further
Principles
Provide your custom DiffUtil.Callback fed with the old and new datasets to the DiffUtil.calculateDiff method, and obtain a DiffUtil.DiffResult which contains all the necessary operations (additions, deletions and optionnally moves) to get from old list to the new one.
Update your dataset
Call diffResult.dispatchUpdatesTo(recyclerviewAdapter), your recyclerviewAdapter will receive all the corresponding notifyItemRange* events and benefit from shiny recyclerview animations!
It is strongly advised to run all dataset operations in the main thread, to ensure consistency. And for now (until next post), DiffUtil calculations will also be run in the main thread for consistency concern.
Basic usage
Here is a simple example of DiffUtil powered recyclerview update method in browsers adapter:
@MainThread
void update(final ArrayList<Item> items) {
final DiffUtil.DiffResult result = DiffUtil.calculateDiff(
new MediaItemDiffCallback(mMediaList, items), false);
mMediaList = items;
result.dispatchUpdatesTo(MyAdapter.this);
}
You can see we only have these 3 basic steps.
With mMediaList the current dataset, items the new one, and false the parameter value for moves detection, we don’t handle it for now.
The base DiffUtil.Callback implementation we use:
public class MediaItemDiffCallback extends DiffUtil.Callback {
protected Item[] oldList, newList;
public MediaItemDiffCallback(Item[] oldList, Item[] newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList == null ? 0 :oldList.length;
}
@Override
public int getNewListSize() {
return newList == null ? 0 : newList.length;
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList[oldItemPosition].equals(newList[newItemPosition]);
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return true;
}
}
For now, areContentsTheSame always returns true, we’ll see later how to use it for smarter updates.
Let’s focus on areItemsTheSame: this is simply a equals-ish method to determine if two instances correspond to the same model view.
Now, with this diffResult, for every item insertion and deletion we get the precise adapter notification.
Typical application is list feeding, all new items are nicely inserted or removed which makes fancy animations to happen, like if we had set all the notifyItemInserted and notifyItemDeleted one by one.
A nicer use case is list/grid filtering. Here’s the result, with that simple update(newList) call:
Smarter items updates
In video section, we want to update an item view if media progress or thumbnail has changed, but we don’t want to completely rebind its view.
Until VLC 2.0.6, you could experience a flicker of the video you were watching once getting back from video player.
That’s because media progress had changed and we blindly updated the whole view (which triggered thumbnail reloading).
Here is the DiffUtil.Callback specific to video grid which not only checks if items are the same, but if their content has changed also:
private class VideoItemDiffCallback extends DiffUtil.Callback {
List<Item> oldList, newList;
VideoItemDiffCallback(List<Item> oldList, List<Item> newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList == null ? 0 : oldList.size();
}
@Override
public int getNewListSize() {
return newList == null ? 0 : newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
Item oldItem = oldList.get(oldItemPosition);
Item newItem = newList.get(newItemPosition);
return oldItem.getTime() == newItem.getTime() &&
TextUtils.equals(oldItem.getArtworkMrl(), newItem.getArtworkMrl());
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
Item oldItem = oldList.get(oldItemPosition);
Item newItem = newList.get(newItemPosition);
if (oldItem.getTime() != newItem.getTime())
return UPDATE_TIME;
else
return UPDATE_THUMB;
}
}
If areItemsTheSame returns true, areContentsTheSame is called for the same items. areContentsTheSame returns false if we detect small changes we want to propagate to the UI without totally rebinding the concerned item view.
In our case this is two Item instances representing the same video file but artwork URL or time value has changed.
If areContentsTheSame returns false, getChangePayload is called for the same items. We define here the updated value and return it. The dispatch util will call notifyItemChanged(position, payload) with this value. Then it’s up to the adapter to manage the update:
In the adapter, we override onBindViewHolder(holder, position, payload) to achieve this:
@Override
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
} else {
MediaWrapper media = mVideos.get(position);
for (Object data : payloads) {
switch ((int) data) {
case UPDATE_THUMB:
AsyncImageLoader.loadPicture(holder.thumbView, media);
break;
case UPDATE_TIME:
fillView(holder, media);
break;
}
}
}
}
onBindViewHolder(holder, position, payloads) makes the smart move and updates the related view(s), instead of rebinding the whole item view. In our case, we load the thumb in the ImageView or we regenerate the progress string and update the progress bar with fillView().
As the dataSet is already updated, we don’t need to pass the values here, so I opted for constants refering to the different actions.
Moves detection
The DiffUtil.calculateDiff algorithm can optionnally do a second pass to look for items movements between the old and new lists. If the sort order doesn’t change, it is useless to do it.
For us it’s only interesting in video grid for now, so we call:
DiffUtil.calculateDiff(new VideoItemDiffCallback(oldList, newList), detectMoves);
Where detectMoves variable is a boolean which is set to true only in case of video resorting call, in other cases we spare the second pass. Thanks to it, animations are fancier with only moving cards. Without this moves detection we’d get disappearing and reappearing cards.
Resorting videos with moves detection:
Without moves detection:
Going further
We now master diffutil, but we can do better and get calculation out of UI thread.
Rendez-vous to the second part of this post to check it out. [Less]
|
Posted
almost 8 years
ago
DiffUtil is an AppCompat utility class developed to calculate the delta between two different datasets of a recyclerview, and dispatch it to its adapter.
I.e. you pass it the current list and new one you want to display and it automagically handles
... [More]
all the notify[Item/ItemRange][Inserted/Deleted/Moved/Changed] to provide cool RecyclerView animations or subtles item updates (like a single progressbar update instead of the whole item rebinding).
DiffUtil steps
Principles
Basic usage
Smarter items updates
Moves detection
Going further
This is the perfect tool to easily manage recyclerview refresh and get dynamic animations or really discreet view updates for every dataset modification.
Principles
Provide your custom DiffUtil.Callback fed with the old and new datasets to the DiffUtil.calculateDiff method, and obtain a DiffUtil.DiffResult which contains all the necessary operations (additions, deletions and optionnally moves) to get from old list to the new one.
Update your dataset
Call diffResult.dispatchUpdatesTo(recyclerviewAdapter), your recyclerviewAdapter will receive all the corresponding notifyItem* events and profit shiny recyclerview animations!
It is strongly advised to run all dataset operations in the main thread, to ensure consistency. And for now (until next post), DiffUtil calculations will also be run in mainthread for consistency concern.
Basic usage
Here is a simple example of DiffUtil powered recyclerview update method in browsers adapter:
@MainThread
void update(final ArrayList<Item> items) {
final DiffUtil.DiffResult result = DiffUtil.calculateDiff(
new MediaItemDiffCallback(mMediaList, items), false);
mMediaList = items;
result.dispatchUpdatesTo(MyAdapter.this);
}
You can see we only have these 3 basic steps.
With mMediaList the current dataset, items the new one, and false the parameter value for moves detection, we don’t handle it for now.
The base DiffUtil.Callback implementation we use:
public class MediaItemDiffCallback extends DiffUtil.Callback {
protected Item[] oldList, newList;
public MediaItemDiffCallback(Item[] oldList, Item[] newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList == null ? 0 :oldList.length;
}
@Override
public int getNewListSize() {
return newList == null ? 0 : newList.length;
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList[oldItemPosition].equals(newList[newItemPosition]);
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
return true;
}
}
For now, areContentsTheSame always returns true, we’ll see later how to use it for smarter updates.
Let’s focus on areItemsTheSame: this is simply a equals-ish method to determine if two instances correspond to the same model view.
Now, with this diffResult, for every item insertion and deletion we get the precise adapter notification.
Typical application is list feeding, all new items are nicely inserted or removed which males fancy animations to happen, like if we had set all the notifyItemInserted and notifyItemDeleted one by one.
Nicer use case is list/grid filtering, check the result, with that simple update(newList) call:
Smarter items updates
In video section, we want to update an item view if media progress or thumbnail has changed, but we don’t want to completely rebind its view.
Until VLC 2.0.6, you could experience a flicker of the video you were watching once getting back from video player.
That’s because media progress had changed and we blindly updated the whole view (which triggered thumbnail reloading).
Here is the DiffUtil.Callback specific to video grid which not only checks if items are the same, but if their content has changed also:
private class VideoItemDiffCallback extends DiffUtil.Callback {
List<Item> oldList, newList;
VideoItemDiffCallback(List<Item> oldList, List<Item> newList) {
this.oldList = oldList;
this.newList = newList;
}
@Override
public int getOldListSize() {
return oldList == null ? 0 : oldList.size();
}
@Override
public int getNewListSize() {
return newList == null ? 0 : newList.size();
}
@Override
public boolean areItemsTheSame(int oldItemPosition, int newItemPosition) {
return oldList.get(oldItemPosition).equals(newList.get(newItemPosition));
}
@Override
public boolean areContentsTheSame(int oldItemPosition, int newItemPosition) {
Item oldItem = oldList.get(oldItemPosition);
Item newItem = newList.get(newItemPosition);
return oldItem.getTime() == newItem.getTime() &&
TextUtils.equals(oldItem.getArtworkMrl(), newItem.getArtworkMrl());
}
@Nullable
@Override
public Object getChangePayload(int oldItemPosition, int newItemPosition) {
Item oldItem = oldList.get(oldItemPosition);
Item newItem = newList.get(newItemPosition);
if (oldItem.getTime() != newItem.getTime())
return UPDATE_TIME;
else
return UPDATE_THUMB;
}
}
If areItemsTheSame returns true, areContentsTheSame is called for the same items. areContentsTheSame returns false if we detect small changes we want to propagate to the UI without totally rebinding the concerned item view.
In our case this is two Item instances representing the same video file but artwork URL or time value has changed.
If areContentsTheSame returns false, getChangePayload is called for the same items. We define here the updated value and return it. The dispatch util will call notifyItemChanged(position, payload) with this value. Then it’s up to the adapter to manage the update:
In the adapter, we override onBindViewHolder(holder, position, payload) to achieve this:
@Override
public void onBindViewHolder(ViewHolder holder, int position, List<Object> payloads) {
if (payloads.isEmpty()) {
onBindViewHolder(holder, position);
} else {
MediaWrapper media = mVideos.get(position);
for (Object data : payloads) {
switch ((int) data) {
case UPDATE_THUMB:
AsyncImageLoader.loadPicture(holder.thumbView, media);
break;
case UPDATE_TIME:
fillView(holder, media);
break;
}
}
}
}
onBindViewHolder(holder, position, payloads) makes the smart move and updates the related view(s), instead of rebinding the whole item view. In our case, we load the thumb in the ImageView or we regenerate the progress string and update the progress bar with fillView().
As the dataSet is already updated, we don’t need to pass the values here, so I opted for constants refering to the different actions.
Moves detection
The DiffUtil.calculateDiff algorithm can optionnally do a second pass to look for items movements between the old and new lists. If the sort order doesn’t change, it is useless to do it.
For us it’s only interesting in video grid for now, so we call:
DiffUtil.calculateDiff(new VideoItemDiffCallback(oldList, newList), detectMoves);
Where detectMoves variable is a boolean which is set to true only in case of video resorting call, in other cases we spare the second pass. Thanks to it, animations are fancier with only moving cards, without this moves detection we’d get disappearing and reappearing cards.
Resorting videos with moves detection:
Without moves detection:
Going further
We now master diffutil, but we can do better and get calculation out of UI thread.
Rendez-vous to the second part of this post to check it out. [Less]
|
Posted
almost 8 years
ago
Not so much activity on Play Store since v2.0.6 release.
I’ve been quite busy but VLC keeps going on with very interesting evolutions!
This post will only deal with features, not their implementation. I will later publish other posts, more
... [More]
interesting for developers, about it.
Incoming features
UX evolutions
Presentation
New Audio Player Style
Dynamic UI
Scrolling
Updating content
TV design
360° Videos support
Search
Android Auto
Action mode
Miscellaneous new features
Under the hood
MediaLibrary
Playback performance & formats support
Future
2.1.x version name will be used for beta only, we’ll decide later which version the stable release will be.
To get it you need to join the beta program, and you’ll receive it like a normal update.
For now, let me introduce you to the new VLC for Android.
UX evolutions
Presentation
Video cards have been refactored, we now show you video informations over its cover picture. This is a nicer presentation and gives room for displaying more videos at once.
Others lists view have been reworked too, like audio media, browsers and history. We got rid of cardview pattern, and got back to a more flat and clean design.
Audio lists have been a bit lifted too but this change is lighter.
Info page has also been redesigned with a fancy collapse effect for thumbnail or cover.
New Audio Player Style
Audio player background is now a blurred version of current art cover if available.
Dynamic UI
Scrolling
The action bar will now hide when your scroll your media lists, to save the more useful space possible while you’re looking for your media.
Album view has been revamped to become more #Material and now serves for playlists too
Updating content
Thanks to the DiffUtil tool from Appcompat library, grids/lists updates are now animated and more efficient.
One disturbing side effect is when you refresh and there’s no change in your media library. You won’t see any update, not even any flickering.
But the cool thing is whith actual content update, like during media scan or filtering the current view with the new search UX, insertions/deletions and position changes are animated:
TV design
TV interface had its own lifting too, nothing really impressive here.
Colors are less depressive and we make long media titles scroll, I heard your (justified) frustration :)
The interesting new feature on TV is the Picture-In-Picture (aka PIP) mode, available for all Android TVs powered by Android 7+.
It’s really like our popup mode in classic phone/tablet interface (so we used the very same icon in video advanced options for PIP).
You can still watch your video while using another application.
360° Videos support
VLC now supports 360° videos, you can change viewpoint by swiping or with remote control arrows.
Cardboard/VR mode is not available yet but we are working on it.
Search
Search has been splitted in two modes:
First step, the text you type in triggers a filtering in the current view. Exaclty like in current playlist view.
Then, if you want to do a global search, click on the SEARCH IN ALL MEDIALIBRARY button to show the new search activity. Which will bring detailed results grouped by video/artist/album/songs/genres/playlist
Bonus:
VLC will now be compatible with voice search.
Asking Google Now “Search game in VLC” will trigger a game search and show you this new search result screen.
Android Auto
This release will bring Android Auto compatibility.
You’ll be able to use VLC as your travel music player with easy browsing into you audio library, with the minimum possible distraction from driving.
Action mode
You can now select multiple items by long press on them (classic context menu is still available with the three dots icon) and enjoy actions like play it all or add selection to playlist
Actions available depend on media type and selection count.
This is very handy for starting or creating a playlist.
Miscellaneous new features
DayNight mode integration
Restored double/long click on remote play to skip songs
Removed sound lowering on notification
Force previous song on audioplayer swipe
Fix audioplayer layout for black theme and RTL
Save subtitles delay and optionally audio delay for each file.
Support for LG devices with 18:9 aspect ratio
Under the hood
MediaLibrary
That’s the most important change in this update, because it affects the whole application, but you should barely notice it…
VLC now uses medialibrary like VLC for Tizen, others VLC ports will follow.
It’s a C++ library, written by Hugo Beauzée-Luyssen, which parses storages for video/audio files and manages a sqlite database to model your media library (with album, artist, genre classification, etc..). It replaces the old system we had on Android which just saved media files with their metadata, we had no proper structure for media library.
So these categories listing are now faster, we don’t have to generate categories at runtime. And this is all native code, which is faster than Java.
Beside this speed improvement, one of the main benefits of this medialibrary is to provide better search results
For now we are focusing on the first scan performance to make it at least as fast as the previous system.
So, this library is aimed to be a common module of all VLC ports, wich means all debugging, performance and any improvement will benefit other platforms.
Next steps for this library will be media scrapping, and network scan:
Medialibrary will get informations and illustrations for your media, so we’ll be able to present you a nice collection, and not files list anymore. We will also group media by shows/seasons et genre/release year/whatever
You will be able to scan your NAS content to access your media easily.
Playback performance & formats support
VLC core team worked hard too to bring performance improvements and some new features. Here are some highlights:
360° videos support
Adaptive (HLS/Dash) & TS playback improved
OpenGLES 2.0 is now used to render video (for software decoders & mediacodec)
Support for VP8/9/10 in MP4
e-AC3 HDMI passthrough
Future
We also plan to implement a feature to download media on your device, in order to sync your series episodes or songs from your NAS to your device.
We’d like to support videos playlists like we do with videos grouped by their common name prefix.
As previously stated, medialibrary will allow to make VLC a real media center with fancy movies/tv shows presentation, and better artists/albums illustrations.
At last, I started an extension API in order for everyone to develop android applications which will provide content to VLC.
For example, we will release (with sources of course) extensions bringing support of podcasts subscriptions and Google Drive access. [Less]
|
Posted
almost 8 years
ago
Not so much activity on Play Store since v2.0.6 release.
I’ve been quite busy but VLC keeps going on with very interesting evolutions!
This post will only deal with features, not their implementation. I will later publish other posts, more
... [More]
interesting for developers, about it.
Incoming features
UX evolutions
Presentation
New Audio Player Style
Dynamic UI
Scrolling
Updating content
TV design
360° Videos support
Search
Android Auto
Action mode
Miscellaneous new features
Under the hood
MediaLibrary
Playback performance & formats support
Future
2.1.x version name will be used for beta only, we’ll decide later which version the stable release will be.
To get it you need to join the beta program, and you’ll receive it like a normal update.
For now, let me introduce you to the new VLC for Android.
UX evolutions
Presentation
Video cards have been refactored, we now show you video informations over its cover picture. This is a nicer presentation and gives room for displaying more videos at once.
Others lists view have been reworked too, like audio media, browsers and history. We got rid of cardview pattern, and got back to a more flat and clean design.
Audio lists have been a bit lifted too but this change is lighter.
Info page has also been redesigned with a fancy collapse effect for thumbnail or cover.
New Audio Player Style
Audio player background is now a blurred version of current art cover if available.
Dynamic UI
Scrolling
The action bar will now hide when your scroll your media lists, to save the more useful space possible while you’re looking for your media.
Album view has been revamped to become more #Material and now serves for playlists too
Updating content
Thanks to the DiffUtil tool from Appcompat library, grids/lists updates are now animated and more efficient.
One disturbing side effect is when you refresh and there’s no change in your media library. You won’t see any update, not even any flickering.
But the cool thing is whith actual content update, like during media scan or filtering the current view with the new search UX, insertions/deletions and position changes are animated:
TV design
TV interface had its own lifting too, nothing really impressive here.
Colors are less depressive and we make long media titles scroll, I heard your (justified) frustration :)
The interesting new feature on TV is the Picture-In-Picture (aka PIP) mode, available for all Android TVs powered by Android 7+.
It’s really like our popup mode in classic phone/tablet interface (so we used the very same icon in video advanced options for PIP).
You can still watch your video while using another application.
360° Videos support
VLC now supports 360° videos, you can change viewpoint by swiping or with remote control arrows.
Cardboard/VR mode is not available yet but we are working on it.
Search
Search has been splitted in two modes:
First step, the text you type in triggers a filtering in the current view. Exaclty like in current playlist view.
Then, if you want to do a global search, click on the SEARCH IN ALL MEDIALIBRARY button to show the new search activity. Which will bring detailed results grouped by video/artist/album/songs/genres/playlist
Bonus:
VLC will now be compatible with voice search.
Asking Google Now “Search game in VLC” will trigger a game search and show you this new search result screen.
Android Auto
This release will bring Android Auto compatibility.
You’ll be able to use VLC as your travel music player with easy browsing into you audio library, with the minimum possible distraction from driving.
VLC also supports voice actions on Android Auto:
You can ask “play Daft Punk” and Google Assistant will recognize whether it’s an artist, an album or a song you’re asking for and trigger VLC to play it.
Action mode
You can now select multiple items by long press on them (classic context menu is still available with the three dots icon) and enjoy actions like play it all or add selection to playlist
Actions available depend on media type and selection count.
This is very handy for starting or creating a playlist.
Miscellaneous new features
DayNight mode integration
Restored double/long click on remote play to skip songs
Removed sound lowering on notification
Force previous song on audioplayer swipe
Fix audioplayer layout for black theme and RTL
Save subtitles delay and optionally audio delay for each file.
Support for LG devices with 18:9 aspect ratio
Under the hood
MediaLibrary
That’s the most important change in this update, because it affects the whole application, but you should barely notice it…
VLC now uses medialibrary like VLC for Tizen, others VLC ports will follow.
It’s a C++ library, written by Hugo Beauzée-Luyssen, which parses storages for video/audio files and manages a sqlite database to model your media library (with album, artist, genre classification, etc..). It replaces the old system we had on Android which just saved media files with their metadata, we had no proper structure for media library.
So these categories listing are now faster, we don’t have to generate categories at runtime. And this is all native code, which is faster than Java.
Beside this speed improvement, one of the main benefits of this medialibrary is to provide better search results
For now we are focusing on the first scan performance to make it at least as fast as the previous system.
So, this library is aimed to be a common module of all VLC ports, wich means all debugging, performance and any improvement will benefit other platforms.
Next steps for this library will be media scrapping, and network scan:
Medialibrary will get informations and illustrations for your media, so we’ll be able to present you a nice collection, and not files list anymore. We will also group media by shows/seasons et genre/release year/whatever
You will be able to scan your NAS content to access your media easily.
Playback performance & formats support
VLC core team worked hard too to bring performance improvements and some new features. Here are some highlights:
360° videos support
Adaptive (HLS/Dash) & TS playback improved
OpenGLES 2.0 is now used to render video (for software decoders & mediacodec)
Support for VP8/9/10 in MP4
e-AC3 HDMI passthrough
Future
We also plan to implement a feature to download media on your device, in order to sync your series episodes or songs from your NAS to your device.
We’d like to support videos playlists like we do with videos grouped by their common name prefix.
As previously stated, medialibrary will allow to make VLC a real media center with fancy movies/tv shows presentation, and better artists/albums illustrations.
At last, I started an extension API in order for everyone to develop android applications which will provide content to VLC.
For example, we will release (with sources of course) extensions bringing support of podcasts subscriptions and Google Drive access. [Less]
|
Posted
almost 8 years
ago
Here are some hidden features of VLC on Android.
Tips
Play video on your Chromecast
STOP playback service
Repeat video
Reorder media in current playlist
Load last playlist
Next/previous by swipe
Video player bindings
... [More]
Play video on your Chromecast
VLC does not yet support Chromecast, but you already can use it!
Android can cast its screen content and audio to it.
Here are some ways to access this option:
With the quick toggle
In Display settings
In Google Home app menu
You can find Google Home here
VLC detects the secondary display (your Chromecast) like it does if you plug your device to your TV with a HDMI cable, and video player will show you this screen:
You have normal controls like swipe to seek and go to advanced options while you watch your movie on TV 📺 😃
STOP playback service
There are 2 ways to completely stop vlc player service (and not just pause playback), but this action has no explicit button.
With mini player: long press on play/pause button
With playback icon: only when playback is paused
on Android 5+: you can swipe the notification.
on Android 4.x: you should have a ‘x’ button on top-right corner.
Repeat video
With version 2.1 you’ll have the repeat button available in the video player advanced options, but you can already do that with version 2.0.x:
Long press on play/pause button to switch playback to repeat mode so your video playback will loop
Reorder media in current playlist
Simply drag media within current playlist to reorder it.
Load last playlist
In action bar, the circled play button triggers loading of last playlist from the current category: In video view it will load last video(s) played, in Audio view it will load last audio playlist.
With remote play/pause control (wired headset or bluetooth ad2p device) when VLC is not playing, you can load last audio playlist and continue playback where you stopped it.
Next/previous by swipe
Swipe miniplayer on left/right triggers skip to previous/next media.
Video player bindings
If you have a keyboard or a gamepad connected to your Android device, here are the key bindings in video player:
within DVD menu:
Key(s)
Action
↓↑←→
navigate
Gamepad A or X /play/pause/space/OK/enter
click on focused item
in 360° video playback (version 2.1.0+):
Key(s)
Action
↓↑←→
change viewpoint
normal case:
Key(s)
Action
F/fast_forward/→
seek (+10 seconds)
R/rewind/←
seek (-10 seconds)
R1
seek (+1 minute)
L1
seek (-1 minute)
A(gamepad)/play/pause/space/OK
toggle play/pause
O/Y(gamepad)/menu/↑
show advanced options
V/audio-track/X(gamepad)
open subtitles options
N
show DVD navigation menu
A
resize video
M/mute
toggle sound mute
S/STOP
stop playback & exit player
captions
select subtitles
J
delay audio (-50ms)
K
delay audio (+50ms)
G
delay subtitles (-50ms)
H
delay subtitles (+50ms)
[Less]
|
Posted
almost 8 years
ago
Here are some hidden features of VLC on Android.
Tips
STOP playback service
Repeat video
Reorder media in current playlist
Load last playlist
Next/previous by swipe
Video player bindings
STOP playback service
There are 2
... [More]
ways to completely stop vlc player service (and not just pause playback), but this action has no explicit button.
With mini player: long press on play/pause button
With playback icon: only when playback is paused
on Android 5+: you can swipe the notification.
on Android 4.x: you should have a ‘x’ button on top-right corner.
Repeat video
With version 2.1 you’ll have the repeat button available in the video player advanced options, but you can already do that with version 2.0.x:
Long press on play/pause button to switch playback to repeat mode so your video playback will loop
Reorder media in current playlist
Simply drag media within current playlist to reorder it.
Load last playlist
In action bar, the circled play button triggers loading of last playlist from the current category: In video view it will load last video(s) played, in Audio view it will load last audio playlist.
With remote play/pause control (wired headset or bluetooth ad2p device) when VLC is not playing, you can load last audio playlist and continue playback where you stopped it.
Next/previous by swipe
Swipe miniplayer on left/right triggers skip to previous/next media.
Video player bindings
If you have a keyboard or a gamepad connected to your Android device, here are the key bindings in video player:
within DVD menu:
Key(s)
Action
↓↑←→
navigate
Gamepad A or X /play/pause/space/OK/enter
click on focused item
in 360° video playback (version 2.1.0+):
Key(s)
Action
↓↑←→
change viewpoint
normal case:
Key(s)
Action
F/fast_forward/→
seek (+10 seconds)
R/rewind/←
seek (-10 seconds)
R1
seek (+1 minute)
L1
seek (-1 minute)
A(gamepad)/play/pause/space/OK
toggle play/pause
O/Y(gamepad)/menu/↑
show advanced options
V/audio-track/X(gamepad)
open subtitles options
N
show DVD navigation menu
A
resize video
M/mute
toggle sound mute
S/STOP
stop playback & exit player
captions
select subtitles
J
delay audio (-50ms)
K
delay audio (+50ms)
G
delay subtitles (-50ms)
H
delay subtitles (+50ms)
[Less]
|
Posted
about 8 years
ago
For some releases now, LAVA server is publishing events every time:
a Job status change (Submitted, Running, ...)
a Device status change (Idle, Reserved, ...)
The stream of events is public and anyone can subscribe and receive updates.
A dump of the streams for the production and
the staging instances is available …
|
Posted
about 8 years
ago
For more than 3 years now, I have been working on LAVA. Looking at the documentation:
LAVA is an automated validation architecture
primarily aimed at testing deployments of systems based around the Linux kernel
on ARM devices, specifically ARMv7 and later.
In order to test LAVA, you need:
a wide …
|
Posted
over 8 years
ago
Revisiting the condition variable with futex
and pondering thread synchronization primitives.
|