Option to redownload artist image

- redownload artist image
- better search
This commit is contained in:
Karim Abou Zeid 2015-02-28 17:49:27 +01:00
commit 59ca3a8c8f
12 changed files with 142 additions and 31 deletions

View file

@ -2,6 +2,7 @@ package com.kabouzeid.materialmusic.adapter;
import android.content.Context; import android.content.Context;
import android.graphics.Color; import android.graphics.Color;
import android.graphics.Typeface;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -38,16 +39,22 @@ public class SearchAdapter extends ArrayAdapter<SearchEntry> {
final ImageView imageView = (ImageView) convertView.findViewById(R.id.image); final ImageView imageView = (ImageView) convertView.findViewById(R.id.image);
if (item instanceof SearchActivity.LabelEntry) { if (item instanceof SearchActivity.LabelEntry) {
title.setTypeface(null, Typeface.BOLD);
subTitle.setVisibility(View.GONE); subTitle.setVisibility(View.GONE);
imageView.setVisibility(View.GONE);
convertView.setBackgroundColor(Util.resolveColor(getContext(), R.attr.colorPrimary)); convertView.setBackgroundColor(Util.resolveColor(getContext(), R.attr.colorPrimary));
} else { } else {
title.setTypeface(null, Typeface.NORMAL);
subTitle.setVisibility(View.VISIBLE); subTitle.setVisibility(View.VISIBLE);
imageView.setVisibility(View.VISIBLE);
convertView.setBackgroundColor(Color.TRANSPARENT); convertView.setBackgroundColor(Color.TRANSPARENT);
} }
title.setText(item.getTitle()); title.setText(item.getTitle());
subTitle.setText(item.getSubTitle()); subTitle.setText(item.getSubTitle());
item.loadImage(imageView);
imageView.setImageBitmap(null);
item.loadImage(getContext(), imageView);
return convertView; return convertView;
} }

View file

