"No se pueden dibujar mapas de bits reciclados" con Picasso

Tengo aplicación de reproductor de música que interactúa con RemoteControlClient. Necesito cargar la imagen de portada del álbum para mostrarla en el widget de pantalla de bloqueo. Trato de usar Piccasso para lograr esto. He escrito el siguiente código:

private final Target artworkTarget = new Target() { @Override public void onBitmapLoaded(Bitmap bitmap, Picasso.LoadedFrom loadedFrom) { remoteControlClient.editMetadata(false).putBitmap(RemoteControlClientCompat.MetadataEditorCompat.METADATA_KEY_ARTWORK, bitmap).apply(); } @Override public void onBitmapFailed(Drawable drawable) { Log.e(Constants.LOG_TAG, "Artwork loading failed"); } @Override public void onPrepareLoad(Drawable drawable) { } }; ... private void playNextSong(int songPosition) { ... String artworkUrl = Constants.Urls.BASE_ARTWORK_URL + currentSong.getArtworkId(); Picasso.with(this).load(artworkUrl).skipMemoryCache().into(artworkTarget); // Update the remote controls remoteControlClient.editMetadata(true) .putString(MediaMetadataRetriever.METADATA_KEY_ARTIST, currentSong.getArtist().getName()) .putString(MediaMetadataRetriever.METADATA_KEY_ALBUM, currentSong.getAlbum().getName()) .putString(MediaMetadataRetriever.METADATA_KEY_TITLE, currentSong.getName()) .apply(); ... } 

Pero a veces tengo excepción:

  ERROR/AndroidRuntime(31121): FATAL EXCEPTION: main java.lang.IllegalArgumentException: Cannot draw recycled bitmaps at android.view.GLES20Canvas.drawBitmap(GLES20Canvas.java:772) at android.view.GLES20RecordingCanvas.drawBitmap(GLES20RecordingCanvas.java:105) at android.graphics.drawable.BitmapDrawable.draw(BitmapDrawable.java:440) at com.squareup.picasso.PicassoDrawable.draw(PicassoDrawable.java:96) at android.widget.ImageView.onDraw(ImageView.java:1025) at android.view.View.draw(View.java:13944) at android.view.View.getDisplayList(View.java:12838) at android.view.View.getDisplayList(View.java:12880) at android.view.View.draw(View.java:13657) at android.view.ViewGroup.drawChild(ViewGroup.java:3083) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2920) at android.view.View.getDisplayList(View.java:12833) at android.view.View.getDisplayList(View.java:12880) at android.view.View.draw(View.java:13657) at android.view.ViewGroup.drawChild(ViewGroup.java:3083) at android.widget.ListView.drawChild(ListView.java:3331) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2920) at android.widget.AbsListView.dispatchDraw(AbsListView.java:2357) at android.widget.ListView.dispatchDraw(ListView.java:3326) at android.view.View.draw(View.java:13947) at android.widget.AbsListView.draw(AbsListView.java:3693) at android.view.View.getDisplayList(View.java:12838) at android.view.View.getDisplayList(View.java:12880) at android.view.View.draw(View.java:13657) at android.view.ViewGroup.drawChild(ViewGroup.java:3083) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2920) at android.view.View.getDisplayList(View.java:12833) at android.view.View.getDisplayList(View.java:12880) at android.view.View.draw(View.java:13657) at android.view.ViewGroup.drawChild(ViewGroup.java:3083) at android.view.ViewGroup.dispatchDraw(ViewGroup.java:2920) at android.view.View.getDisplayList(View.java:12833) at android.view.View.getDisplayList(View.java:12880) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3057) at android.view.View.getDisplayList(View.java:12775) at android.view.View.getDisplayList(View.java:12880) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3057) at android.view.View.getDisplayList(View.java:12775) at android.view.View.getDisplayList(View.java:12880) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3057) at android.view.View.getDisplayList(View.java:12775) at android.view.View.getDisplayList(View.java:12880) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3057) at android.view.View.getDisplayList(View.java:12775) at android.view.View.getDisplayList(View.java:12880) at android.view.ViewGroup.dispatchGetDisplayList(ViewGroup.java:3057) at android.view.View.getDisplayList(View.java:12775) at android.view.View.getDisplayList(View.java:12880) at android.view.HardwareRenderer$GlRenderer.buildDisplayList(HardwareRenderer.java:1411) at android.view.HardwareRenderer$GlRenderer.draw(HardwareRenderer.java:1359) at android.view.ViewRootImpl.draw(ViewRootImpl.java:2367) at android.view.ViewRootImpl.performDraw(ViewRootImpl.java:2239) at android.view.ViewRootImpl.performTraversals(ViewRootImpl.java:1872) at android.view.ViewRootImpl.doTraversal(ViewRootImpl.java:1004) at android.view.ViewRootImpl$TraversalRunnable.run(ViewRootImpl.java:5481) at android.view.Choreographer$CallbackRecord.run(Choreographer.java:749) at android.view.Choreographer.doCallbacks(Choreographer.java:562) at android.view.Choreographer.doFrame(Choreographer.java:532) at android.view.Choreographer$FrameDisplayEventReceiver.run(Choreographer.java:735) at android.os.Handler.handleCallback(Handler.java:730) at android.os.Handler.dispatchMessage(Handler.java:92) at android.os.Looper.loop(Looper.java:137) at android.app.ActivityThread.main(ActivityThread.java:5103) at java.lang.reflect.Method.invokeNative(Native Method) at java.lang.reflect.Method.invoke(Method.java:525) at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java: 

