Switched from Volley to RetroFit + OkHttp for performance and simplicity

This commit is contained in:
Karim Abou Zeid 2015-06-29 21:38:09 +02:00
commit cdba76c933
55 changed files with 1702 additions and 571 deletions

View file

@ -60,7 +60,8 @@ dependencies {
compile 'com.github.ksoichiro:android-observablescrollview:1.5.1' compile 'com.github.ksoichiro:android-observablescrollview:1.5.1'
compile 'asia.ivity.android:drag-sort-listview:1.0' compile 'asia.ivity.android:drag-sort-listview:1.0'
compile 'com.mcxiaoke.volley:library:1.0.16' compile 'com.squareup.retrofit:retrofit:1.9.0'
compile 'com.squareup.okhttp:okhttp:2.4.0'
compile 'com.squareup:otto:1.3.7' compile 'com.squareup:otto:1.3.7'
compile 'de.hdodenhof:circleimageview:1.3.0' compile 'de.hdodenhof:circleimageview:1.3.0'
compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4' compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4'

View file

@ -16,11 +16,13 @@
# public *; # public *;
#} #}
# RetroFit
-dontwarn retrofit.**
-keep class retrofit.** { *; }
-keepattributes Signature
-keepattributes Exceptions
-keep class !android.support.v7.internal.view.menu.**,** {*;} -keep class !android.support.v7.internal.view.menu.**,** {*;}
-keep public class * implements com.bumptech.glide.module.GlideModule
-keep public enum com.bumptech.glide.load.resource.bitmap.ImageHeaderParser$** {
**[] $VALUES;
public *;
}
-dontwarn -dontwarn
-ignorewarnings -ignorewarnings

View file

@ -2,9 +2,6 @@ package com.kabouzeid.gramophone;
import android.app.Application; import android.app.Application;
import com.android.volley.Request;
import com.android.volley.RequestQueue;
import com.android.volley.toolbox.Volley;
import com.crashlytics.android.Crashlytics; import com.crashlytics.android.Crashlytics;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoader;
@ -24,8 +21,6 @@ public class App extends Application {
public static final String TAG = App.class.getSimpleName(); public static final String TAG = App.class.getSimpleName();
public static final Bus bus = new Bus(ThreadEnforcer.MAIN); public static final Bus bus = new Bus(ThreadEnforcer.MAIN);
private RequestQueue requestQueue;
@Override @Override
public void onCreate() { public void onCreate() {
super.onCreate(); super.onCreate();
@ -39,16 +34,4 @@ public class App extends Application {
TagOptionSingleton.getInstance().isAndroid(); TagOptionSingleton.getInstance().isAndroid();
} }
public void addToVolleyRequestQueue(Request request) {
request.setTag(TAG);
getVolleyRequestQueue().add(request);
}
public RequestQueue getVolleyRequestQueue() {
if (requestQueue == null) {
requestQueue = Volley.newRequestQueue(this);
}
return requestQueue;
}
} }

View file

@ -17,7 +17,9 @@ import com.kabouzeid.gramophone.dialogs.AddToPlaylistDialog;
import com.kabouzeid.gramophone.dialogs.DeleteSongsDialog; import com.kabouzeid.gramophone.dialogs.DeleteSongsDialog;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.lastfm.artist.LastFMArtistThumbnailUrlLoader; import com.kabouzeid.gramophone.lastfm.rest.LastFMRestClient;
import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.ArtistInfo;
import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.Image;
import com.kabouzeid.gramophone.loader.ArtistLoader; import com.kabouzeid.gramophone.loader.ArtistLoader;
import com.kabouzeid.gramophone.loader.ArtistSongLoader; import com.kabouzeid.gramophone.loader.ArtistSongLoader;
import com.kabouzeid.gramophone.model.Artist; import com.kabouzeid.gramophone.model.Artist;
@ -33,16 +35,22 @@ import com.squareup.otto.Subscribe;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List; import java.util.List;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
/** /**
* @author Karim Abou Zeid (kabouzeid) * @author Karim Abou Zeid (kabouzeid)
*/ */
public class ArtistAdapter extends AbsMultiSelectAdapter<ArtistAdapter.ViewHolder, Artist> { public class ArtistAdapter extends AbsMultiSelectAdapter<ArtistAdapter.ViewHolder, Artist> {
protected final AppCompatActivity activity; protected final AppCompatActivity activity;
protected List<Artist> dataSet; protected List<Artist> dataSet;
protected final LastFMRestClient lastFMRestClient;
public ArtistAdapter(AppCompatActivity activity, @Nullable CabHolder cabHolder) { public ArtistAdapter(AppCompatActivity activity, @Nullable CabHolder cabHolder) {
super(activity, cabHolder, R.menu.menu_media_selection); super(activity, cabHolder, R.menu.menu_media_selection);
this.activity = activity; this.activity = activity;
lastFMRestClient = new LastFMRestClient(activity);
loadDataSet(); loadDataSet();
} }
@ -62,23 +70,42 @@ public class ArtistAdapter extends AbsMultiSelectAdapter<ArtistAdapter.ViewHolde
holder.artistName.setText(artist.name); holder.artistName.setText(artist.name);
holder.artistInfo.setText(MusicUtil.getArtistInfoString(activity, artist)); holder.artistInfo.setText(MusicUtil.getArtistInfoString(activity, artist));
holder.artistImage.setImageResource(R.drawable.default_artist_image);
holder.view.setActivated(isChecked(artist)); holder.view.setActivated(isChecked(artist));
LastFMArtistThumbnailUrlLoader.loadArtistThumbnailUrl(activity, artist.name, false, new LastFMArtistThumbnailUrlLoader.ArtistThumbnailUrlLoaderCallback() { lastFMRestClient.getApiService().getArtistInfo(artist.name, null, new Callback<ArtistInfo>() {
@Override @Override
public void onArtistThumbnailUrlLoaded(final String url) { public void success(ArtistInfo artistInfo, Response response) {
ImageLoader.getInstance().displayImage(url, if (artistInfo.getArtist() != null) {
holder.artistImage, int thumbnailIndex = 0;
new DisplayImageOptions.Builder() List<Image> images = artistInfo.getArtist().getImage();
.cacheInMemory(true) if (images.size() > 2) {
.cacheOnDisk(true) thumbnailIndex = 2;
.build() } else if (images.size() > 1) {
); thumbnailIndex = 1;
}
ImageLoader.getInstance().displayImage(images.get(thumbnailIndex).getText(),
holder.artistImage,
new DisplayImageOptions.Builder()
.cacheInMemory(true)
.cacheOnDisk(true)
.build()
);
} else {
setDefaultArtistImage(holder);
}
}
@Override
public void failure(RetrofitError error) {
setDefaultArtistImage(holder);
} }
}); });
} }
private void setDefaultArtistImage(ViewHolder holder) {
holder.artistImage.setImageResource(R.drawable.default_artist_image);
}
@Override @Override
public int getItemCount() { public int getItemCount() {
return dataSet.size(); return dataSet.size();

View file

@ -15,7 +15,8 @@ import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.helper.MenuItemClickHelper; import com.kabouzeid.gramophone.helper.MenuItemClickHelper;
import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.lastfm.artist.LastFMArtistThumbnailUrlLoader; import com.kabouzeid.gramophone.lastfm.rest.LastFMRestClient;
import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.ArtistInfo;
import com.kabouzeid.gramophone.loader.AlbumLoader; import com.kabouzeid.gramophone.loader.AlbumLoader;
import com.kabouzeid.gramophone.loader.ArtistLoader; import com.kabouzeid.gramophone.loader.ArtistLoader;
import com.kabouzeid.gramophone.loader.SongLoader; import com.kabouzeid.gramophone.loader.SongLoader;
@ -33,6 +34,10 @@ import java.util.ArrayList;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
/** /**
* @author Karim Abou Zeid (kabouzeid) * @author Karim Abou Zeid (kabouzeid)
*/ */
@ -45,6 +50,7 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
private AppCompatActivity activity; private AppCompatActivity activity;
private List results = Collections.emptyList(); private List results = Collections.emptyList();
private String query; private String query;
private LastFMRestClient lastFMRestClient;
public SearchAdapter(AppCompatActivity activity) { public SearchAdapter(AppCompatActivity activity) {
this.activity = activity; this.activity = activity;
@ -115,19 +121,31 @@ public class SearchAdapter extends RecyclerView.Adapter<SearchAdapter.ViewHolder
final Artist artist = (Artist) results.get(position); final Artist artist = (Artist) results.get(position);
holder.title.setText(artist.name); holder.title.setText(artist.name);
holder.subTitle.setText(MusicUtil.getArtistInfoString(activity, artist)); holder.subTitle.setText(MusicUtil.getArtistInfoString(activity, artist));
holder.image.setImageResource(R.drawable.default_artist_image); lastFMRestClient.getApiService().getArtistInfo(artist.name, null, new Callback<ArtistInfo>() {
LastFMArtistThumbnailUrlLoader.loadArtistThumbnailUrl(activity, artist.name, false, new LastFMArtistThumbnailUrlLoader.ArtistThumbnailUrlLoaderCallback() {
@Override @Override
public void onArtistThumbnailUrlLoaded(final String url) { public void success(ArtistInfo artistInfo, Response response) {
ImageLoader.getInstance().displayImage(url, if (artistInfo.getArtist() != null) {
holder.image, ImageLoader.getInstance().displayImage(artistInfo.getArtist().getImage().get(0).getText(),
new DisplayImageOptions.Builder() holder.image,
.cacheInMemory(true) new DisplayImageOptions.Builder()
.cacheOnDisk(true) .cacheInMemory(true)
.showImageOnFail(R.drawable.default_artist_image) .cacheOnDisk(true)
.resetViewBeforeLoading(true) .showImageOnFail(R.drawable.default_artist_image)
.build() .resetViewBeforeLoading(true)
); .build()
);
} else {
setDefaultArtistImage();
}
}
@Override
public void failure(RetrofitError error) {
setDefaultArtistImage();
}
private void setDefaultArtistImage() {
holder.image.setImageResource(R.drawable.default_artist_image);
} }
}); });
break; break;

View file

@ -1,9 +0,0 @@
package com.kabouzeid.gramophone.lastfm;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastFMUtil {
public static final String BASE_URL = "ws.audioscrobbler.com";
public static final String API_KEY = "bd9c6ea4d55ec9ed3af7d276e5ece304";
}

View file

@ -1,58 +0,0 @@
package com.kabouzeid.gramophone.lastfm.album;
import android.content.Context;
import android.util.Log;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.kabouzeid.gramophone.provider.AlbumJSONStore;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastFMAlbumImageUrlLoader {
public static final String TAG = LastFMAlbumImageUrlLoader.class.getSimpleName();
public static void loadAlbumImageUrl(Context context, String queryAlbum, String queryArtist, final AlbumImageUrlLoaderCallback callback) {
if (queryAlbum != null) {
String albumJSON = AlbumJSONStore.getInstance(context).getJSONData(queryAlbum + queryArtist);
if (albumJSON != null) {
try {
loadAlbumImageUrlFromJSON(new JSONObject(albumJSON), callback);
} catch (JSONException e) {
Log.e(TAG, "Error while parsing string from cache to JSONObject", e);
}
} else {
LastFMAlbumInfoUtil.downloadAlbumInfoJSON(context, queryAlbum, queryArtist, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
loadAlbumImageUrlFromJSON(response, callback);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
callback.onError();
}
});
}
}
}
private static void loadAlbumImageUrlFromJSON(final JSONObject jsonObject, final AlbumImageUrlLoaderCallback callback) {
String url = LastFMAlbumInfoUtil.getAlbumImageUrlFromJSON(jsonObject);
if (!url.trim().equals("")) {
callback.onAlbumImageUrlLoaded(url);
} else {
callback.onError();
}
}
public interface AlbumImageUrlLoaderCallback {
void onAlbumImageUrlLoaded(String url);
void onError();
}
}

View file

@ -1,109 +0,0 @@
package com.kabouzeid.gramophone.lastfm.album;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.lastfm.LastFMUtil;
import com.kabouzeid.gramophone.provider.AlbumJSONStore;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastFMAlbumInfoUtil {
public static final String TAG = LastFMAlbumInfoUtil.class.getSimpleName();
private static final String AUTO_CORRECT = "1";
public static String getAlbumUrl(String album, String artist) {
if (album != null) {
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.authority(LastFMUtil.BASE_URL)
.appendPath("2.0")
.appendQueryParameter("method", "album.getinfo")
.appendQueryParameter("album", album)
.appendQueryParameter("artist", artist)
//.appendQueryParameter("lang", "de")
.appendQueryParameter("autocorrect", AUTO_CORRECT)
.appendQueryParameter("api_key", LastFMUtil.API_KEY)
.appendQueryParameter("format", "json");
return builder.build().toString();
}
return "";
}
public static String getAlbumNameFromJSON(JSONObject rootJSON) {
try {
return rootJSON.getJSONObject("album").getString("name");
} catch (JSONException e) {
//Log.e(TAG, "Error while getting album name from JSON_DATA parameter!", e);
return "";
}
}
public static String getAlbumThumbnailUrlFromJSON(JSONObject rootJSON) {
try {
JSONArray images = getAlbumImageArrayFromJSON(rootJSON);
if (images.length() > 2) {
return images.getJSONObject(2).getString("#text");
} else if (images.length() > 1) {
return images.getJSONObject(1).getString("#text");
}
return images.getJSONObject(0).getString("#text");
} catch (JSONException | NullPointerException e) {
//Log.e(TAG, "Error while getting album thumbnail image from JSON_DATA parameter!", e);
return "";
}
}
public static JSONArray getAlbumImageArrayFromJSON(JSONObject rootJSON) {
try {
return rootJSON.getJSONObject("album").getJSONArray("image");
} catch (JSONException e) {
//Log.e(TAG, "Error while getting album image array from JSON_DATA parameter!", e);
return null;
}
}
public static String getAlbumImageUrlFromJSON(JSONObject rootJSON) {
try {
JSONArray images = getAlbumImageArrayFromJSON(rootJSON);
return images.getJSONObject(images.length() - 1).getString("#text");
} catch (JSONException | NullPointerException e) {
//Log.e(TAG, "Error while getting album image from JSON_DATA parameter!", e);
return "";
}
}
public static void downloadAlbumInfoJSON(final Context context, final String album, final String artist, final Response.Listener<JSONObject> callbackSuccess, final Response.ErrorListener callbackError) {
App app = (App) context.getApplicationContext();
String albumUrl = LastFMAlbumInfoUtil.getAlbumUrl(album, artist);
JsonObjectRequest albumInfoJSONRequest = new JsonObjectRequest(0, albumUrl, (JSONObject) null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
LastFMAlbumInfoUtil.saveAlbumJSONDataToCacheAndDisk(context, album, artist, response);
callbackSuccess.onResponse(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Download failed!", error);
callbackError.onErrorResponse(error);
}
});
app.addToVolleyRequestQueue(albumInfoJSONRequest);
}
public static void saveAlbumJSONDataToCacheAndDisk(Context context, String album, String artist, JSONObject jsonObject) {
AlbumJSONStore.getInstance(context).addAlbumJSON(album + artist, jsonObject.toString());
}
}

View file

@ -1,61 +0,0 @@
package com.kabouzeid.gramophone.lastfm.artist;
import android.content.Context;
import android.util.Log;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.provider.ArtistJSONStore;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastFMArtistBiographyLoader {
public static final String TAG = LastFMArtistBiographyLoader.class.getSimpleName();
public static void loadArtistBio(Context context, String queryArtist, ArtistBioLoaderCallback callback) {
if (queryArtist != null) {
String artistJSON = ArtistJSONStore.getInstance(context).getArtistJSON(queryArtist);
if (artistJSON != null) {
try {
JSONObject json = new JSONObject(artistJSON);
String bio = LastFMArtistInfoUtil.getArtistBiographyFromJSON(json);
callback.onArtistBioLoaded(bio);
} catch (JSONException e) {
Log.e(TAG, "Error while parsing bio from cache to JSONObject", e);
}
} else {
downloadArtistBio(context, queryArtist, callback);
}
}
}
private static void downloadArtistBio(final Context context, final String artist, final ArtistBioLoaderCallback callback) {
App app = (App) context.getApplicationContext();
String artistUrl = LastFMArtistInfoUtil.getArtistUrl(artist);
JsonObjectRequest artistInfoJSONRequest = new JsonObjectRequest(0, artistUrl, (JSONObject) null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
LastFMArtistInfoUtil.saveArtistJSONDataToCacheAndDisk(context, artist, response);
String bio = LastFMArtistInfoUtil.getArtistBiographyFromJSON(response);
callback.onArtistBioLoaded(bio);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Download failed!", error);
callback.onArtistBioLoaded("");
}
});
app.addToVolleyRequestQueue(artistInfoJSONRequest);
}
public interface ArtistBioLoaderCallback {
void onArtistBioLoaded(String bio);
}
}

