2012-11-30 12 views
11

Si consideri lo scenario come in questa immagine:MediaStore.Images.Thumbnails.getThumbnail torna miniature sbagliato, invece di NULL

Native Galery

tre foto, uno di loro è un grande file GIF (3MP).

Sto interrogando MediaStore per recuperare le miniature corrispondenti. Se io inizializzare il cursore tramite CursorLoader con questo sortOrder:

MediaStore.Images.Media.DATE_ADDED + " DESC"" 

Cosa succede: MediaStore restituisce il precedente miniature recuperato correttamente:

DESC

Comportamento previsto: quando MediaStore non può recuperare il miniatura di una determinata immagine per qualche motivo deve restituire NULL, come per il suo Javadoc: "... Restituisce un'istanza Bitmap. Potrebbe essere nullo se il culo immagine originale ociate con origId non esiste o la memoria non è sufficiente. "

Se io inizializzare il cursore con questo sortOrder:

MediaStore.Images.Media.DATE_ADDED + " ASC"" 

Si corre bene:

ASC

Tuttavia non posso semplicemente cambiare la sortOrder poiché il requisito è quello di mostrare prima le nuove foto

Di seguito è il mio codice di esempio e here is the complete sample project nonché the three images used to reproduce.

package com.example.getimagefrommediastore; 

import android.app.Activity; 
import android.database.Cursor; 
import android.graphics.Bitmap; 
import android.os.Bundle; 
import android.provider.MediaStore; 
import android.support.v4.content.CursorLoader; 
import android.widget.ImageView; 
import android.widget.TextView; 

public class GetThumbnailsFromMediaStoreSampleActivity extends Activity { 

TextView mThumb_id_01; 
TextView mThumb_id_02; 
TextView mThumb_id_03; 
ImageView mImg_01; 
ImageView mImg_02; 
ImageView mImg_03; 
boolean isThumb01 = true; // Simple flag to control this example 
boolean isThumb02 = true; 
Cursor mCursorLoader; 
int mColumnIndex; 
long mOrigId; // Original image id associated with thumbnail of interest 

@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.activity_main); 

    // Just initializing views 
    mThumb_id_01 = (TextView) findViewById(R.id.thumb_id_01); 
    mThumb_id_02 = (TextView) findViewById(R.id.thumb_id_02); 
    mThumb_id_03 = (TextView) findViewById(R.id.thumb_id_03); 
    mImg_01 = (ImageView) findViewById(R.id.thumb_01); 
    mImg_02 = (ImageView) findViewById(R.id.thumb_02); 
    mImg_03 = (ImageView) findViewById(R.id.thumb_03); 

    // Initializing CursorLoader 
    mCursorLoader = initializeCursorLoader(); 
    mColumnIndex = mCursorLoader.getColumnIndex(MediaStore.Images.Media._ID); 

    // Go thru all the images in the device (EXTERNAL_CONTENT_URI) 
    // In this example there are only three images 
    for (int i = 0; i < mCursorLoader.getCount(); i++) { 
     mCursorLoader.moveToPosition(i); 
     mOrigId = mCursorLoader.getInt(mColumnIndex); 

     // Update views 
     chooseViewToUpdate(); 
    } 
} 

private Cursor initializeCursorLoader() { 
    String[] COLUMNS = { 
      MediaStore.Images.Thumbnails._ID, MediaStore.Images.Media.DATA 
    }; 

    CursorLoader cursorLoader = new CursorLoader(
    GetThumbnailsFromMediaStoreSampleActivity.this, // Context 
    MediaStore.Images.Media.EXTERNAL_CONTENT_URI, // Uri 
    COLUMNS, // Projection 
    null, // Selection 
    null, // Selection Args 

    // Sort Order: DESC = newest first 
    // Sort Order: ASC = oldest first 

    MediaStore.Images.Media.DATE_ADDED + " DESC"); 

    // *** NOTE *** 
    // With: 
    // 
    // MediaStore.Images.Media.DATE_ADDED + " ASC" 
    // 
    // It runs just fine (MediaStore returns 'null' for invalid thumbnails) 
    // The problem seems to reside on the " DESC" tag. 
    // 
    // How bizarre is that? 

    return cursorLoader.loadInBackground(); 
} 