He intentado guardar la referencia cargada del mapa de bits en mi servicio, pero no ayudó.
¿Alguien tiene idea de lo que está mal con mi código?
Gracias por adelantado.

Supongo que estás usando un dispositivo Android 4.3 o más reciente. La implementación RemoteControlClient de 4.3 hace un reciclado en la ilustración bajo ciertas condiciones. Ver

http://androidxref.com/4.3_r2.1/xref/frameworks/base/media/java/android/media/RemoteControlClient.java#556

Usted esencialmente tiene que hacer una copia del mapa de bits que si Build.VERSION.SDK_INT> = 18.

En sus onDestory() o onDestroyView() intente llamar a Picasso.with(Context).cancelRequest(Target);

Crédito a los chicos aquí: https://github.com/square/picasso/issues/38

Para mí la solución fue llamar unregisterRemoteControlClient para el RemoteControlClient existente, y crear uno nuevo cada vez para reproducir una nueva canción. El problema se produjo cuando el usuario intenta reproducir dos veces la misma canción, con la misma imagen de portada, por supuesto.

El fragmento que resuelve el problema es:

 if(mRemoteControlClientCompat!=null){ RemoteControlHelper.unregisterRemoteControlClient(mAudioManager, mRemoteControlClientCompat); } Intent intent = new Intent(Intent.ACTION_MEDIA_BUTTON); intent.setComponent(mMediaButtonReceiverComponent); mRemoteControlClientCompat = new RemoteControlClientCompat(PendingIntent.getBroadcast(PlayerService.this, 0, intent, 0)); RemoteControlHelper.registerRemoteControlClient(mAudioManager, mRemoteControlClientCompat); 
  • Android borrar algunas fotos de caché Picasso
  • ¿Cómo implementar Pinch Zoom en la biblioteca de Picasso?
  • ¿No soporta Picasso para descargar imágenes que utilizan el protocolo https
  • Cómo cargar un mapa de bits en una vista de imagen con Picasso
  • Adición de marcadores de url con Picasso
  • Descargar y guardar imágenes con Picasso
  • Descargar múltiples imágenes de Picasso en Android
  • Acercamiento a las imágenes de Android en DB
  • Picasso image loading library: cómo cargar miniaturas de video
  • Cómo borrar la caché de imágenes de Picasso
  • Fade in animation while loading image Uso de Picasso
  • FlipAndroid es un fan de Google para Android, Todo sobre Android Phones, Android Wear, Android Dev y Aplicaciones para Android Aplicaciones.