View file

@ -1,48 +0,0 @@
package com.kabouzeid.gramophone.lastfm.artist;
import android.content.Context;
import android.util.Log;
import com.android.volley.Response;
import com.kabouzeid.gramophone.provider.ArtistJSONStore;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastFMArtistImageUrlLoader {
public static final String TAG = LastFMArtistImageUrlLoader.class.getSimpleName();
public static void loadArtistImageUrl(final Context context, String queryArtist, boolean forceDownload, final ArtistImageUrlLoaderCallback callback) {
if (queryArtist != null && !queryArtist.trim().equals("<unknown>")) {
String artistJSON = ArtistJSONStore.getInstance(context).getArtistJSON(queryArtist);
if (artistJSON != null && !forceDownload) {
try {
loadArtistImageUrlFromJSON(new JSONObject(artistJSON), callback);
} catch (JSONException e) {
Log.e(TAG, "Error while parsing string from cache to JSONObject", e);
}
} else {
LastFMArtistInfoUtil.downloadArtistJSON(context, queryArtist, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
loadArtistImageUrlFromJSON(response, callback);
}
});
}
}
}
private static void loadArtistImageUrlFromJSON(JSONObject jsonObject, final ArtistImageUrlLoaderCallback callback) {
String url = LastFMArtistInfoUtil.getArtistImageUrlFromJSON(jsonObject);
if (!url.trim().equals("")) {
callback.onArtistImageUrlLoaded(url);
}
}
public interface ArtistImageUrlLoaderCallback {
void onArtistImageUrlLoaded(String url);
}
}

View file