private void chooseViewToUpdate() { 
    if (isThumb01) { 
     updateUI(mThumb_id_01, mImg_01); 
     isThumb01 = false; 
    } else if (isThumb02) { 
     updateUI(mThumb_id_02, mImg_02); 
     isThumb02 = false; 
    } else { 
     updateUI(mThumb_id_03, mImg_03); 
    } 
} 

private void updateUI(TextView textView, ImageView imgView) { 
    textView.setText("ID:" + String.valueOf(mOrigId)); 

    Bitmap mediaStoreThumbmail = MediaStore.Images.Thumbnails.getThumbnail(
      this.getContentResolver(), 
      mOrigId, 
      MediaStore.Images.Thumbnails.MICRO_KIND, null); 

    if (mediaStoreThumbmail != null) { 
     imgView.setImageBitmap(mediaStoreThumbmail); 
    } 
} 

Mi manca qualcosa? Qualcuno ha un'idea di cosa potrebbe essere sbagliato?

I filled a bug against Android anyway.

EDIT

Sembra che questo problema è fixed in Lollipop. (l'ultimo commento su quel thread).

+0

Stampa il 'mOrigId' per ogni immagine che si ottiene, potrebbe essere lo stesso per le immagini 2 e 3. O c'è una 4a immagine che sovrascrive i dati. Ci sono diversi motivi nel tuo codice che potrebbero causare un simile errore. Tanto più che ottieni l'ID immagine nella tua query ASC/DESC, quindi risolvi l'immagine in una seconda query non correlata. – zapl

+0

Ciao! Nella seconda immagine (il mio secondo link - http://cl.ly/image/2U0z1Z2b1m1v) ho messo gli ID sopra le immagini. Sono diversi: 7858, 7854 e 7851. Non sono sicuro di cosa intendi per "Specialmente dal momento che ottieni l'ID immagine nella tua query ASC/DESC, quindi risolvi l'immagine in una seconda query non correlata." Grazie per dare un'occhiata. –

+1

Ho hackerato insieme un piccolo esempio ASC/DESC che funziona perfettamente per me (emulatore 4.0.3). https://www.dropbox.com/s/in048v3fh3xae2m/AscDescGallery.zip - "Soprattutto ..." significa: in un primo passaggio si esegue una query su un elenco di immagini dal mediastore. O ASC o DESC. Quindi chiedi a MediaStore le miniature, in una query indipendente che non sa/cura di come hai ottenuto gli id. Pertanto, la modifica dell'ordine nella prima query non dovrebbe avere alcun impatto sul risultato di "Thumbnails.getThumbnail" a condizione che vengano utilizzati gli ID corretti. – zapl

risposta

0

dopo tre anni, sembra che questo problema is fixed in Lollipop . (L'ultimo commento su quel thread).
Pertanto sto rispondendo alla mia stessa domanda.

2

I "m solo indovinare qui. Quando si chiede per il MICRO_KIND il sistema operativo è la creazione di una nuova immagine che ottiene il prossimo in linea sul cursore DESC produrre di nuovo la stessa immagine.

Un lavoro intorno è quello di caricare un ArrayList . per l'immagine id Quindi per andare dopo le miniature lavorativi dalla ArrayList

Possibilità provare il codice utilizzando la MINI_KIND e bmoptions.inSampleSize = 2;.

final BitmapFactory.Options bmOptions = new BitmapFactory.Options(); 
      bmOptions.inSampleSize =2; 



        Bitmap bm = MediaStore.Images.Thumbnails.getThumbnail(
          context.getContentResolver(), newImageId, 
          MediaStore.Images.Thumbnails.MINI_KIND, 
          bmOptions); 
Problemi correlati