@ -24,10 +24,15 @@ import org.json.JSONObject;
public class LastFMArtistImageLoader { public class LastFMArtistImageLoader {
public static final String TAG = LastFMArtistImageLoader.class.getSimpleName(); public static final String TAG = LastFMArtistImageLoader.class.getSimpleName();
@Deprecated
public static void loadArtistImage(Context context, String queryArtist, ArtistImageLoaderCallback callback) { public static void loadArtistImage(Context context, String queryArtist, ArtistImageLoaderCallback callback) {
loadArtistImage(context, queryArtist, false, callback);
}
public static void loadArtistImage(Context context, String queryArtist, boolean forceDownload, ArtistImageLoaderCallback callback) {
if (queryArtist != null) { if (queryArtist != null) {
String artistJSON = ArtistJSONStore.getInstance(context).getArtistJSON(queryArtist); String artistJSON = ArtistJSONStore.getInstance(context).getArtistJSON(queryArtist);
if (artistJSON != null) { if (artistJSON != null && !forceDownload) {
Log.i(TAG, queryArtist + " is in cache."); Log.i(TAG, queryArtist + " is in cache.");
try { try {
loadArtistImageFromJSON(new JSONObject(artistJSON), callback); loadArtistImageFromJSON(new JSONObject(artistJSON), callback);
@ -35,7 +40,11 @@ public class LastFMArtistImageLoader {
Log.e(TAG, "Error while parsing string from cache to JSONObject", e); Log.e(TAG, "Error while parsing string from cache to JSONObject", e);
} }
} else { } else {
Log.i(TAG, queryArtist + " is not in cache."); if(forceDownload){
Log.i(TAG, queryArtist + " force re-download");
} else {
Log.i(TAG, queryArtist + " is not in cache.");
}
downloadArtistJSONAndStartImageDownload(context, queryArtist, callback); downloadArtistJSONAndStartImageDownload(context, queryArtist, callback);
} }
} }

View file

@ -90,6 +90,7 @@ public class LastFMArtistInfoUtil {
public static void saveArtistJSONDataToCacheAndDisk(Context context, String artist, JSONObject jsonObject) { public static void saveArtistJSONDataToCacheAndDisk(Context context, String artist, JSONObject jsonObject) {
Log.i(TAG, "Saving new JSON artist data for " + artist + "..."); Log.i(TAG, "Saving new JSON artist data for " + artist + "...");
ArtistJSONStore.getInstance(context).removeItem(artist);
ArtistJSONStore.getInstance(context).addArtistJSON(artist, jsonObject.toString()); ArtistJSONStore.getInstance(context).addArtistJSON(artist, jsonObject.toString());
} }
} }

View file

@ -24,10 +24,15 @@ import org.json.JSONObject;
public class LastFMArtistThumbnailLoader { public class LastFMArtistThumbnailLoader {
public static final String TAG = LastFMArtistThumbnailLoader.class.getSimpleName(); public static final String TAG = LastFMArtistThumbnailLoader.class.getSimpleName();
@Deprecated
public static void loadArtistThumbnail(Context context, String queryArtist, ArtistThumbnailLoaderCallback callback) { public static void loadArtistThumbnail(Context context, String queryArtist, ArtistThumbnailLoaderCallback callback) {
loadArtistThumbnail(context, queryArtist, false, callback);
}
public static void loadArtistThumbnail(Context context, String queryArtist, boolean forceDownload, ArtistThumbnailLoaderCallback callback) {
if (queryArtist != null) { if (queryArtist != null) {
String artistJSON = ArtistJSONStore.getInstance(context).getArtistJSON(queryArtist); String artistJSON = ArtistJSONStore.getInstance(context).getArtistJSON(queryArtist);
if (artistJSON != null) { if (artistJSON != null && !forceDownload) {
Log.i(TAG, queryArtist + " is in cache."); Log.i(TAG, queryArtist + " is in cache.");
try { try {
loadArtistThumbnailFromJSON(new JSONObject(artistJSON), callback); loadArtistThumbnailFromJSON(new JSONObject(artistJSON), callback);
@ -35,7 +40,11 @@ public class LastFMArtistThumbnailLoader {
Log.e(TAG, "Error while parsing string from cache to JSONObject", e); Log.e(TAG, "Error while parsing string from cache to JSONObject", e);
} }
} else { } else {
Log.i(TAG, queryArtist + " is not in cache."); if(forceDownload){
Log.i(TAG, queryArtist + " force re-download");
} else {
Log.i(TAG, queryArtist + " is not in cache.");
}
downloadArtistThumbnail(context, queryArtist, callback); downloadArtistThumbnail(context, queryArtist, callback);
} }
} }

View file

@ -1,7 +1,12 @@
package com.kabouzeid.materialmusic.model; package com.kabouzeid.materialmusic.model;
import android.content.Context;
import android.widget.ImageView; import android.widget.ImageView;
import com.kabouzeid.materialmusic.util.ImageLoaderUtil;
import com.kabouzeid.materialmusic.util.MusicUtil;
import com.nostra13.universalimageloader.core.ImageLoader;
/** /**
* Created by karim on 22.11.14. * Created by karim on 22.11.14.
*/ */
@ -43,7 +48,7 @@ public class Album implements SearchEntry {
} }
@Override @Override
public void loadImage(ImageView imageView) { public void loadImage(Context context, ImageView imageView) {
ImageLoader.getInstance().displayImage(MusicUtil.getAlbumArtUri(id).toString(), imageView, new ImageLoaderUtil.defaultAlbumArtOnFailed());
} }
} }

View file

@ -1,7 +1,12 @@
package com.kabouzeid.materialmusic.model; package com.kabouzeid.materialmusic.model;
import android.content.Context;
import android.graphics.Bitmap;
import android.widget.ImageView; import android.widget.ImageView;
import com.kabouzeid.materialmusic.R;
import com.kabouzeid.materialmusic.lastfm.artist.LastFMArtistThumbnailLoader;
/** /**
* Created by karim on 29.12.14. * Created by karim on 29.12.14.
*/ */
@ -36,7 +41,19 @@ public class Artist implements SearchEntry {
} }
@Override @Override
public void loadImage(ImageView imageView) { public void loadImage(Context context, final ImageView imageView) {
imageView.setTag(name);
LastFMArtistThumbnailLoader.loadArtistThumbnail(context, name, new LastFMArtistThumbnailLoader.ArtistThumbnailLoaderCallback() {
@Override
public void onArtistThumbnailLoaded(Bitmap thumbnail) {
if (imageView.getTag().equals(name)) {
if (thumbnail != null) {
imageView.setImageBitmap(thumbnail);
} else {
imageView.setImageResource(R.drawable.default_artist_image);
}
}
}
});
} }
} }

View file

@ -1,5 +1,6 @@
package com.kabouzeid.materialmusic.model; package com.kabouzeid.materialmusic.model;
import android.content.Context;
import android.widget.ImageView; import android.widget.ImageView;
/** /**
@ -10,5 +11,5 @@ public interface SearchEntry {
public String getSubTitle(); public String getSubTitle();
public void loadImage(ImageView imageView); public void loadImage(Context context, ImageView imageView);
} }

View file

@ -1,7 +1,12 @@
package com.kabouzeid.materialmusic.model; package com.kabouzeid.materialmusic.model;
import android.content.Context;
import android.widget.ImageView; import android.widget.ImageView;
import com.kabouzeid.materialmusic.util.ImageLoaderUtil;
import com.kabouzeid.materialmusic.util.MusicUtil;
import com.nostra13.universalimageloader.core.ImageLoader;
import java.io.Serializable; import java.io.Serializable;
/** /**
@ -51,7 +56,7 @@ public class Song implements Serializable, SearchEntry {
} }
@Override @Override
public void loadImage(ImageView imageView) { public void loadImage(Context context, ImageView imageView) {
ImageLoader.getInstance().displayImage(MusicUtil.getAlbumArtUri(albumId).toString(), imageView, new ImageLoaderUtil.defaultAlbumArtOnFailed());
} }
} }

View file

@ -20,6 +20,7 @@ import android.view.ViewGroup;
import android.view.animation.DecelerateInterpolator; import android.view.animation.DecelerateInterpolator;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.TextView; import android.widget.TextView;
import android.widget.Toast;
import com.github.ksoichiro.android.observablescrollview.ObservableScrollViewCallbacks; import com.github.ksoichiro.android.observablescrollview.ObservableScrollViewCallbacks;
import com.github.ksoichiro.android.observablescrollview.ScrollState; import com.github.ksoichiro.android.observablescrollview.ScrollState;
@ -103,7 +104,7 @@ public class ArtistDetailActivity extends AbsFabActivity implements OnMusicRemot
@Override @Override
public void onTransitionEnd(Transition transition) { public void onTransitionEnd(Transition transition) {
setUpArtistImageAndApplyPalette(); setUpArtistImageAndApplyPalette(false);
} }
@Override @Override
@ -160,7 +161,7 @@ public class ArtistDetailActivity extends AbsFabActivity implements OnMusicRemot
artistTitleText.setText(artist.name); artistTitleText.setText(artist.name);
ViewHelper.setAlpha(artistArtOverlayView, 0); ViewHelper.setAlpha(artistArtOverlayView, 0);
setUpArtistImageAndApplyPalette(); setUpArtistImageAndApplyPalette(false);
setUpViewPatch(); setUpViewPatch();
setUpSlidingTabs(); setUpSlidingTabs();
} }
@ -312,8 +313,8 @@ public class ArtistDetailActivity extends AbsFabActivity implements OnMusicRemot
} }
} }
private void setUpArtistImageAndApplyPalette() { private void setUpArtistImageAndApplyPalette(final boolean forceDownload) {
LastFMArtistImageLoader.loadArtistImage(this, artist.name, new LastFMArtistImageLoader.ArtistImageLoaderCallback() { LastFMArtistImageLoader.loadArtistImage(this, artist.name, forceDownload, new LastFMArtistImageLoader.ArtistImageLoaderCallback() {
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Override @Override
public void onArtistImageLoaded(Bitmap artistImage) { public void onArtistImageLoaded(Bitmap artistImage) {
@ -321,7 +322,9 @@ public class ArtistDetailActivity extends AbsFabActivity implements OnMusicRemot
artistImageView.setImageBitmap(artistImage); artistImageView.setImageBitmap(artistImage);
applyPalette(artistImage); applyPalette(artistImage);
} }
//if (Util.hasLollipopSDK()) startPostponedEnterTransition(); if(forceDownload){
Toast.makeText(ArtistDetailActivity.this, getResources().getString(R.string.updated_artist_image_for) + " " + artist.name, Toast.LENGTH_SHORT).show();
}
} }
}); });
} }
@ -383,6 +386,9 @@ public class ArtistDetailActivity extends AbsFabActivity implements OnMusicRemot
case android.R.id.home: case android.R.id.home:
super.onBackPressed(); super.onBackPressed();
return true; return true;
case R.id.action_re_download_artist_image:
Toast.makeText(ArtistDetailActivity.this, getResources().getString(R.string.updating), Toast.LENGTH_SHORT).show();
setUpArtistImageAndApplyPalette(true);
case R.id.action_settings: case R.id.action_settings:
return true; return true;
case R.id.action_current_playing: case R.id.action_current_playing:

View file

@ -2,6 +2,7 @@ package com.kabouzeid.materialmusic.ui.activities;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.ActionBar; import android.app.ActionBar;
import android.content.Context;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.util.Pair; import android.support.v4.util.Pair;
import android.support.v4.view.MenuItemCompat; import android.support.v4.view.MenuItemCompat;
@ -9,6 +10,7 @@ import android.support.v7.widget.SearchView;
import android.support.v7.widget.Toolbar; import android.support.v7.widget.Toolbar;
import android.view.Menu; import android.view.Menu;
import android.view.MenuItem; import android.view.MenuItem;
import android.view.MotionEvent;
import android.view.View; import android.view.View;
import android.widget.AdapterView; import android.widget.AdapterView;
import android.widget.ArrayAdapter; import android.widget.ArrayAdapter;
@ -34,6 +36,7 @@ public class SearchActivity extends AbsBaseActivity {
public static final String TAG = SearchActivity.class.getSimpleName(); public static final String TAG = SearchActivity.class.getSimpleName();
private ListView listView; private ListView listView;
private SearchView searchView;
@SuppressLint("NewApi") @SuppressLint("NewApi")
@Override @Override
@ -69,6 +72,17 @@ public class SearchActivity extends AbsBaseActivity {
} }
}); });
listView.setOnTouchListener(new View.OnTouchListener() {
@Override
public boolean onTouch(View v, MotionEvent event) {
Util.hideSoftKeyboard(SearchActivity.this);
if(searchView != null){
searchView.clearFocus();
}
return false;
}
});
setSupportActionBar((Toolbar) findViewById(R.id.toolbar)); setSupportActionBar((Toolbar) findViewById(R.id.toolbar));
getSupportActionBar().setDisplayHomeAsUpEnabled(true); getSupportActionBar().setDisplayHomeAsUpEnabled(true);
} }
@ -101,7 +115,7 @@ public class SearchActivity extends AbsBaseActivity {
getMenuInflater().inflate(R.menu.menu_search, menu); getMenuInflater().inflate(R.menu.menu_search, menu);
final MenuItem search = menu.findItem(R.id.action_search); final MenuItem search = menu.findItem(R.id.action_search);
SearchView searchView = (SearchView) MenuItemCompat.getActionView(search); searchView = (SearchView) MenuItemCompat.getActionView(search);
searchView.setIconified(false); searchView.setIconified(false);
searchView.setIconifiedByDefault(false); searchView.setIconifiedByDefault(false);
@ -111,7 +125,10 @@ public class SearchActivity extends AbsBaseActivity {
searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() { searchView.setOnQueryTextListener(new SearchView.OnQueryTextListener() {
@Override @Override
public boolean onQueryTextSubmit(String query) { public boolean onQueryTextSubmit(String query) {
return false; onQueryTextChange(query);
Util.hideSoftKeyboard(SearchActivity.this);
searchView.clearFocus();
return true;
} }
@Override @Override
@ -148,26 +165,51 @@ public class SearchActivity extends AbsBaseActivity {
} }
private void search(String query) { private void search(String query) {
List<SearchEntry> results = new ArrayList<>();
if (!query.trim().equals("")) { if (!query.trim().equals("")) {
List<SearchEntry> results = new ArrayList<>(); LabelEntry songLabel = new LabelEntry(getResources().getString(R.string.songs).toUpperCase());
results.add(new LabelEntry("Songs")); results.add(songLabel);
results.addAll(SongLoader.getSongs(this, query)); List<Song> songs = SongLoader.getSongs(this, query);
results.add(new LabelEntry("Artists")); results.addAll(songs);
results.addAll(ArtistLoader.getArtists(this, query)); songLabel.setNumber(songs.size());
results.add(new LabelEntry("Albums"));
results.addAll(AlbumLoader.getAlbums(this, query)); LabelEntry artistLabel = new LabelEntry(getResources().getString(R.string.artists).toUpperCase());
ArrayAdapter adapter = new SearchAdapter(this, results); results.add(artistLabel);
listView.setAdapter(adapter); List<Artist> artists = ArtistLoader.getArtists(this, query);
} else { results.addAll(artists);
listView.setAdapter(null); artistLabel.setNumber(artists.size());
LabelEntry albumLabel = new LabelEntry(getResources().getString(R.string.albums).toUpperCase());
results.add(albumLabel);
List<Album> albums = AlbumLoader.getAlbums(this, query);
results.addAll(albums);
albumLabel.setNumber(albums.size());
} }
if(results.size() <= 3){
results.clear();
results.add(new LabelEntry(getResources().getString(R.string.no_results).toUpperCase()));
}
ArrayAdapter adapter = new SearchAdapter(this, results);
listView.setAdapter(adapter);
} }
public static class LabelEntry implements SearchEntry { public static class LabelEntry implements SearchEntry {
String title;
String label; String label;
public LabelEntry(String label) { public LabelEntry(String label) {
this.label = label; this.label = label;
this.title = label;
}
public void setNumber(int number){
if(number != -1) {
label = title + " (" + number + ")";
} else {
label = title;
}
} }
@Override @Override
@ -181,7 +223,7 @@ public class SearchActivity extends AbsBaseActivity {
} }
@Override @Override
public void loadImage(ImageView imageView) { public void loadImage(Context context, ImageView imageView) {
} }
} }

View file

@ -9,6 +9,11 @@
android:title="@string/action_current_playing" android:title="@string/action_current_playing"
app:showAsAction="ifRoom"/> app:showAsAction="ifRoom"/>
<item
android:id="@+id/action_re_download_artist_image"
android:title="@string/action_re_download_artist_image"
app:showAsAction="never"/>
<item <item
android:id="@+id/action_settings" android:id="@+id/action_settings"
android:orderInCategory="100" android:orderInCategory="100"

View file

@ -68,5 +68,9 @@
<string name="credits">Material Music is a completely free material designed music player by <b>Karim Abou Zeid</b>.\n\n<a href="https://plus.google.com/+KarimAbouZeid23697">Google+</a>&#160;&#160;&#160;<a href="https://twitter.com/karim23697">Twitter</a></string> <string name="credits">Material Music is a completely free material designed music player by <b>Karim Abou Zeid</b>.\n\n<a href="https://plus.google.com/+KarimAbouZeid23697">Google+</a>&#160;&#160;&#160;<a href="https://twitter.com/karim23697">Twitter</a></string>
<string name="title_activity_search">SearchActivity</string> <string name="title_activity_search">SearchActivity</string>
<string name="more">more</string> <string name="more">more</string>
<string name="no_results">No results</string>
<string name="action_re_download_artist_image">Update artist image</string>
<string name="updated_artist_image_for">Updated artist image for</string>
<string name="updating">Updating…</string>
</resources> </resources>