@ -1,119 +0,0 @@
package com.kabouzeid.gramophone.lastfm.artist;
import android.content.Context;
import android.net.Uri;
import android.util.Log;
import com.android.volley.Response;
import com.android.volley.VolleyError;
import com.android.volley.toolbox.JsonObjectRequest;
import com.kabouzeid.gramophone.App;
import com.kabouzeid.gramophone.lastfm.LastFMUtil;
import com.kabouzeid.gramophone.provider.ArtistJSONStore;
import org.json.JSONArray;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastFMArtistInfoUtil {
public static final String TAG = LastFMArtistInfoUtil.class.getSimpleName();
@SuppressWarnings("FieldCanBeLocal")
private static final String AUTO_CORRECT = "1";
public static String getArtistUrl(String artist) {
if (artist != null) {
Uri.Builder builder = new Uri.Builder();
builder.scheme("http")
.authority(LastFMUtil.BASE_URL)
.appendPath("2.0")
.appendQueryParameter("method", "artist.getinfo")
.appendQueryParameter("artist", artist)
//.appendQueryParameter("lang", "de")
.appendQueryParameter("autocorrect", AUTO_CORRECT)
.appendQueryParameter("api_key", LastFMUtil.API_KEY)
.appendQueryParameter("format", "json");
return builder.build().toString();
}
return "";
}
public static String getArtistNameFromJSON(JSONObject rootJSON) {
try {
return rootJSON.getJSONObject("artist").getString("name");
} catch (JSONException e) {
//Log.e(TAG, "Error while getting artist name from JSON_DATA parameter!", e);
return "";
}
}
public static String getArtistThumbnailUrlFromJSON(JSONObject rootJSON) {
try {
JSONArray images = getArtistImageArrayFromJSON(rootJSON);
if (images.length() > 2) {
return images.getJSONObject(2).getString("#text");
} else if (images.length() > 1) {
return images.getJSONObject(1).getString("#text");
}
return images.getJSONObject(0).getString("#text");
} catch (JSONException | NullPointerException e) {
//Log.e(TAG, "Error while getting artist thumbnail image from JSON_DATA parameter!", e);
return "";
}
}
public static JSONArray getArtistImageArrayFromJSON(JSONObject rootJSON) {
try {
return rootJSON.getJSONObject("artist").getJSONArray("image");
} catch (JSONException e) {
//Log.e(TAG, "Error while getting artist image array from JSON_DATA parameter!", e);
return null;
}
}
public static String getArtistImageUrlFromJSON(JSONObject rootJSON) {
try {
JSONArray images = getArtistImageArrayFromJSON(rootJSON);
return images.getJSONObject(images.length() - 1).getString("#text");
} catch (JSONException | NullPointerException e) {
//Log.e(TAG, "Error while getting artist image from JSON_DATA parameter!", e);
return "";
}
}
public static String getArtistBiographyFromJSON(JSONObject rootJSON) {
try {
return rootJSON.getJSONObject("artist").getJSONObject("bio").getString("content");
} catch (JSONException e) {
//Log.e(TAG, "Error while getting artist biography from JSON_DATA parameter!", e);
return "";
}
}
public static void saveArtistJSONDataToCacheAndDisk(Context context, String artist, JSONObject jsonObject) {
ArtistJSONStore.getInstance(context).removeArtistJSON(artist);
ArtistJSONStore.getInstance(context).addArtistJSON(artist, jsonObject.toString());
}
public static void downloadArtistJSON(final Context context, final String artist, final Response.Listener<JSONObject> callback) {
App app = (App) context.getApplicationContext();
String artistUrl = LastFMArtistInfoUtil.getArtistUrl(artist);
JsonObjectRequest artistInfoJSONRequest = new JsonObjectRequest(0, artistUrl, (JSONObject) null, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
LastFMArtistInfoUtil.saveArtistJSONDataToCacheAndDisk(context, artist, response);
callback.onResponse(response);
}
}, new Response.ErrorListener() {
@Override
public void onErrorResponse(VolleyError error) {
Log.e(TAG, "Download failed!", error);
}
});
app.addToVolleyRequestQueue(artistInfoJSONRequest);
}
}

View file

@ -1,48 +0,0 @@
package com.kabouzeid.gramophone.lastfm.artist;
import android.content.Context;
import android.util.Log;
import com.android.volley.Response;
import com.kabouzeid.gramophone.provider.ArtistJSONStore;
import org.json.JSONException;
import org.json.JSONObject;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastFMArtistThumbnailUrlLoader {
public static final String TAG = LastFMArtistThumbnailUrlLoader.class.getSimpleName();
public static void loadArtistThumbnailUrl(final Context context, String queryArtist, boolean forceDownload, final ArtistThumbnailUrlLoaderCallback callback) {
if (queryArtist != null && !queryArtist.trim().equals("<unknown>")) {
String artistJSON = ArtistJSONStore.getInstance(context).getArtistJSON(queryArtist);
if (artistJSON != null && !forceDownload) {
try {
loadArtistThumbnailUrlFromJSON(new JSONObject(artistJSON), callback);
} catch (JSONException e) {
Log.e(TAG, "Error while parsing string from cache to JSONObject", e);
}
} else {
LastFMArtistInfoUtil.downloadArtistJSON(context, queryArtist, new Response.Listener<JSONObject>() {
@Override
public void onResponse(JSONObject response) {
loadArtistThumbnailUrlFromJSON(response, callback);
}
});
}
}
}
private static void loadArtistThumbnailUrlFromJSON(final JSONObject jsonObject, final ArtistThumbnailUrlLoaderCallback callback) {
String url = LastFMArtistInfoUtil.getArtistThumbnailUrlFromJSON(jsonObject);
if (!url.trim().equals("")) {
callback.onArtistThumbnailUrlLoaded(url);
}
}
public interface ArtistThumbnailUrlLoaderCallback {
void onArtistThumbnailUrlLoaded(String url);
}
}

View file

@ -0,0 +1,49 @@
package com.kabouzeid.gramophone.lastfm.rest;
import android.content.Context;
import com.kabouzeid.gramophone.lastfm.rest.service.LastFMService;
import com.squareup.okhttp.Cache;
import com.squareup.okhttp.OkHttpClient;
import java.io.File;
import retrofit.RequestInterceptor;
import retrofit.RestAdapter;
import retrofit.client.OkClient;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public class LastFMRestClient {
public static final String BASE_URL = "http://ws.audioscrobbler.com/2.0";
private LastFMService apiService;
public LastFMRestClient(Context context) {
OkHttpClient okHttpClient = new OkHttpClient();
File cacheDir = new File(context.getCacheDir().getAbsolutePath(), "/okhttp-lastfm/");
if (cacheDir.mkdirs() || cacheDir.isDirectory()) {
okHttpClient.setCache(new Cache(cacheDir, 1024 * 1024 * 10));
}
RestAdapter restAdapter = new RestAdapter.Builder()
.setLogLevel(RestAdapter.LogLevel.FULL)
.setEndpoint(BASE_URL)
.setClient(new OkClient(okHttpClient))
.setRequestInterceptor(new RequestInterceptor() {
@Override
public void intercept(RequestInterceptor.RequestFacade request) {
request.addHeader("Cache-Control", String.format("max-age=%d, max-stale=%d", 31536000, 31536000));
}
})
.build();
apiService = restAdapter.create(LastFMService.class);
}
public LastFMService getApiService() {
return apiService;
}
}

View file

@ -0,0 +1,204 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
import java.util.ArrayList;
import java.util.List;
public class Album {
@Expose
private String name;
@Expose
private String artist;
@Expose
private String id;
@Expose
private String mbid;
@Expose
private String url;
@Expose
private String releasedate;
@Expose
private List<Image> image = new ArrayList<Image>();
@Expose
private String listeners;
@Expose
private String playcount;
@Expose
private Tracks tracks;
@Expose
private Toptags toptags;
@Expose
private Wiki wiki;
/**
* @return The name
*/
public String getName() {
return name;
}
/**
* @param name The name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return The artist
*/
public String getArtist() {
return artist;
}
/**
* @param artist The artist
*/
public void setArtist(String artist) {
this.artist = artist;
}
/**
* @return The id
*/
public String getId() {
return id;
}
/**
* @param id The id
*/
public void setId(String id) {
this.id = id;
}
/**
* @return The mbid
*/
public String getMbid() {
return mbid;
}
/**
* @param mbid The mbid
*/
public void setMbid(String mbid) {
this.mbid = mbid;
}
/**
* @return The url
*/
public String getUrl() {
return url;
}
/**
* @param url The url
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return The releasedate
*/
public String getReleasedate() {
return releasedate;
}
/**
* @param releasedate The releasedate
*/
public void setReleasedate(String releasedate) {
this.releasedate = releasedate;
}
/**
* @return The image
*/
public List<Image> getImage() {
return image;
}
/**
* @param image The image
*/
public void setImage(List<Image> image) {
this.image = image;
}
/**
* @return The listeners
*/
public String getListeners() {
return listeners;
}
/**
* @param listeners The listeners
*/
public void setListeners(String listeners) {
this.listeners = listeners;
}
/**
* @return The playcount
*/
public String getPlaycount() {
return playcount;
}
/**
* @param playcount The playcount
*/
public void setPlaycount(String playcount) {
this.playcount = playcount;
}
/**
* @return The tracks
*/
public Tracks getTracks() {
return tracks;
}
/**
* @param tracks The tracks
*/
public void setTracks(Tracks tracks) {
this.tracks = tracks;
}
/**
* @return The toptags
*/
public Toptags getToptags() {
return toptags;
}
/**
* @param toptags The toptags
*/
public void setToptags(Toptags toptags) {
this.toptags = toptags;
}
/**
* @return The wiki
*/
public Wiki getWiki() {
return wiki;
}
/**
* @param wiki The wiki
*/
public void setWiki(Wiki wiki) {
this.wiki = wiki;
}
}

View file

