From b41ef5bff51956e71a46b1103aba4fa0a32ad392 Mon Sep 17 00:00:00 2001 From: h4h13 Date: Sun, 1 Mar 2020 18:51:43 +0530 Subject: [PATCH] Fix loading placeholder image for artist --- app/build.gradle | 2 - .../retromusic/activities/MainActivity.java | 7 +- .../tageditor/AlbumTagEditorActivity.kt | 3 - .../glide/artistimage/ArtistImageLoader.kt | 21 +++- .../retromusic/providers/RepositoryImpl.kt | 6 +- .../retromusic/rest/LastFMRestClient.java | 99 ------------------- .../monkey/retromusic/rest/LastFmClient.kt | 70 +++++++++++++ .../retromusic/rest/service/LastFMService.kt | 3 +- 8 files changed, 96 insertions(+), 115 deletions(-) delete mode 100644 app/src/main/java/code/name/monkey/retromusic/rest/LastFMRestClient.java create mode 100644 app/src/main/java/code/name/monkey/retromusic/rest/LastFmClient.kt diff --git a/app/build.gradle b/app/build.gradle index dc5b3a0c..16fb2d8c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -141,8 +141,6 @@ dependencies { implementation "com.squareup.retrofit2:retrofit:$retrofit_version" implementation "com.squareup.retrofit2:converter-gson:$retrofit_version" - implementation 'com.jakewharton.retrofit:retrofit2-kotlin-coroutines-adapter:0.9.2' - def material_dialog_version = "3.1.1" implementation "com.afollestad.material-dialogs:core:$material_dialog_version" implementation "com.afollestad.material-dialogs:input:$material_dialog_version" diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java index 16d56e64..c81c3d90 100644 --- a/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java +++ b/app/src/main/java/code/name/monkey/retromusic/activities/MainActivity.java @@ -215,9 +215,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity menu.add(0, R.id.action_search, 0, getString(R.string.action_search)) .setIcon(R.drawable.ic_mic_white_24dp) .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM); - menu.add(0, R.id.action_settings, 0, getString(R.string.action_settings)) - .setIcon(R.drawable.ic_settings_white_24dp) - .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM); + } if (isFolderPage()) { menu.add(0, R.id.action_scan, 0, R.string.scan_media) @@ -249,6 +247,9 @@ public class MainActivity extends AbsSlidingMusicPanelActivity menu.removeItem(R.id.action_grid_size); menu.removeItem(R.id.action_sort_order); } + menu.add(0, R.id.action_settings, 0, getString(R.string.action_settings)) + .setIcon(R.drawable.ic_settings_white_24dp) + .setShowAsActionFlags(MenuItem.SHOW_AS_ACTION_IF_ROOM); return super.onCreateOptionsMenu(menu); } diff --git a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt index 6dabc933..b2968404 100755 --- a/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt +++ b/app/src/main/java/code/name/monkey/retromusic/activities/tageditor/AlbumTagEditorActivity.kt @@ -19,7 +19,6 @@ import code.name.monkey.retromusic.extensions.appHandleColor import code.name.monkey.retromusic.glide.palette.BitmapPaletteTranscoder import code.name.monkey.retromusic.glide.palette.BitmapPaletteWrapper import code.name.monkey.retromusic.loaders.AlbumLoader -import code.name.monkey.retromusic.rest.LastFMRestClient import code.name.monkey.retromusic.util.ImageUtil import code.name.monkey.retromusic.util.RetroColorUtil.generatePalette import code.name.monkey.retromusic.util.RetroColorUtil.getColor @@ -82,7 +81,6 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher { private var albumArtBitmap: Bitmap? = null private var deleteAlbumArt: Boolean = false - private var lastFMRestClient: LastFMRestClient? = null private fun setupToolbar() { toolbar.setBackgroundColor(ATHUtil.resolveColor(this, R.attr.colorSurface)) @@ -93,7 +91,6 @@ class AlbumTagEditorActivity : AbsTagEditorActivity(), TextWatcher { setDrawUnderStatusBar() super.onCreate(savedInstanceState) window.sharedElementsUseOverlay = true - lastFMRestClient = LastFMRestClient(this) imageContainer?.transitionName = "${getString(R.string.transition_album_art)}_$id" windowEnterTransition() setUpViews() diff --git a/app/src/main/java/code/name/monkey/retromusic/glide/artistimage/ArtistImageLoader.kt b/app/src/main/java/code/name/monkey/retromusic/glide/artistimage/ArtistImageLoader.kt index 0ed4e892..7c8e4f7a 100644 --- a/app/src/main/java/code/name/monkey/retromusic/glide/artistimage/ArtistImageLoader.kt +++ b/app/src/main/java/code/name/monkey/retromusic/glide/artistimage/ArtistImageLoader.kt @@ -27,7 +27,9 @@ import com.bumptech.glide.load.model.GlideUrl import com.bumptech.glide.load.model.ModelLoader import com.bumptech.glide.load.model.ModelLoaderFactory import com.bumptech.glide.load.model.stream.StreamModelLoader +import okhttp3.Interceptor import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor import java.io.IOException import java.io.InputStream import java.util.concurrent.TimeUnit @@ -76,9 +78,15 @@ class ArtistImageFetcher( return try { val deezerResponse = response.body(); val imageUrl = deezerResponse?.data?.get(0)?.let { getHighestQuality(it) } - val glideUrl = GlideUrl(imageUrl) - urlFetcher = urlLoader.getResourceFetcher(glideUrl, width, height) - urlFetcher?.loadData(priority) + // Fragile way to detect a place holder image returned from Deezer: + // ex: "https://e-cdns-images.dzcdn.net/images/artist//250x250-000000-80-0-0.jpg" + // the double slash implies no artist identified + val placeHolder = imageUrl?.contains("/images/artist//") ?: false + if (!placeHolder) { + val glideUrl = GlideUrl(imageUrl) + urlFetcher = urlLoader.getResourceFetcher(glideUrl, width, height) + urlFetcher?.loadData(priority) + } else null } catch (e: Exception) { null } @@ -132,10 +140,17 @@ class Factory( .connectTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .readTimeout(TIMEOUT, TimeUnit.MILLISECONDS) .writeTimeout(TIMEOUT, TimeUnit.MILLISECONDS) + .addInterceptor(createLogInterceptor()) .build() ) } + private fun createLogInterceptor(): Interceptor { + val interceptor = HttpLoggingInterceptor() + interceptor.level = HttpLoggingInterceptor.Level.BODY + return interceptor + } + override fun build( context: Context?, factories: GenericLoaderFactory? diff --git a/app/src/main/java/code/name/monkey/retromusic/providers/RepositoryImpl.kt b/app/src/main/java/code/name/monkey/retromusic/providers/RepositoryImpl.kt index 91d4f947..a85017f0 100644 --- a/app/src/main/java/code/name/monkey/retromusic/providers/RepositoryImpl.kt +++ b/app/src/main/java/code/name/monkey/retromusic/providers/RepositoryImpl.kt @@ -23,7 +23,7 @@ import code.name.monkey.retromusic.adapter.HomeAdapter import code.name.monkey.retromusic.loaders.* import code.name.monkey.retromusic.model.* import code.name.monkey.retromusic.providers.interfaces.Repository -import code.name.monkey.retromusic.rest.LastFMRestClient +import code.name.monkey.retromusic.rest.LastFmClient import code.name.monkey.retromusic.rest.model.LastFmAlbum import code.name.monkey.retromusic.rest.model.LastFmArtist import java.io.IOException @@ -259,7 +259,7 @@ class RepositoryImpl @Inject constructor(private val context: Context) : Reposit cache: String? ): Result = safeApiCall( call = { - Success(LastFMRestClient(context).apiService.artistInfo(name, lang, cache)) + Success(LastFmClient.getApiService().artistInfo(name, lang, cache)) }, errorMessage = "Error" @@ -270,7 +270,7 @@ class RepositoryImpl @Inject constructor(private val context: Context) : Reposit album: String ): Result = safeApiCall( call = { - Success(LastFMRestClient(context).apiService.albumInfo(artist, album)) + Success(LastFmClient.getApiService().albumInfo(artist, album)) }, errorMessage = "Error" ) diff --git a/app/src/main/java/code/name/monkey/retromusic/rest/LastFMRestClient.java b/app/src/main/java/code/name/monkey/retromusic/rest/LastFMRestClient.java deleted file mode 100644 index 8e1113ea..00000000 --- a/app/src/main/java/code/name/monkey/retromusic/rest/LastFMRestClient.java +++ /dev/null @@ -1,99 +0,0 @@ -/* - * Copyright (c) 2019 Hemanth Savarala. - * - * Licensed under the GNU General Public License v3 - * - * This is free software: you can redistribute it and/or modify it under - * the terms of the GNU General Public License as published by - * the Free Software Foundation either version 3 of the License, or (at your option) any later version. - * - * This software is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; - * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. - * See the GNU General Public License for more details. - */ - -package code.name.monkey.retromusic.rest; - -import android.content.Context; - -import androidx.annotation.NonNull; -import androidx.annotation.Nullable; - -import java.io.File; -import java.util.concurrent.TimeUnit; - -import code.name.monkey.retromusic.rest.service.LastFMService; -import okhttp3.Cache; -import okhttp3.Call; -import okhttp3.ConnectionPool; -import okhttp3.Interceptor; -import okhttp3.OkHttpClient; -import okhttp3.Request; -import okhttp3.logging.HttpLoggingInterceptor; -import retrofit2.Retrofit; -import retrofit2.converter.gson.GsonConverterFactory; - - -public class LastFMRestClient { - - private static final String BASE_URL = "https://ws.audioscrobbler.com/2.0/"; - - private LastFMService apiService; - - public LastFMRestClient(@NonNull Context context) { - this(createDefaultOkHttpClientBuilder(context).build()); - } - - private LastFMRestClient(@NonNull Call.Factory client) { - Retrofit restAdapter = new Retrofit.Builder() - .baseUrl(BASE_URL) - .callFactory(client) - .addConverterFactory(GsonConverterFactory.create()) - .build(); - - apiService = restAdapter.create(LastFMService.class); - } - - private static Interceptor createCacheControlInterceptor() { - return chain -> { - Request modifiedRequest = chain.request().newBuilder() - .addHeader("Cache-Control", "max-age=31536000, max-stale=31536000") - .build(); - return chain.proceed(modifiedRequest); - }; - } - - @Nullable - private static Cache createDefaultCache(Context context) { - File cacheDir = new File(context.getCacheDir().getAbsolutePath(), "/okhttp-lastfm/"); - if (cacheDir.mkdirs() || cacheDir.isDirectory()) { - return new Cache(cacheDir, 1024 * 1024 * 10); - } - return null; - } - - @NonNull - private static OkHttpClient.Builder createDefaultOkHttpClientBuilder(@NonNull Context context) { - return new OkHttpClient.Builder() - .connectionPool(new ConnectionPool(0, 1, TimeUnit.NANOSECONDS)) - .retryOnConnectionFailure(true) - .connectTimeout(1, TimeUnit.MINUTES) // connect timeout - .writeTimeout(1, TimeUnit.MINUTES) // write timeout - .readTimeout(1, TimeUnit.MINUTES) // read timeout - .cache(createDefaultCache(context)) - .addInterceptor(createCacheControlInterceptor()) - .addInterceptor(createLogInterceptor()); - } - - @NonNull - private static Interceptor createLogInterceptor() { - HttpLoggingInterceptor interceptor = new HttpLoggingInterceptor(); - interceptor.setLevel(HttpLoggingInterceptor.Level.BODY); - return interceptor; - } - - @NonNull - public LastFMService getApiService() { - return apiService; - } -} diff --git a/app/src/main/java/code/name/monkey/retromusic/rest/LastFmClient.kt b/app/src/main/java/code/name/monkey/retromusic/rest/LastFmClient.kt new file mode 100644 index 00000000..5c2e6e85 --- /dev/null +++ b/app/src/main/java/code/name/monkey/retromusic/rest/LastFmClient.kt @@ -0,0 +1,70 @@ +package code.name.monkey.retromusic.rest + +import code.name.monkey.retromusic.App +import code.name.monkey.retromusic.rest.service.LastFMService +import com.google.gson.Gson +import okhttp3.Cache +import okhttp3.ConnectionPool +import okhttp3.Interceptor +import okhttp3.Interceptor.Chain +import okhttp3.OkHttpClient +import okhttp3.logging.HttpLoggingInterceptor +import retrofit2.Retrofit +import retrofit2.converter.gson.GsonConverterFactory +import java.io.File +import java.util.concurrent.TimeUnit + +object LastFmClient { + private const val baseUrl = "https://ws.audioscrobbler.com/2.0/" + + private var lastFMService: LastFMService + + fun getApiService(): LastFMService { + return lastFMService + } + + init { + val retrofit = Retrofit.Builder() + .baseUrl(baseUrl) + .callFactory(createDefaultOkHttpClientBuilder().build()) + .addConverterFactory(GsonConverterFactory.create(Gson())) + .build() + + lastFMService = retrofit.create(LastFMService::class.java) + } + + private fun createDefaultOkHttpClientBuilder(): OkHttpClient.Builder { + return OkHttpClient.Builder() + .connectionPool(ConnectionPool(0, 1, TimeUnit.NANOSECONDS)) + .retryOnConnectionFailure(true) + .connectTimeout(1, TimeUnit.MINUTES) // connect timeout + .writeTimeout(1, TimeUnit.MINUTES) // write timeout + .readTimeout(1, TimeUnit.MINUTES) // read timeout + .cache(createDefaultCache()) + .addInterceptor(createCacheControlInterceptor()) + .addInterceptor(createLogInterceptor()) + } + + private fun createLogInterceptor(): Interceptor { + val interceptor = HttpLoggingInterceptor() + interceptor.level = HttpLoggingInterceptor.Level.BASIC + return interceptor + } + + private fun createCacheControlInterceptor(): Interceptor { + return Interceptor { chain: Chain -> + val modifiedRequest = chain.request().newBuilder() + .addHeader("Cache-Control", "max-age=31536000, max-stale=31536000") + .build() + chain.proceed(modifiedRequest) + } + } + + private fun createDefaultCache(): Cache? { + val cacheDir = File(App.getContext().cacheDir.absolutePath, "/okhttp-lastfm/") + if (cacheDir.mkdirs() || cacheDir.isDirectory) { + return Cache(cacheDir, 1024 * 1024 * 10) + } + return null + } +} \ No newline at end of file diff --git a/app/src/main/java/code/name/monkey/retromusic/rest/service/LastFMService.kt b/app/src/main/java/code/name/monkey/retromusic/rest/service/LastFMService.kt index 02175e1c..c9ee7d10 100644 --- a/app/src/main/java/code/name/monkey/retromusic/rest/service/LastFMService.kt +++ b/app/src/main/java/code/name/monkey/retromusic/rest/service/LastFMService.kt @@ -25,9 +25,8 @@ import retrofit2.http.Query */ interface LastFMService { - companion object { - const val API_KEY = "c679c8d3efa84613dc7dcb2e8d42da4c" + private const val API_KEY = "c679c8d3efa84613dc7dcb2e8d42da4c" const val BASE_QUERY_PARAMETERS = "?format=json&autocorrect=1&api_key=$API_KEY" }