[Android] [PATCH 2/2] Thread Media listing and thumbnails handling
Geoffrey Métais
geoffrey.metais at gmail.com
Fri Dec 5 11:23:48 CET 2014
---
.../src/org/videolan/vlc/gui/tv/GridFragment.java | 356 ++++++++++++---------
.../org/videolan/vlc/gui/tv/MainTvActivity.java | 93 ++++--
2 files changed, 274 insertions(+), 175 deletions(-)
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/GridFragment.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/GridFragment.java
index 17b02ad..6501c37 100644
--- a/vlc-android/tv/src/org/videolan/vlc/gui/tv/GridFragment.java
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/GridFragment.java
@@ -32,6 +32,7 @@ import org.videolan.vlc.MediaDatabase;
import org.videolan.vlc.MediaLibrary;
import org.videolan.vlc.R;
import org.videolan.vlc.Thumbnailer;
+import org.videolan.vlc.gui.MainActivity;
import org.videolan.vlc.gui.audio.AudioUtil;
import org.videolan.vlc.gui.audio.MediaComparators;
import org.videolan.vlc.gui.tv.audioplayer.AudioPlayerActivity;
@@ -42,17 +43,17 @@ import org.videolan.vlc.util.Util;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
+import android.os.AsyncTask;
import android.os.Bundle;
import android.os.Handler;
import android.support.v17.leanback.app.VerticalGridFragment;
import android.support.v17.leanback.widget.ArrayObjectAdapter;
-import android.support.v17.leanback.widget.OnItemClickedListener;
import android.support.v17.leanback.widget.OnItemViewClickedListener;
-import android.support.v17.leanback.widget.OnItemViewSelectedListener;
import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.Row;
import android.support.v17.leanback.widget.RowPresenter;
import android.support.v17.leanback.widget.VerticalGridPresenter;
+import android.util.Log;
public class GridFragment extends VerticalGridFragment implements VideoBrowserInterface {
private static final String TAG = "VLC/GridFragment";
@@ -63,9 +64,10 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
protected Media mItemToUpdate;
private Map<String, ListItem> mMediaItemMap;
private ArrayList<ListItem> mMediaItemList;
+ ArrayList<Media> mMediaList = null;
private ArrayObjectAdapter mAdapter;
private MediaLibrary mMediaLibrary;
- private Thumbnailer mThumbnailer;
+ private static Thumbnailer sThumbnailer;
HashMap<String, Integer> mMediaIndex;
Context mContext;
String mCategory, mFilter;
@@ -87,8 +89,9 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
mMediaLibrary = MediaLibrary.getInstance();
+ mAdapter = new ArrayObjectAdapter(new CardPresenter());
+ setAdapter(mAdapter);
if (mType == HEADER_VIDEO) {
- mThumbnailer = new Thumbnailer(mContext, getActivity().getWindowManager().getDefaultDisplay());
setupFragment();
} else if (mType == HEADER_MUSIC) {
setupFragment();
@@ -103,18 +106,21 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
Util.actionScanStart();
}
- /* Start the thumbnailer */
- if (mThumbnailer != null)
- mThumbnailer.start(this);
+ /* register to thumbnailer */
+ sThumbnailer = MainTvActivity.getThumbnailer();
+ if (sThumbnailer != null)
+ sThumbnailer.setVideoBrowser(this);
}
public void onPause() {
super.onPause();
mMediaLibrary.removeUpdateHandler(mHandler);
- /* Stop the thumbnailer */
- if (mThumbnailer != null)
- mThumbnailer.stop();
+ /* unregister from thumbnailer */
+ sThumbnailer = MainTvActivity.getThumbnailer();
+ if (sThumbnailer != null)
+ sThumbnailer.setVideoBrowser(null);
+ mBarrier.reset();
}
public void onSaveInstanceState(Bundle outState){
@@ -123,148 +129,13 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
outState.putString(AUDIO_CATEGORY, mCategory);
}
- @Override
- public void onDestroy() {
- super.onDestroy();
- if (mThumbnailer != null)
- mThumbnailer.clearJobs();
- mBarrier.reset();
- }
-
private void setupFragmentForAudio() {
- Bitmap picture;
- String title;
- mMediaItemMap = new HashMap<String, ListItem>();
- mMediaItemList = new ArrayList<GridFragment.ListItem>();
- VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
- mAdapter = new ArrayObjectAdapter(new CardPresenter());
- gridPresenter.setNumberOfColumns(NUM_COLUMNS);
- setGridPresenter(gridPresenter);
-
- List<Media> audioList = MediaLibrary.getInstance().getAudioItems();
- if (getString(R.string.artists).equals(mCategory)){
- Collections.sort(audioList, MediaComparators.byArtist);
- title = getString(R.string.artists);
- for (Media media : audioList){
- add(media.getArtist(), null, media);
- }
- } else if (getString(R.string.albums).equals(mCategory)){
- title = getString(R.string.albums);
- Collections.sort(audioList, MediaComparators.byAlbum);
- for (Media media : audioList){
- if (mFilter == null
- || (mType == FILTER_ARTIST && mFilter.equals(media.getArtist().trim()))
- || (mType == FILTER_GENRE && mFilter.equals(media.getGenre().trim()))) {
- add(media.getAlbum(), media.getArtist(), media);
- }
- }
- //Customize title for artist/genre browsing
- if (mType == FILTER_ARTIST){
- title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getArtist();
- } else if (mType == FILTER_GENRE){
- title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getGenre();
- }
- } else if (getString(R.string.genres).equals(mCategory)){
- title = getString(R.string.genres);
- Collections.sort(audioList, MediaComparators.byGenre);
- for (Media media : audioList){
- add(media.getGenre(), null, media);
- }
- } else if (getString(R.string.songs).equals(mCategory)){
- title = getString(R.string.songs);
- Collections.sort(audioList, MediaComparators.byName);
- for (Media media : audioList){
- add(media.getTitle(), media.getArtist(), media);
- }
- } else {
- title = getString(R.string.app_name_full);
- }
- setTitle(title);
- //check for pictures
- for (Media media : audioList){
- picture = AudioUtil.getCover(mContext, media, 320);
- if (picture != null){
- MediaDatabase.setPicture(media, picture);
- picture = null;
- }
- }
- mAdapter.addAll(0, mMediaItemList);
- setAdapter(mAdapter);
-
- setOnItemViewClickedListener(new OnItemViewClickedListener() {
- @Override
- public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
- RowPresenter.ViewHolder rowViewHolder, Row row) {
- ListItem listItem = (ListItem) item;
- Intent intent;
- if (getString(R.string.artists).equals(mCategory)){
- intent = new Intent(mContext, VerticalGridActivity.class);
- intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
- intent.putExtra(MEDIA_SECTION, FILTER_ARTIST);
- intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getArtist().trim());
- } else if (getString(R.string.genres).equals(mCategory)){
- intent = new Intent(mContext, VerticalGridActivity.class);
- intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
- intent.putExtra(MEDIA_SECTION, FILTER_GENRE);
- intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getGenre().trim());
- } else {
- ArrayList<String> locations = new ArrayList<String>();
- for (Media media : listItem.mMediaList){
- locations.add(media.getLocation());
- }
- intent = new Intent(mContext, AudioPlayerActivity.class);
- intent.putExtra("locations", locations);
- }
- startActivity(intent);
- }
- });
+ new AsyncAudioUpdate().execute();
}
//TODO shrink audio part, I keep it for now just in case...
private void setupFragment() {
- setTitle(getString(R.string.app_name_full));
- int size;
- Media media;
- Bitmap picture;
-
- MediaDatabase mediaDatabase = MediaDatabase.getInstance();
- VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
- mAdapter = new ArrayObjectAdapter(new CardPresenter());
-
- gridPresenter.setNumberOfColumns(NUM_COLUMNS);
- setGridPresenter(gridPresenter);
-
-
- ArrayList<Media> mediaList = null;
- if (mType == HEADER_VIDEO)
- mediaList = mMediaLibrary.getVideoItems();
- else
- mediaList = mMediaLibrary.getAudioItems();
- size = mediaList == null ? 0 : mediaList.size();
- mMediaIndex = new HashMap<String, Integer>(size);
-
- for (int i = 0 ; i < size ; ++i){
- media = mediaList.get(i);
- mAdapter.add(media);
- mMediaIndex.put(media.getLocation(), i);
- if (mThumbnailer != null){
- picture = mediaDatabase.getPicture(mContext, media.getLocation());
- if (picture== null) {
- mThumbnailer.addJob(media);
- }
- }
- }
-
- setAdapter(mAdapter);
-
- setOnItemViewClickedListener(new OnItemViewClickedListener() {
- @Override
- public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
- RowPresenter.ViewHolder rowViewHolder, Row row) {
- Media media = (Media) item;
- TvUtil.openMedia(getActivity(), media, null);
- }
- });
+ new AsyncVideoUpdate().execute();
}
public void await() throws InterruptedException, BrokenBarrierException {
@@ -290,8 +161,29 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
@Override
public void updateList() {
- // TODO Auto-generated method stub
- };
+ }
+
+ @Override
+ public void showProgressBar() {
+ //TODO
+ }
+
+ @Override
+ public void hideProgressBar() {
+ //TODO
+ }
+
+ @Override
+ public void clearTextInfo() {
+ //TODO
+ }
+
+ @Override
+ public void sendTextInfo(String info, int progress, int max) {
+ Log.d(TAG, info);
+ }
+
+ ;
private Handler mHandler = new VideoListHandler(this);
@@ -312,8 +204,8 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
}
}
- public void add(String title, String subTitle, Media media) {
- if(title == null) return;
+ public ListItem add(String title, String subTitle, Media media) {
+ if(title == null) return null;
title = title.trim();
if(subTitle != null) subTitle = subTitle.trim();
if (mMediaItemMap.containsKey(title))
@@ -322,6 +214,168 @@ public class GridFragment extends VerticalGridFragment implements VideoBrowserIn
ListItem item = new ListItem(title, subTitle, media, false);
mMediaItemMap.put(title, item);
mMediaItemList.add(item);
+ return item;
+ }
+ return null;
+ }
+
+ public class AsyncVideoUpdate extends AsyncTask<Void, Media, Void> {
+
+ public AsyncVideoUpdate() {}
+
+ @Override
+ protected void onPreExecute(){
+ setTitle(getString(R.string.app_name_full));
+ mAdapter.clear();
+ }
+ @Override
+ protected Void doInBackground(Void... params) {
+ int size;
+ Media media;
+
+ VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
+
+ gridPresenter.setNumberOfColumns(NUM_COLUMNS);
+ setGridPresenter(gridPresenter);
+
+
+ if (mType == HEADER_VIDEO)
+ mMediaList = mMediaLibrary.getVideoItems();
+ else
+ mMediaList = mMediaLibrary.getAudioItems();
+ size = mMediaList == null ? 0 : mMediaList.size();
+ mMediaIndex = new HashMap<String, Integer>(size);
+
+ for (int i = 0 ; i < size ; ++i){
+ media = mMediaList.get(i);
+ mMediaIndex.put(media.getLocation(), i);
+ publishProgress(media);
+
+ }
+ return null;
+ }
+
+ protected void onProgressUpdate(Media... medias){
+ mAdapter.add(medias[0]);
+ }
+
+ @Override
+ protected void onPostExecute(Void result) {
+ setOnItemViewClickedListener(new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ TvUtil.openMedia(getActivity(), (Media) item, null);
+ }
+ });
+ }
+ }
+
+ public class AsyncAudioUpdate extends AsyncTask<Void, ListItem, String> {
+
+ public AsyncAudioUpdate() {}
+
+ @Override
+ protected void onPreExecute() {
+ setTitle(getString(R.string.app_name_full));
+ mAdapter.clear();
+ VerticalGridPresenter gridPresenter = new VerticalGridPresenter();
+ gridPresenter.setNumberOfColumns(NUM_COLUMNS);
+ setGridPresenter(gridPresenter);
+ mMediaItemMap = new HashMap<String, ListItem>();
+ mMediaItemList = new ArrayList<GridFragment.ListItem>();
+ }
+
+ @Override
+ protected String doInBackground(Void... params) {
+ String title;
+ ListItem item;
+
+ List<Media> audioList = MediaLibrary.getInstance().getAudioItems();
+ if (getString(R.string.artists).equals(mCategory)){
+ Collections.sort(audioList, MediaComparators.byArtist);
+ title = getString(R.string.artists);
+ for (Media media : audioList){
+ item = add(media.getArtist(), null, media);
+ if (item != null)
+ publishProgress(item);
+ }
+ } else if (getString(R.string.albums).equals(mCategory)){
+ title = getString(R.string.albums);
+ Collections.sort(audioList, MediaComparators.byAlbum);
+ for (Media media : audioList){
+ if (mFilter == null
+ || (mType == FILTER_ARTIST && mFilter.equals(media.getArtist().trim()))
+ || (mType == FILTER_GENRE && mFilter.equals(media.getGenre().trim()))) {
+ item = add(media.getAlbum(), media.getArtist(), media);
+ if (item != null)
+ publishProgress(item);
+ }
+ }
+ //Customize title for artist/genre browsing
+ if (mType == FILTER_ARTIST){
+ title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getArtist();
+ } else if (mType == FILTER_GENRE){
+ title = title + " " + mMediaItemList.get(0).mMediaList.get(0).getGenre();
+ }
+ } else if (getString(R.string.genres).equals(mCategory)){
+ title = getString(R.string.genres);
+ Collections.sort(audioList, MediaComparators.byGenre);
+ for (Media media : audioList){
+ item = add(media.getGenre(), null, media);
+ if (item != null)
+ publishProgress(item);
+ }
+ } else if (getString(R.string.songs).equals(mCategory)){
+ title = getString(R.string.songs);
+ Collections.sort(audioList, MediaComparators.byName);
+ ListItem mediaItem;
+ for (Media media : audioList){
+ mediaItem = new ListItem(media.getTitle(), media.getArtist(), media, false);
+ mMediaItemMap.put(title, mediaItem);
+ mMediaItemList.add(mediaItem);
+ publishProgress(mediaItem);
+ }
+ } else {
+ title = getString(R.string.app_name_full);
+ }
+ return title;
+ }
+
+ protected void onProgressUpdate(ListItem... items){
+ mAdapter.add(items[0]);
+ }
+
+ @Override
+ protected void onPostExecute(String title) {
+ setTitle(title);
+ setOnItemViewClickedListener(new OnItemViewClickedListener() {
+ @Override
+ public void onItemClicked(Presenter.ViewHolder itemViewHolder, Object item,
+ RowPresenter.ViewHolder rowViewHolder, Row row) {
+ ListItem listItem = (ListItem) item;
+ Intent intent;
+ if (getString(R.string.artists).equals(mCategory)) {
+ intent = new Intent(mContext, VerticalGridActivity.class);
+ intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
+ intent.putExtra(MEDIA_SECTION, FILTER_ARTIST);
+ intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getArtist().trim());
+ } else if (getString(R.string.genres).equals(mCategory)) {
+ intent = new Intent(mContext, VerticalGridActivity.class);
+ intent.putExtra(AUDIO_CATEGORY, getString(R.string.albums));
+ intent.putExtra(MEDIA_SECTION, FILTER_GENRE);
+ intent.putExtra(AUDIO_FILTER, listItem.mMediaList.get(0).getGenre().trim());
+ } else {
+ ArrayList<String> locations = new ArrayList<String>();
+ for (Media media : listItem.mMediaList) {
+ locations.add(media.getLocation());
+ }
+ intent = new Intent(mContext, AudioPlayerActivity.class);
+ intent.putExtra("locations", locations);
+ }
+ startActivity(intent);
+ }
+ });
}
}
}
\ No newline at end of file
diff --git a/vlc-android/tv/src/org/videolan/vlc/gui/tv/MainTvActivity.java b/vlc-android/tv/src/org/videolan/vlc/gui/tv/MainTvActivity.java
index b66a9a1..5925155 100644
--- a/vlc-android/tv/src/org/videolan/vlc/gui/tv/MainTvActivity.java
+++ b/vlc-android/tv/src/org/videolan/vlc/gui/tv/MainTvActivity.java
@@ -50,8 +50,11 @@ import android.support.v17.leanback.widget.ArrayObjectAdapter;
import android.support.v17.leanback.widget.HeaderItem;
import android.support.v17.leanback.widget.ListRow;
import android.support.v17.leanback.widget.ListRowPresenter;
-import android.support.v17.leanback.widget.OnItemClickedListener;
+import android.support.v17.leanback.widget.OnItemViewClickedListener;
+import android.support.v17.leanback.widget.Presenter;
import android.support.v17.leanback.widget.Row;
+import android.support.v17.leanback.widget.RowPresenter;
+import android.util.Log;
import android.view.View;
import android.view.View.OnClickListener;
@@ -64,7 +67,7 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
protected BrowseFragment mBrowseFragment;
protected final CyclicBarrier mBarrier = new CyclicBarrier(2);
private MediaLibrary mMediaLibrary;
- private Thumbnailer mThumbnailer;
+ private static Thumbnailer sThumbnailer;
private Media mItemToUpdate;
ArrayObjectAdapter mRowsAdapter;
ArrayObjectAdapter mVideoAdapter;
@@ -74,16 +77,16 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
Drawable mDefaultBackground;
Activity mContext;
- OnItemClickedListener mItemClickListener = new OnItemClickedListener() {
+ OnItemViewClickedListener mItemClickListener = new OnItemViewClickedListener() {
@Override
- public void onItemClicked(Object item, Row row) {
+ public void onItemClicked(Presenter.ViewHolder viewHolder, Object o, RowPresenter.ViewHolder viewHolder2, Row row) {
if (row.getId() == HEADER_CATEGORIES){
- String category = (String)item;
+ String category = (String)o;
Intent intent = new Intent(mContext, VerticalGridActivity.class);
intent.putExtra(AUDIO_CATEGORY, category);
startActivity(intent);
} else if (row.getId() == HEADER_VIDEO)
- TvUtil.openMedia(mContext, (Media)item, row);
+ TvUtil.openMedia(mContext, (Media)o, row);
else if (row.getId() == HEADER_MISC)
startActivity(new Intent(mContext, PreferencesActivity.class));
}
@@ -127,11 +130,10 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
mBrowseFragment.setSearchAffordanceColor(getResources().getColor(R.color.darkorange));
// add a listener for selected items
- mBrowseFragment.setOnItemClickedListener(mItemClickListener);
+ mBrowseFragment.setOnItemViewClickedListener(mItemClickListener);
mBrowseFragment.setOnSearchClickedListener(mSearchClickedListenernew);
mMediaLibrary.loadMediaItems(this, true);
- mThumbnailer = new Thumbnailer(this, getWindowManager().getDefaultDisplay());
BackgroundManager.getInstance(this).attach(getWindow());
}
@@ -141,10 +143,8 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
if (mMediaLibrary.isWorking()) {
Util.actionScanStart();
}
-
- /* Start the thumbnailer */
- if (mThumbnailer != null)
- mThumbnailer.start(this);
+ if (sThumbnailer != null)
+ sThumbnailer.setVideoBrowser(this);
}
public void onPause() {
@@ -152,16 +152,16 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
mMediaLibrary.removeUpdateHandler(mHandler);
/* Stop the thumbnailer */
- if (mThumbnailer != null)
- mThumbnailer.stop();
+ if (sThumbnailer != null)
+ sThumbnailer.setVideoBrowser(null);
+ mBarrier.reset();
}
@Override
public void onDestroy() {
super.onDestroy();
- if (mThumbnailer != null)
- mThumbnailer.clearJobs();
- mBarrier.reset();
+ if (sThumbnailer != null)
+ sThumbnailer.clearJobs();
}
protected void updateBackground(Drawable drawable) {
@@ -181,21 +181,47 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
}
public void updateList() {
+ checkThumbs();
new AsyncUpdate().execute();
}
@Override
+ public void showProgressBar() {
+ //TODO
+ }
+
+ @Override
+ public void hideProgressBar() {
+ //TODO
+ }
+
+ @Override
+ public void clearTextInfo() {
+ //TODO
+ }
+
+ @Override
+ public void sendTextInfo(String info, int progress, int max) {
+ Log.d(TAG, info);
+ }
+
+ @Override
public void setItemToUpdate(Media item) {
mItemToUpdate = item;
mHandler.sendEmptyMessage(VideoListHandler.UPDATE_ITEM);
}
public void updateItem() {
- mVideoAdapter.notifyArrayItemRangeChanged(mVideoIndex.get(mItemToUpdate.getLocation()), 1);
+ if (mVideoAdapter != null && mVideoIndex != null && mItemToUpdate != null) {
+ if (mVideoIndex.containsKey(mItemToUpdate.getLocation())) {
+ mVideoAdapter.notifyArrayItemRangeChanged(mVideoIndex.get(mItemToUpdate.getLocation()), 1);
+ }
+ }
try {
mBarrier.await();
} catch (InterruptedException e) {
} catch (BrokenBarrierException e) {}
+
}
private Handler mHandler = new VideoListHandler(this);
@@ -231,12 +257,6 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
mVideoAdapter.add(item);
mVideoIndex.put(item.getLocation(), i);
- if (mThumbnailer != null){
- if (picture== null) {
- mThumbnailer.addJob(item);
- }
-
- }
}
// Empty item to launch grid activity
mVideoAdapter.add(new Media(null, 0, 0, Media.TYPE_GROUP, null, "Browse more", null, null, null, 0, 0, null, 0, 0));
@@ -266,4 +286,29 @@ public class MainTvActivity extends Activity implements VideoBrowserInterface {
mBrowseFragment.setAdapter(mRowsAdapter);
}
}
+
+ private void checkThumbs() {
+ new Thread(new Runnable() {
+ @Override
+ public void run() {
+ sThumbnailer = new Thumbnailer(mContext, getWindowManager().getDefaultDisplay());
+ Bitmap picture;
+ ArrayList<Media> videoList = mMediaLibrary.getVideoItems();
+ MediaDatabase mediaDatabase = MediaDatabase.getInstance();
+ if (sThumbnailer != null && videoList != null && !videoList.isEmpty()) {
+ for (Media media : videoList){
+ picture = mediaDatabase.getPicture(mContext, media.getLocation());
+ if (picture== null)
+ sThumbnailer.addJob(media);
+ }
+ if (sThumbnailer.getJobsCount() > 0)
+ sThumbnailer.start((VideoBrowserInterface) mContext);
+ }
+ }
+ }).start();
+ }
+
+ public static Thumbnailer getThumbnailer(){
+ return sThumbnailer;
+ }
}
--
1.9.1
More information about the Android
mailing list