@ -0,0 +1,25 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
public class AlbumInfo {
@Expose
private Album album;
/**
* @return The album
*/
public Album getAlbum() {
return album;
}
/**
* @param album The album
*/
public void setAlbum(Album album) {
this.album = album;
}
}

View file

@ -0,0 +1,57 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
public class Artist {
@Expose
private String name;
@Expose
private String mbid;
@Expose
private String url;
/**
* @return The name
*/
public String getName() {
return name;
}
/**
* @param name The name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return The mbid
*/
public String getMbid() {
return mbid;
}
/**
* @param mbid The mbid
*/
public void setMbid(String mbid) {
this.mbid = mbid;
}
/**
* @return The url
*/
public String getUrl() {
return url;
}
/**
* @param url The url
*/
public void setUrl(String url) {
this.url = url;
}
}

View file

@ -0,0 +1,25 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
public class Attr {
@Expose
private String rank;
/**
* @return The rank
*/
public String getRank() {
return rank;
}
/**
* @param rank The rank
*/
public void setRank(String rank) {
this.rank = rank;
}
}

View file

@ -0,0 +1,43 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Image {
@SerializedName("#text")
@Expose
private String Text;
@Expose
private String size;
/**
* @return The Text
*/
public String getText() {
return Text;
}
/**
* @param Text The #text
*/
public void setText(String Text) {
this.Text = Text;
}
/**
* @return The size
*/
public String getSize() {
return size;
}
/**
* @param size The size
*/
public void setSize(String size) {
this.size = size;
}
}

View file

@ -0,0 +1,43 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Streamable {
@SerializedName("#text")
@Expose
private String Text;
@Expose
private String fulltrack;
/**
* @return The Text
*/
public String getText() {
return Text;
}
/**
* @param Text The #text
*/
public void setText(String Text) {
this.Text = Text;
}
/**
* @return The fulltrack
*/
public String getFulltrack() {
return fulltrack;
}
/**
* @param fulltrack The fulltrack
*/
public void setFulltrack(String fulltrack) {
this.fulltrack = fulltrack;
}
}

View file

@ -0,0 +1,41 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
public class Tag {
@Expose
private String name;
@Expose
private String url;
/**
* @return The name
*/
public String getName() {
return name;
}
/**
* @param name The name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return The url
*/
public String getUrl() {
return url;
}
/**
* @param url The url
*/
public void setUrl(String url) {
this.url = url;
}
}

View file

@ -0,0 +1,28 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
import java.util.ArrayList;
import java.util.List;
public class Toptags {
@Expose
private List<Tag> tag = new ArrayList<Tag>();
/**
* @return The tag
*/
public List<Tag> getTag() {
return tag;
}
/**
* @param tag The tag
*/
public void setTag(List<Tag> tag) {
this.tag = tag;
}
}

View file

@ -0,0 +1,123 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Track {
@Expose
private String name;
@Expose
private String duration;
@Expose
private String mbid;
@Expose
private String url;
@Expose
private Streamable streamable;
@Expose
private Artist artist;
@SerializedName("@attr")
@Expose
private com.kabouzeid.gramophone.lastfm.rest.model.albuminfo.Attr Attr;
/**
* @return The name
*/
public String getName() {
return name;
}
/**
* @param name The name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return The duration
*/
public String getDuration() {
return duration;
}
/**
* @param duration The duration
*/
public void setDuration(String duration) {
this.duration = duration;
}
/**
* @return The mbid
*/
public String getMbid() {
return mbid;
}
/**
* @param mbid The mbid
*/
public void setMbid(String mbid) {
this.mbid = mbid;
}
/**
* @return The url
*/
public String getUrl() {
return url;
}
/**
* @param url The url
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return The streamable
*/
public Streamable getStreamable() {
return streamable;
}
/**
* @param streamable The streamable
*/
public void setStreamable(Streamable streamable) {
this.streamable = streamable;
}
/**
* @return The artist
*/
public Artist getArtist() {
return artist;
}
/**
* @param artist The artist
*/
public void setArtist(Artist artist) {
this.artist = artist;
}
/**
* @return The Attr
*/
public com.kabouzeid.gramophone.lastfm.rest.model.albuminfo.Attr getAttr() {
return Attr;
}
/**
* @param Attr The @attr
*/
public void setAttr(com.kabouzeid.gramophone.lastfm.rest.model.albuminfo.Attr Attr) {
this.Attr = Attr;
}
}

View file

@ -0,0 +1,28 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
import java.util.ArrayList;
import java.util.List;
public class Tracks {
@Expose
private List<Track> track = new ArrayList<Track>();
/**
* @return The track
*/
public List<Track> getTrack() {
return track;
}
/**
* @param track The track
*/
public void setTrack(List<Track> track) {
this.track = track;
}
}

View file

@ -0,0 +1,57 @@
package com.kabouzeid.gramophone.lastfm.rest.model.albuminfo;
import com.google.gson.annotations.Expose;
public class Wiki {
@Expose
private String published;
@Expose
private String summary;
@Expose
private String content;
/**
* @return The published
*/
public String getPublished() {
return published;
}
/**
* @param published The published
*/
public void setPublished(String published) {
this.published = published;
}
/**
* @return The summary
*/
public String getSummary() {
return summary;
}
/**
* @param summary The summary
*/
public void setSummary(String summary) {
this.summary = summary;
}
/**
* @return The content
*/
public String getContent() {
return content;
}
/**
* @param content The content
*/
public void setContent(String content) {
this.content = content;
}
}

View file

@ -0,0 +1,172 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
import java.util.ArrayList;
import java.util.List;
public class Artist {
@Expose
private String name;
@Expose
private String mbid;
@Expose
private String url;
@Expose
private List<Image> image = new ArrayList<Image>();
@Expose
private String streamable;
@Expose
private String ontour;
@Expose
private Stats stats;
@Expose
private Similar similar;
@Expose
private Tags tags;
@Expose
private Bio bio;
/**
* @return The name
*/
public String getName() {
return name;
}
/**
* @param name The name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return The mbid
*/
public String getMbid() {
return mbid;
}
/**
* @param mbid The mbid
*/
public void setMbid(String mbid) {
this.mbid = mbid;
}
/**
* @return The url
*/
public String getUrl() {
return url;
}
/**
* @param url The url
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return The image
*/
public List<Image> getImage() {
return image;
}
/**
* @param image The image
*/
public void setImage(List<Image> image) {
this.image = image;
}
/**
* @return The streamable
*/
public String getStreamable() {
return streamable;
}
/**
* @param streamable The streamable
*/
public void setStreamable(String streamable) {
this.streamable = streamable;
}
/**
* @return The ontour
*/
public String getOntour() {
return ontour;
}
/**
* @param ontour The ontour
*/
public void setOntour(String ontour) {
this.ontour = ontour;
}
/**
* @return The stats
*/
public Stats getStats() {
return stats;
}
/**
* @param stats The stats
*/
public void setStats(Stats stats) {
this.stats = stats;
}
/**
* @return The similar
*/
public Similar getSimilar() {
return similar;
}
/**
* @param similar The similar
*/
public void setSimilar(Similar similar) {
this.similar = similar;
}
/**
* @return The tags
*/
public Tags getTags() {
return tags;
}
/**
* @param tags The tags
*/
public void setTags(Tags tags) {
this.tags = tags;
}
/**
* @return The bio
*/
public Bio getBio() {
return bio;
}
/**
* @param bio The bio
*/
public void setBio(Bio bio) {
this.bio = bio;
}
}

View file

@ -0,0 +1,25 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
public class ArtistInfo {
@Expose
private Artist artist;
/**
* @return The artist
*/
public Artist getArtist() {
return artist;
}
/**
* @param artist The artist
*/
public void setArtist(Artist artist) {
this.artist = artist;
}
}

View file

@ -0,0 +1,60 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
import java.util.ArrayList;
import java.util.List;
public class Artist_ {
@Expose
private String name;
@Expose
private String url;
@Expose
private List<Image_> image = new ArrayList<Image_>();
/**
* @return The name
*/
public String getName() {
return name;
}
/**
* @param name The name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return The url
*/
public String getUrl() {
return url;
}
/**
* @param url The url
*/
public void setUrl(String url) {
this.url = url;
}
/**
* @return The image
*/
public List<Image_> getImage() {
return image;
}
/**
* @param image The image
*/
public void setImage(List<Image_> image) {
this.image = image;
}
}

View file

@ -0,0 +1,105 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
public class Bio {
@Expose
private Links links;
@Expose
private String published;
@Expose
private String summary;
@Expose
private String content;
@Expose
private String yearformed;
@Expose
private Formationlist formationlist;
/**
* @return The links
*/
public Links getLinks() {
return links;
}
/**
* @param links The links
*/
public void setLinks(Links links) {
this.links = links;
}
/**
* @return The published
*/
public String getPublished() {
return published;
}
/**
* @param published The published
*/
public void setPublished(String published) {
this.published = published;
}
/**
* @return The summary
*/
public String getSummary() {
return summary;
}
/**
* @param summary The summary
*/
public void setSummary(String summary) {
this.summary = summary;
}
/**
* @return The content
*/
public String getContent() {
return content;
}
/**
* @param content The content
*/
public void setContent(String content) {
this.content = content;
}
/**
* @return The yearformed
*/
public String getYearformed() {
return yearformed;
}
/**
* @param yearformed The yearformed
*/
public void setYearformed(String yearformed) {
this.yearformed = yearformed;
}
/**
* @return The formationlist
*/
public Formationlist getFormationlist() {
return formationlist;
}
/**
* @param formationlist The formationlist
*/
public void setFormationlist(Formationlist formationlist) {
this.formationlist = formationlist;
}
}

View file

@ -0,0 +1,41 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
public class Formation {
@Expose
private String yearfrom;
@Expose
private String yearto;
/**
* @return The yearfrom
*/
public String getYearfrom() {
return yearfrom;
}
/**
* @param yearfrom The yearfrom
*/
public void setYearfrom(String yearfrom) {
this.yearfrom = yearfrom;
}
/**
* @return The yearto
*/
public String getYearto() {
return yearto;
}
/**
* @param yearto The yearto
*/
public void setYearto(String yearto) {
this.yearto = yearto;
}
}

View file

@ -0,0 +1,25 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
public class Formationlist {
@Expose
private Formation formation;
/**
* @return The formation
*/
public Formation getFormation() {
return formation;
}
/**
* @param formation The formation
*/
public void setFormation(Formation formation) {
this.formation = formation;
}
}

View file

@ -0,0 +1,43 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Image {
@SerializedName("#text")
@Expose
private String Text;
@Expose
private String size;
/**
* @return The Text
*/
public String getText() {
return Text;
}
/**
* @param Text The #text
*/
public void setText(String Text) {
this.Text = Text;
}
/**
* @return The size
*/
public String getSize() {
return size;
}
/**
* @param size The size
*/
public void setSize(String size) {
this.size = size;
}
}

View file

@ -0,0 +1,43 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Image_ {
@SerializedName("#text")
@Expose
private String Text;
@Expose
private String size;
/**
* @return The Text
*/
public String getText() {
return Text;
}
/**
* @param Text The #text
*/
public void setText(String Text) {
this.Text = Text;
}
/**
* @return The size
*/
public String getSize() {
return size;
}
/**
* @param size The size
*/
public void setSize(String size) {
this.size = size;
}
}

View file

@ -0,0 +1,59 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
import com.google.gson.annotations.SerializedName;
public class Link {
@SerializedName("#text")
@Expose
private String Text;
@Expose
private String rel;
@Expose
private String href;
/**
* @return The Text
*/
public String getText() {
return Text;
}
/**
* @param Text The #text
*/
public void setText(String Text) {
this.Text = Text;
}
/**
* @return The rel
*/
public String getRel() {
return rel;
}
/**
* @param rel The rel
*/
public void setRel(String rel) {
this.rel = rel;
}
/**
* @return The href
*/
public String getHref() {
return href;
}
/**
* @param href The href
*/
public void setHref(String href) {
this.href = href;
}
}

View file

@ -0,0 +1,25 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
public class Links {
@Expose
private Link link;
/**
* @return The link
*/
public Link getLink() {
return link;
}
/**
* @param link The link
*/
public void setLink(Link link) {
this.link = link;
}
}

View file

@ -0,0 +1,28 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
import java.util.ArrayList;
import java.util.List;
public class Similar {
@Expose
private List<Artist_> artist = new ArrayList<Artist_>();
/**
* @return The artist
*/
public List<Artist_> getArtist() {
return artist;
}
/**
* @param artist The artist
*/
public void setArtist(List<Artist_> artist) {
this.artist = artist;
}
}

View file

@ -0,0 +1,41 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
public class Stats {
@Expose
private String listeners;
@Expose
private String playcount;
/**
* @return The listeners
*/
public String getListeners() {
return listeners;
}
/**
* @param listeners The listeners
*/
public void setListeners(String listeners) {
this.listeners = listeners;
}
/**
* @return The playcount
*/
public String getPlaycount() {
return playcount;
}
/**
* @param playcount The playcount
*/
public void setPlaycount(String playcount) {
this.playcount = playcount;
}
}

View file

@ -0,0 +1,41 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
public class Tag {
@Expose
private String name;
@Expose
private String url;
/**
* @return The name
*/
public String getName() {
return name;
}
/**
* @param name The name
*/
public void setName(String name) {
this.name = name;
}
/**
* @return The url
*/
public String getUrl() {
return url;
}
/**
* @param url The url
*/
public void setUrl(String url) {
this.url = url;
}
}

View file

@ -0,0 +1,28 @@
package com.kabouzeid.gramophone.lastfm.rest.model.artistinfo;
import com.google.gson.annotations.Expose;
import java.util.ArrayList;
import java.util.List;
public class Tags {
@Expose
private List<Tag> tag = new ArrayList<Tag>();
/**
* @return The tag
*/
public List<Tag> getTag() {
return tag;
}
/**
* @param tag The tag
*/
public void setTag(List<Tag> tag) {
this.tag = tag;
}
}

View file

@ -0,0 +1,25 @@
package com.kabouzeid.gramophone.lastfm.rest.service;
import android.support.annotation.Nullable;
import com.kabouzeid.gramophone.lastfm.rest.model.albuminfo.AlbumInfo;
import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.ArtistInfo;
import retrofit.Callback;
import retrofit.http.GET;
import retrofit.http.Header;
import retrofit.http.Query;
/**
* @author Karim Abou Zeid (kabouzeid)
*/
public interface LastFMService {
String API_KEY = "bd9c6ea4d55ec9ed3af7d276e5ece304";
String BASE_QUERY_PARAMETERS = "/?format=json&autocorrect=1&api_key=" + API_KEY;
@GET(BASE_QUERY_PARAMETERS + "&method=album.getinfo")
void getAlbumInfo(@Query("album") String albumName, @Query("artist") String artistName, Callback<AlbumInfo> callback);
@GET(BASE_QUERY_PARAMETERS + "&method=artist.getinfo")
void getArtistInfo(@Query("artist") String artistName, @Nullable @Header("Cache-Control") String cacheControl, Callback<ArtistInfo> callback);
}

View file

@ -37,8 +37,9 @@ import com.kabouzeid.gramophone.helper.MusicPlayerRemote;
import com.kabouzeid.gramophone.helper.bitmapblur.StackBlurManager; import com.kabouzeid.gramophone.helper.bitmapblur.StackBlurManager;
import com.kabouzeid.gramophone.interfaces.CabHolder; import com.kabouzeid.gramophone.interfaces.CabHolder;
import com.kabouzeid.gramophone.interfaces.PaletteColorHolder; import com.kabouzeid.gramophone.interfaces.PaletteColorHolder;
import com.kabouzeid.gramophone.lastfm.artist.LastFMArtistBiographyLoader; import com.kabouzeid.gramophone.lastfm.rest.LastFMRestClient;
import com.kabouzeid.gramophone.lastfm.artist.LastFMArtistImageUrlLoader; import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.ArtistInfo;
import com.kabouzeid.gramophone.lastfm.rest.model.artistinfo.Image;
import com.kabouzeid.gramophone.loader.ArtistAlbumLoader; import com.kabouzeid.gramophone.loader.ArtistAlbumLoader;
import com.kabouzeid.gramophone.loader.ArtistLoader; import com.kabouzeid.gramophone.loader.ArtistLoader;
import com.kabouzeid.gramophone.loader.ArtistSongLoader; import com.kabouzeid.gramophone.loader.ArtistSongLoader;
@ -62,9 +63,14 @@ import com.nostra13.universalimageloader.core.listener.SimpleImageLoadingListene
import com.squareup.otto.Subscribe; import com.squareup.otto.Subscribe;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.List;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.InjectView; import butterknife.InjectView;
import hugo.weaving.DebugLog;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
/** /**
* A lot of hackery is done in this activity. Changing things may will brake the whole activity. * A lot of hackery is done in this activity. Changing things may will brake the whole activity.
@ -108,6 +114,10 @@ public class ArtistDetailActivity extends AbsFabActivity implements PaletteColor
private ArrayList<Song> songs; private ArrayList<Song> songs;
private ArrayList<Album> albums; private ArrayList<Album> albums;
private LastFMRestClient lastFMRestClient;
private StackBlurManager defaultArtistImageBlurManager;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
setStatusBarTransparent(); setStatusBarTransparent();
@ -123,6 +133,8 @@ public class ArtistDetailActivity extends AbsFabActivity implements PaletteColor
setNavigationBarColor(DialogUtils.resolveColor(this, R.attr.default_bar_color)); setNavigationBarColor(DialogUtils.resolveColor(this, R.attr.default_bar_color));
} }
lastFMRestClient = new LastFMRestClient(this);
getIntentExtras(); getIntentExtras();
initViews(); initViews();
setUpObservableListViewParams(); setUpObservableListViewParams();
@ -261,15 +273,21 @@ public class ArtistDetailActivity extends AbsFabActivity implements PaletteColor
} }
private void loadBiography() { private void loadBiography() {
LastFMArtistBiographyLoader.loadArtistBio(this, artist.name, new LastFMArtistBiographyLoader.ArtistBioLoaderCallback() { lastFMRestClient.getApiService().getArtistInfo(artist.name, null, new Callback<ArtistInfo>() {
@Override @Override
public void onArtistBioLoaded(String bio) { public void success(ArtistInfo artistInfo, Response response) {
String bio = artistInfo.getArtist().getBio().getContent();
if (bio != null && !bio.trim().equals("")) { if (bio != null && !bio.trim().equals("")) {
biography = Html.fromHtml(bio); biography = Html.fromHtml(bio);
} else { } else {
biography = null; biography = null;
} }
} }
@Override
public void failure(RetrofitError error) {
biography = null;
}
}); });
} }
@ -284,36 +302,68 @@ public class ArtistDetailActivity extends AbsFabActivity implements PaletteColor
private void setUpArtistImageAndApplyPalette(final boolean forceDownload) { private void setUpArtistImageAndApplyPalette(final boolean forceDownload) {
BitmapFactory.Options options = new BitmapFactory.Options(); BitmapFactory.Options options = new BitmapFactory.Options();
options.inSampleSize = 2; options.inSampleSize = 2;
final StackBlurManager defaultArtistImageBlurManager = new StackBlurManager(BitmapFactory.decodeResource(getResources(), R.drawable.default_artist_image, options)); if (defaultArtistImageBlurManager == null) {
LastFMArtistImageUrlLoader.loadArtistImageUrl(this, artist.name, forceDownload, new LastFMArtistImageUrlLoader.ArtistImageUrlLoaderCallback() { defaultArtistImageBlurManager = new StackBlurManager(BitmapFactory.decodeResource(getResources(), R.drawable.default_artist_image, options));
}
lastFMRestClient.getApiService().getArtistInfo(artist.name, forceDownload ? "no-cache" : null, new Callback<ArtistInfo>() {
@DebugLog
@Override @Override
public void onArtistImageUrlLoaded(final String url) { public void success(ArtistInfo artistInfo, Response response) {
ImageLoader.getInstance().displayImage(url, if (artistInfo.getArtist() != null) {
artistImage, List<Image> images = artistInfo.getArtist().getImage();
new DisplayImageOptions.Builder() int lastElementIndex = images.size() - 1;
.cacheInMemory(true) ImageLoader.getInstance().displayImage(images.get(lastElementIndex).getText(),
.cacheOnDisk(true) artistImage,
.showImageOnFail(R.drawable.default_artist_image) new DisplayImageOptions.Builder()
.resetViewBeforeLoading(true) .cacheInMemory(true)
.build(), .cacheOnDisk(true)
new SimpleImageLoadingListener() { .showImageOnFail(R.drawable.default_artist_image)
@Override .resetViewBeforeLoading(true)
public void onLoadingFailed(String imageUri, View view, FailReason failReason) { .build(),
applyPalette(null); new SimpleImageLoadingListener() {
artistImageBackground.setImageBitmap(defaultArtistImageBlurManager.process(10)); @DebugLog
} @Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
resetPaletteAndArtistImageBackground();
toastUpdatedArtistImageIfDownloadWasForced();
}
@Override @DebugLog
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { @Override
applyPalette(loadedImage); public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
artistImageBackground.setImageBitmap(new StackBlurManager(loadedImage).process(10)); applyPalette(loadedImage);
artistImageBackground.setImageBitmap(new StackBlurManager(loadedImage).process(10));
toastUpdatedArtistImageIfDownloadWasForced();
}
private void toastUpdatedArtistImageIfDownloadWasForced() {
if (forceDownload) {
Toast.makeText(ArtistDetailActivity.this, getString(R.string.updated_artist_image), Toast.LENGTH_SHORT).show();
}
}
} }
} );
); }
}
@DebugLog
@Override
public void failure(RetrofitError error) {
if (forceDownload) {
Toast.makeText(ArtistDetailActivity.this, getString(R.string.could_not_update_artist_image), Toast.LENGTH_SHORT).show();
} else {
artistImage.setImageResource(R.drawable.default_artist_image);
resetPaletteAndArtistImageBackground();
}
} }
}); });
} }
private void resetPaletteAndArtistImageBackground() {
applyPalette(null);
artistImageBackground.setImageBitmap(defaultArtistImageBlurManager.process(10));
}
private void applyPalette(Bitmap bitmap) { private void applyPalette(Bitmap bitmap) {
if (bitmap != null) { if (bitmap != null) {
Palette.from(bitmap) Palette.from(bitmap)

View file

@ -11,7 +11,9 @@ import android.widget.EditText;
import android.widget.Toast; import android.widget.Toast;
import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.R;
import com.kabouzeid.gramophone.lastfm.album.LastFMAlbumImageUrlLoader; import com.kabouzeid.gramophone.lastfm.rest.LastFMRestClient;
import com.kabouzeid.gramophone.lastfm.rest.model.albuminfo.AlbumInfo;
import com.kabouzeid.gramophone.lastfm.rest.model.albuminfo.Image;
import com.kabouzeid.gramophone.loader.AlbumSongLoader; import com.kabouzeid.gramophone.loader.AlbumSongLoader;
import com.kabouzeid.gramophone.loader.SongFilePathLoader; import com.kabouzeid.gramophone.loader.SongFilePathLoader;
import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.model.Song;
@ -35,6 +37,9 @@ import java.util.Map;
import butterknife.ButterKnife; import butterknife.ButterKnife;
import butterknife.InjectView; import butterknife.InjectView;
import retrofit.Callback;
import retrofit.RetrofitError;
import retrofit.client.Response;
public class AlbumTagEditorActivity extends AbsTagEditorActivity implements TextWatcher { public class AlbumTagEditorActivity extends AbsTagEditorActivity implements TextWatcher {
@ -51,12 +56,15 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text
private Bitmap albumArtBitmap; private Bitmap albumArtBitmap;
private boolean deleteAlbumArt; private boolean deleteAlbumArt;
private LastFMRestClient lastFMRestClient;
@Override @Override
protected void onCreate(Bundle savedInstanceState) { protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState); super.onCreate(savedInstanceState);
ButterKnife.inject(this); ButterKnife.inject(this);
lastFMRestClient = new LastFMRestClient(this);
setUpViews(); setUpViews();
} }
@ -95,36 +103,44 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text
Toast.makeText(this, getResources().getString(R.string.album_or_artist_empty), Toast.LENGTH_SHORT).show(); Toast.makeText(this, getResources().getString(R.string.album_or_artist_empty), Toast.LENGTH_SHORT).show();
return; return;
} }
LastFMAlbumImageUrlLoader.loadAlbumImageUrl(this, albumTitleStr, albumArtistNameStr, new LastFMAlbumImageUrlLoader.AlbumImageUrlLoaderCallback() { lastFMRestClient.getApiService().getAlbumInfo(albumTitleStr, albumArtistNameStr, new Callback<AlbumInfo>() {
@Override @Override
public void onAlbumImageUrlLoaded(String url) { public void success(AlbumInfo albumInfo, Response response) {
ImageLoader.getInstance().loadImage(url, if (albumInfo.getAlbum() != null) {
new ImageSize(500, 500), List<Image> images = albumInfo.getAlbum().getImage();
new SimpleImageLoadingListener() { int lastIndexOfImages = images.size() - 1;
@Override ImageLoader.getInstance().loadImage(images.get(lastIndexOfImages).getText(),
public void onLoadingFailed(String imageUri, View view, FailReason failReason) { new ImageSize(500, 500),
Toast.makeText(AlbumTagEditorActivity.this, new SimpleImageLoadingListener() {
R.string.failed_to_download_album_art, Toast.LENGTH_SHORT).show(); @Override
} public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
toastLoadingFailed();
}
@Override @Override
public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) { public void onLoadingComplete(String imageUri, View view, Bitmap loadedImage) {
albumArtBitmap = loadedImage; albumArtBitmap = loadedImage;
setImageBitmap(albumArtBitmap); setImageBitmap(albumArtBitmap);
deleteAlbumArt = false; deleteAlbumArt = false;
dataChanged(); dataChanged();
setResult(RESULT_OK); setResult(RESULT_OK);
} }
}); });
} } else {
toastLoadingFailed();
@Override
public void onError() {
Toast.makeText(AlbumTagEditorActivity.this,
R.string.failed_to_download_album_art, Toast.LENGTH_SHORT).show();
}
} }
); }
@Override
public void failure(RetrofitError error) {
toastLoadingFailed();
}
private void toastLoadingFailed() {
Toast.makeText(AlbumTagEditorActivity.this,
R.string.could_not_download_album_cover, Toast.LENGTH_SHORT).show();
}
});
} }
@Override @Override
@ -190,7 +206,7 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text
@Override @Override
public void onLoadingFailed(String imageUri, View view, FailReason failReason) { public void onLoadingFailed(String imageUri, View view, FailReason failReason) {
Toast.makeText(AlbumTagEditorActivity.this, Toast.makeText(AlbumTagEditorActivity.this,
R.string.failed_to_download_album_art, Toast.LENGTH_SHORT).show(); R.string.could_not_download_album_cover, Toast.LENGTH_SHORT).show();
} }
@Override @Override

View file

@ -135,7 +135,7 @@
<string name="pref_summary_colored_album_footers">"Názvy alb v mřížce jsou obarvena podle jejich obalu."</string> <string name="pref_summary_colored_album_footers">"Názvy alb v mřížce jsou obarvena podle jejich obalu."</string>
<string name="pref_summary_colored_notification">"Notifikace jsou zbarvena podle obalu alba."</string> <string name="pref_summary_colored_notification">"Notifikace jsou zbarvena podle obalu alba."</string>
<string name="pref_summary_gapless_playback">"Odstraní ticho mezi skladbami. Deaktivace může vyřešit problémy s přehráváním."</string> <string name="pref_summary_gapless_playback">"Odstraní ticho mezi skladbami. Deaktivace může vyřešit problémy s přehráváním."</string>
<string name="failed_to_download_album_art">"Nebylo možné stáhnout obrázek obalu alba"</string> <string name="could_not_download_album_cover">"Nebylo možné stáhnout obrázek obalu alba"</string>
<string name="search_hint">Vyhledat zvukové soubory...</string> <string name="search_hint">Vyhledat zvukové soubory...</string>
<string name="rescanning_media">Kontrola médií...</string> <string name="rescanning_media">Kontrola médií...</string>
<string name="favorites">Oblíbené</string> <string name="favorites">Oblíbené</string>

View file

@ -158,7 +158,7 @@
<string name="pref_summary_larger_title_box_now_playing">Die Bar unter dem Album Cover wo sich der Titel und Interpret befinden ist höher.</string> <string name="pref_summary_larger_title_box_now_playing">Die Bar unter dem Album Cover wo sich der Titel und Interpret befinden ist höher.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Benutzt einen Balken als Progress Slider anstatt dem normalen Progress Slider.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Benutzt einen Balken als Progress Slider anstatt dem normalen Progress Slider.</string>
<string name="pref_summary_playback_controller_card_now_playing">Zeigt eine Karte hinter der Wiedergabesteuerung</string> <string name="pref_summary_playback_controller_card_now_playing">Zeigt eine Karte hinter der Wiedergabesteuerung</string>
<string name="failed_to_download_album_art">"Das Album Cover konnte nicht heruntergeladen werden."</string> <string name="could_not_download_album_cover">"Das Album Cover konnte nicht heruntergeladen werden."</string>
<string name="search_hint">Durchsuche deine Mediathek</string> <string name="search_hint">Durchsuche deine Mediathek</string>
<string name="rescanning_media">Medien neu scannen...</string> <string name="rescanning_media">Medien neu scannen...</string>
<string name="favorites">Favoriten</string> <string name="favorites">Favoriten</string>

View file

@ -160,7 +160,7 @@
<string name="pref_summary_larger_title_box_now_playing">La caja detrás de la tapa del álbum donde se encuentra el título de la canción y el artista es mas largo que su altura.</string> <string name="pref_summary_larger_title_box_now_playing">La caja detrás de la tapa del álbum donde se encuentra el título de la canción y el artista es mas largo que su altura.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Usa una barra de progreso que no cubre la tapa del álbum en vez de la barra normal de progreso.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Usa una barra de progreso que no cubre la tapa del álbum en vez de la barra normal de progreso.</string>
<string name="pref_summary_playback_controller_card_now_playing">Mostrar tarjeta detrás de los botones de control de reproducción (reproducir/pausar, etc).</string> <string name="pref_summary_playback_controller_card_now_playing">Mostrar tarjeta detrás de los botones de control de reproducción (reproducir/pausar, etc).</string>
<string name="failed_to_download_album_art">"No se puede descargar la técnica para éste álbum"</string> <string name="could_not_download_album_cover">"No se puede descargar la técnica para éste álbum"</string>
<string name="search_hint">Buscar en librería...</string> <string name="search_hint">Buscar en librería...</string>
<string name="rescanning_media">Escaneando contenido...</string> <string name="rescanning_media">Escaneando contenido...</string>
<string name="favorites">Favoritos</string> <string name="favorites">Favoritos</string>

View file

@ -155,7 +155,7 @@
<string name="pref_summary_larger_title_box_now_playing">La boîte en dessous de la vignette de l\'album où se trouvent le titre de la musique et l\'artiste est plus large dans sa hauteur.</string> <string name="pref_summary_larger_title_box_now_playing">La boîte en dessous de la vignette de l\'album où se trouvent le titre de la musique et l\'artiste est plus large dans sa hauteur.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Utilise une barre de progression qui ne recouvre pas la vignette de l\'album à la place de la barre de progression normale.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Utilise une barre de progression qui ne recouvre pas la vignette de l\'album à la place de la barre de progression normale.</string>
<string name="pref_summary_playback_controller_card_now_playing">Affiche une carte derrière les boutons de lecture (lecture/pause etc.)</string> <string name="pref_summary_playback_controller_card_now_playing">Affiche une carte derrière les boutons de lecture (lecture/pause etc.)</string>
<string name="failed_to_download_album_art">"Impossible de télécharger la pochette pour cet album."</string> <string name="could_not_download_album_cover">"Impossible de télécharger la pochette pour cet album."</string>
<string name="search_hint">Rechercher votre bibliothèque...</string> <string name="search_hint">Rechercher votre bibliothèque...</string>
<string name="rescanning_media">Réanalyse des médias…</string> <string name="rescanning_media">Réanalyse des médias…</string>
<string name="favorites">Favoris</string> <string name="favorites">Favoris</string>

View file

@ -155,7 +155,7 @@
<string name="pref_summary_larger_title_box_now_playing">Okvir ispod omota albuma gdje su prikazani naslov pjesme i izvođač je viši.</string> <string name="pref_summary_larger_title_box_now_playing">Okvir ispod omota albuma gdje su prikazani naslov pjesme i izvođač je viši.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Koristi se traka napretka koja ne prekriva omot albuma umjesto zadanog klizača.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Koristi se traka napretka koja ne prekriva omot albuma umjesto zadanog klizača.</string>
<string name="pref_summary_playback_controller_card_now_playing">Prikazuje karticu ispod gumbića koji služe za kontrolu reprodukcije (pokreni/pauziraj itd.).</string> <string name="pref_summary_playback_controller_card_now_playing">Prikazuje karticu ispod gumbića koji služe za kontrolu reprodukcije (pokreni/pauziraj itd.).</string>
<string name="failed_to_download_album_art">"Neuspjelo skidanje omota ovog albuma."</string> <string name="could_not_download_album_cover">"Neuspjelo skidanje omota ovog albuma."</string>
<string name="search_hint">Pretraži fonoteku</string> <string name="search_hint">Pretraži fonoteku</string>
<string name="rescanning_media">Ponovno skeniram medijske datoteke</string> <string name="rescanning_media">Ponovno skeniram medijske datoteke</string>
<string name="favorites">Favoriti</string> <string name="favorites">Favoriti</string>

View file

@ -158,7 +158,7 @@
<string name="pref_summary_larger_title_box_now_playing">Il riquadro al di sotto della copertina in cui sono visualizzati il titolo del brano e l\'artista è più grande in altezza.</string> <string name="pref_summary_larger_title_box_now_playing">Il riquadro al di sotto della copertina in cui sono visualizzati il titolo del brano e l\'artista è più grande in altezza.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Usa una barra di scorrimento che non copre la copertina invece del normale cursore.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Usa una barra di scorrimento che non copre la copertina invece del normale cursore.</string>
<string name="pref_summary_playback_controller_card_now_playing">Visualizza un contorno in stile card dietro i controlli di riproduzione (play, pausa ecc.).</string> <string name="pref_summary_playback_controller_card_now_playing">Visualizza un contorno in stile card dietro i controlli di riproduzione (play, pausa ecc.).</string>
<string name="failed_to_download_album_art">"Impossibile scaricare la copertina per questo album."</string> <string name="could_not_download_album_cover">"Impossibile scaricare la copertina per questo album."</string>
<string name="search_hint">Cerca nella tua libreria...</string> <string name="search_hint">Cerca nella tua libreria...</string>
<string name="rescanning_media">Nuova scannerizzazione media in corso...</string> <string name="rescanning_media">Nuova scannerizzazione media in corso...</string>
<string name="favorites">Preferiti</string> <string name="favorites">Preferiti</string>

View file

@ -158,7 +158,7 @@
<string name="pref_summary_larger_title_box_now_playing">アルバムアート下のタイトルとアーティスト名を大きく表示します</string> <string name="pref_summary_larger_title_box_now_playing">アルバムアート下のタイトルとアーティスト名を大きく表示します</string>
<string name="pref_summary_alternative_progress_slider_now_playing">アルバムアートに被らないシークバーに変更します</string> <string name="pref_summary_alternative_progress_slider_now_playing">アルバムアートに被らないシークバーに変更します</string>
<string name="pref_summary_playback_controller_card_now_playing">再生コントロールキー(l◀, ▶/ll, ▶l など)をカードの上に表示します</string> <string name="pref_summary_playback_controller_card_now_playing">再生コントロールキー(l◀, ▶/ll, ▶l など)をカードの上に表示します</string>
<string name="failed_to_download_album_art">"アルバムアートのダウンロードに失敗しました"</string> <string name="could_not_download_album_cover">"アルバムアートのダウンロードに失敗しました"</string>
<string name="search_hint">ライブラリ内を検索…</string> <string name="search_hint">ライブラリ内を検索…</string>
<string name="rescanning_media">メディアの再スキャン中…</string> <string name="rescanning_media">メディアの再スキャン中…</string>
<string name="favorites">お気に入り</string> <string name="favorites">お気に入り</string>

View file

@ -156,7 +156,7 @@
<string name="pref_summary_larger_title_box_now_playing">앨범 아트 밑에 있는 제목 바의 높이를 커지게 합니다.</string> <string name="pref_summary_larger_title_box_now_playing">앨범 아트 밑에 있는 제목 바의 높이를 커지게 합니다.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">보통의 조절 슬라이더 대신 앨범 아트를 가리지 않는 대체 조절 슬라이더를 사용합니다.</string> <string name="pref_summary_alternative_progress_slider_now_playing">보통의 조절 슬라이더 대신 앨범 아트를 가리지 않는 대체 조절 슬라이더를 사용합니다.</string>
<string name="pref_summary_playback_controller_card_now_playing">지금 재생 중 화면에서 컨트롤 부분(재생, 일시정지 등의 버튼이 있는 곳)을 카드로 표시합니다.</string> <string name="pref_summary_playback_controller_card_now_playing">지금 재생 중 화면에서 컨트롤 부분(재생, 일시정지 등의 버튼이 있는 곳)을 카드로 표시합니다.</string>
<string name="failed_to_download_album_art">"이 앨범의 앨범 커버를 다운로드할 수 없습니다."</string> <string name="could_not_download_album_cover">"이 앨범의 앨범 커버를 다운로드할 수 없습니다."</string>
<string name="search_hint">저장소 검색...</string> <string name="search_hint">저장소 검색...</string>
<string name="rescanning_media">미디어 재스캐닝 중...</string> <string name="rescanning_media">미디어 재스캐닝 중...</string>
<string name="favorites">좋아하는 곡들</string> <string name="favorites">좋아하는 곡들</string>

View file

@ -158,7 +158,7 @@
<string name="pref_summary_larger_title_box_now_playing">De kader onder de albumhoes, waar de artiest en titel worden getoond, is groter.</string> <string name="pref_summary_larger_title_box_now_playing">De kader onder de albumhoes, waar de artiest en titel worden getoond, is groter.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Gebruikt een progressiebalk die de albumhoes niet bedekt, in plaats van de standaard progressiecirkel.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Gebruikt een progressiebalk die de albumhoes niet bedekt, in plaats van de standaard progressiecirkel.</string>
<string name="pref_summary_playback_controller_card_now_playing">Weergeeft een kaart onder de bedieningsknoppen (afspelen/pauze etc.).</string> <string name="pref_summary_playback_controller_card_now_playing">Weergeeft een kaart onder de bedieningsknoppen (afspelen/pauze etc.).</string>
<string name="failed_to_download_album_art">"Niet in staat deze albumhoes te downloaden."</string> <string name="could_not_download_album_cover">"Niet in staat deze albumhoes te downloaden."</string>
<string name="search_hint">Zoek in je bibliotheek...</string> <string name="search_hint">Zoek in je bibliotheek...</string>
<string name="rescanning_media">Media herscannen...</string> <string name="rescanning_media">Media herscannen...</string>
<string name="favorites">Favorieten</string> <string name="favorites">Favorieten</string>

View file

@ -158,7 +158,7 @@
<string name="pref_summary_larger_title_box_now_playing">Zaznacz, a pole nazwy utworu i wykonawcy pod okładką albumu będzie większe</string> <string name="pref_summary_larger_title_box_now_playing">Zaznacz, a pole nazwy utworu i wykonawcy pod okładką albumu będzie większe</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Zaznacz, a w odróżnieniu od domyślnego suwaka, pasek postępu nie zasłoni okładki albumu</string> <string name="pref_summary_alternative_progress_slider_now_playing">Zaznacz, a w odróżnieniu od domyślnego suwaka, pasek postępu nie zasłoni okładki albumu</string>
<string name="pref_summary_playback_controller_card_now_playing">Zaznacz, a pod przyciskami sterującymi odtwarzaczem (odtwarzanie/pauza, itp.) zostanie wyświetlona karta</string> <string name="pref_summary_playback_controller_card_now_playing">Zaznacz, a pod przyciskami sterującymi odtwarzaczem (odtwarzanie/pauza, itp.) zostanie wyświetlona karta</string>
<string name="failed_to_download_album_art">"Nie można pobrać okładki dla tego albumu"</string> <string name="could_not_download_album_cover">"Nie można pobrać okładki dla tego albumu"</string>
<string name="search_hint">Szukaj w bibliotece...</string> <string name="search_hint">Szukaj w bibliotece...</string>
<string name="rescanning_media">Ponowny skan nośnika...</string> <string name="rescanning_media">Ponowny skan nośnika...</string>
<string name="favorites">Ulubione</string> <string name="favorites">Ulubione</string>

View file

@ -158,7 +158,7 @@
<string name="pref_summary_larger_title_box_now_playing">A caixa embaixo da capa do álbum onde o titulo da musica e o artista são mostrados é mais largo na sua altura.</string> <string name="pref_summary_larger_title_box_now_playing">A caixa embaixo da capa do álbum onde o titulo da musica e o artista são mostrados é mais largo na sua altura.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Usa uma barra de progresso que não cobre a capa do álbum substituindo a barra padrão.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Usa uma barra de progresso que não cobre a capa do álbum substituindo a barra padrão.</string>
<string name="pref_summary_playback_controller_card_now_playing">Mostra um cartão abaixo dos controles de reprodução (tocar/pausar etc.)</string> <string name="pref_summary_playback_controller_card_now_playing">Mostra um cartão abaixo dos controles de reprodução (tocar/pausar etc.)</string>
<string name="failed_to_download_album_art">"Não foi possível baixar a imagem para este álbum."</string> <string name="could_not_download_album_cover">"Não foi possível baixar a imagem para este álbum."</string>
<string name="search_hint">Pesquisar na sua biblioteca...</string> <string name="search_hint">Pesquisar na sua biblioteca...</string>
<string name="rescanning_media">Verificando mídia novamente...</string> <string name="rescanning_media">Verificando mídia novamente...</string>
<string name="favorites">Favoritos</string> <string name="favorites">Favoritos</string>

View file

@ -155,7 +155,7 @@
<string name="pref_summary_larger_title_box_now_playing">Şarkı başlığı ve sanatçıya giden albüm kapağı altındaki kutusunun yüksekliğini büyültür.</string> <string name="pref_summary_larger_title_box_now_playing">Şarkı başlığı ve sanatçıya giden albüm kapağı altındaki kutusunun yüksekliğini büyültür.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Varsayılan ilerleme çubuğu yerine albüm kapağına taşan ilerleme çubuğu kullanılır.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Varsayılan ilerleme çubuğu yerine albüm kapağına taşan ilerleme çubuğu kullanılır.</string>
<string name="pref_summary_playback_controller_card_now_playing">Oynatma kontrol düğmelerinin altında bir kart görüntüler (oynat/duraklat, vb.).</string> <string name="pref_summary_playback_controller_card_now_playing">Oynatma kontrol düğmelerinin altında bir kart görüntüler (oynat/duraklat, vb.).</string>
<string name="failed_to_download_album_art">"Bu albüm için kapak indirilemiyor."</string> <string name="could_not_download_album_cover">"Bu albüm için kapak indirilemiyor."</string>
<string name="search_hint">Kütüphaneniz taranıyor...</string> <string name="search_hint">Kütüphaneniz taranıyor...</string>
<string name="rescanning_media">Medyayı yeniden tara</string> <string name="rescanning_media">Medyayı yeniden tara</string>
<string name="favorites">Favoriler</string> <string name="favorites">Favoriler</string>

View file

@ -158,7 +158,7 @@
<string name="pref_summary_larger_title_box_now_playing">增加专辑封面下方用于显示歌曲名称和艺术家区域的高度</string> <string name="pref_summary_larger_title_box_now_playing">增加专辑封面下方用于显示歌曲名称和艺术家区域的高度</string>
<string name="pref_summary_alternative_progress_slider_now_playing">使用不会遮挡专辑封面的进度条替代正常的进度滑块。</string> <string name="pref_summary_alternative_progress_slider_now_playing">使用不会遮挡专辑封面的进度条替代正常的进度滑块。</string>
<string name="pref_summary_playback_controller_card_now_playing">在播放控制按钮(播放/暂停等)下方显示卡片背景</string> <string name="pref_summary_playback_controller_card_now_playing">在播放控制按钮(播放/暂停等)下方显示卡片背景</string>
<string name="failed_to_download_album_art">"专辑信息下载失败"</string> <string name="could_not_download_album_cover">"专辑信息下载失败"</string>
<string name="search_hint">正在扫描</string> <string name="search_hint">正在扫描</string>
<string name="rescanning_media">正在重新扫描媒体库…</string> <string name="rescanning_media">正在重新扫描媒体库…</string>
<string name="favorites">收藏夹</string> <string name="favorites">收藏夹</string>

View file

@ -59,6 +59,8 @@
<string name="credits_1">"Phonograph is a completely free material designed music player by"</string> <string name="credits_1">"Phonograph is a completely free material designed music player by"</string>
<string name="no_results">No results</string> <string name="no_results">No results</string>
<string name="action_re_download_artist_image">Update artist image</string> <string name="action_re_download_artist_image">Update artist image</string>
<string name="updated_artist_image">Updated artist image.</string>
<string name="could_not_update_artist_image">Could not update artist image.</string>
<string name="updating">Updating…</string> <string name="updating">Updating…</string>
<string name="added_title_to_playing_queue">"Added 1 title to the playing queue."</string> <string name="added_title_to_playing_queue">"Added 1 title to the playing queue."</string>
<string name="added_x_titles_to_playing_queue">Added %1$d titles to the playing queue.</string> <string name="added_x_titles_to_playing_queue">Added %1$d titles to the playing queue.</string>
@ -158,7 +160,7 @@
<string name="pref_summary_larger_title_box_now_playing">The box below the album art where the song title and artist goes is larger in its height.</string> <string name="pref_summary_larger_title_box_now_playing">The box below the album art where the song title and artist goes is larger in its height.</string>
<string name="pref_summary_alternative_progress_slider_now_playing">Uses a progressbar which does not cover the album art instead of the default progress slider.</string> <string name="pref_summary_alternative_progress_slider_now_playing">Uses a progressbar which does not cover the album art instead of the default progress slider.</string>
<string name="pref_summary_playback_controller_card_now_playing">Displays a card below the playback controller buttons (play/pause etc.).</string> <string name="pref_summary_playback_controller_card_now_playing">Displays a card below the playback controller buttons (play/pause etc.).</string>
<string name="failed_to_download_album_art">"Unable to download the art for this album."</string> <string name="could_not_download_album_cover">"Could not download a matching album cover."</string>
<string name="search_hint">Search your library…</string> <string name="search_hint">Search your library…</string>
<string name="rescanning_media">Rescanning media…</string> <string name="rescanning_media">Rescanning media…</string>
<string name="favorites">Favorites</string> <string name="favorites">Favorites</string>