2015-09-28 8 views
6

Ho un po 'di codice usando la nuova classe Palette e sto ricevendo questi rapporti di arresto anomalo su Crashlytics dicendo che il width and height must be > 0. Ciò che è strano è che questo è il modo che io chiamo il codice palette:android.support.v7.graphics.Palette width and height deve essere> 0

if(bitmap == null || bitmap.getHeight() <= 0 || bitmap.getWidth() <= 0){ 
    //do something 
}else{ 
    Palette.Builder(bitmap).generate(new Palette.PaletteAsyncListener() { 
..... 
} 

, quindi sono solo non è sicuro come sia possibile che la bitmap tutto ad un tratto non ha la giusta altezza o larghezza. Non so da quale parte del mio codice provenga l'eccezione perché il report include solo elementi all'interno della classe della palette.

Qui è l'eccezione:

java.lang.RuntimeException: An error occured while executing doInBackground() 
     at android.os.AsyncTask$3.done(AsyncTask.java:300) 
     at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:355) 
     at java.util.concurrent.FutureTask.setException(FutureTask.java:222) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
     at java.lang.Thread.run(Thread.java:818) 
Caused by: java.lang.IllegalArgumentException: width and height must be > 0 
     at android.graphics.Bitmap.createBitmap(Bitmap.java:815) 
     at android.graphics.Bitmap.createBitmap(Bitmap.java:794) 
     at android.graphics.Bitmap.createBitmap(Bitmap.java:725) 
     at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:601) 
     at android.support.v7.graphics.Palette.scaleBitmapDown(Palette.java:282) 
     at android.support.v7.graphics.Palette.access$100(Palette.java:67) 
     at android.support.v7.graphics.Palette$Builder.generate(Palette.java:557) 
     at android.support.v7.graphics.Palette$Builder$1.doInBackground(Palette.java:623) 
     at android.support.v7.graphics.Palette$Builder$1.doInBackground(Palette.java:620) 
     at android.os.AsyncTask$2.call(AsyncTask.java:288) 
     at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
     at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112) 
     at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587) 
     at java.lang.Thread.run(Thread.java:818) 

Sto usando la classe tavolozza da com.android.support:palette-v7:23+

Tutte le idee su quello che potrebbe essere sbagliato?

+0

sei davvero sicuro che la bitmap abbia qualcosa o addirittura lo mostri? la palette deve analizzare l'immagine e pochi ms dopo, otterrai il colore. –

+0

Beh, ho solo gli errori su Crashlytics, non mi succede mai. Ma sto controllando per null e dimensioni prima di chiamare il codice della palette. – casolorz

+0

l'app non si arresta mai in modo anomalo? potresti ricreare il problema? in caso contrario ... forse alcuni utenti hanno uno smartphone di fascia bassa e l'attività ha richiesto troppo tempo e la tavolozza ha trovato valori nulli (crash sopra la tavolozza e non sopra la bitmap) –

risposta

0

Probabilmente stai provando ad accedere alla larghezza e all'altezza dell'elemento dell'interfaccia utente prima che sia stato effettivamente aggiunto al layout.

Ecco perché hai ottenuto la larghezza e l'altezza è uguale a 0, poiché l'elemento non è effettivamente lì.

Utilizzare un ViewTreeObserver http://developer.android.com/reference/android/view/ViewTreeObserver.html

myView.getViewTreeObserver().addOnPreDrawListener(
      new ViewTreeObserver.OnPreDrawListener() { 
       public boolean onPreDraw() { 

         int finalHeight = myView.getMeasuredHeight(); 
         int finalWidth = myView.getMeasuredWidth(); 
         // Do your work here 


        return true; 
       } 
      }); 

dove il myView sarebbe la vostra bitmap

+0

Non sto cercando di accedervi, la classe 'Palette' è. E sto controllando per larghezza e altezza e null prima di chiamare la classe 'Palette'. Non riesco a cambiare il codice 'Palette', quindi come posso assicurarmi che questo non accada? – casolorz

+0

Chiamare la classe Tavolozza all'interno di TreeObserver. In questo modo la bitmap viene definita prima che la classe della palette tenti di accedervi. –

+0

In realtà non ho viste su cui sono state caricate queste immagini bitmap prima di chiamare il codice della palette. Li carico nelle viste dopo aver conosciuto il colore della tavolozza. Questo funziona bene per la maggior parte dei miei utenti, ottenendo solo 4 o 5 arresti anomali al giorno su 20k utenti giornalieri. – casolorz

0

Non credo che il codice ha alcun problema. Stavo guardando lo StackTrace che hai postato.

at android.graphics.Bitmap.createScaledBitmap(Bitmap.java:601) 
at android.support.v7.graphics.Palette.scaleBitmapDown(Palette.java:282) 

Se si guarda il codice sorgente di Palette.java, si trova la logica di scala scritta in modo scaleBitmapDown(Bitmap bitmap). Se la 'bitmap' è inferiore a 100px, non viene eseguito alcun ridimensionamento. Tuttavia se il tuo 'bitmap' è più grande di 100px, viene chiamato Bitmap.createScaledBitmap(). Ora questo metodo genera lo IllegalArgumentException se larghezza o altezza < 0;

Quindi la bitmap che si sta passando non ha una larghezza zero, perché se così fosse, non avresti mai raggiunto il metodo Bitmap.createScaledBitmap(). Detto questo, non sono sicuro di quale potrebbe essere la vera ragione. Prova a leggere il codice sorgente dell'esatto numero Palette.java che stai utilizzando.

+0

Il codice per la palette che Android Studio mi fornisce quando faccio clic sullo stacktrack incollato è leggermente diverso ma ha gli stessi controlli visualizzati. Immagino che se fosse successo qualcosa alla bitmap tra il controllo e il ridimensionamento sarebbe l'unica possibilità. – casolorz

+0

Anche la mia ipotesi. L'arresto si verifica in qualche particolare dispositivo, in una versione particolare? Se questo è il caso, probabilmente il codice di versione del sistema operativo ha il bug. Ma in ogni caso, non penso che tu faccia nulla a riguardo. – Henry

0

Il problema è legato a un problema di concorrenza: dal momento che si sta utilizzando il Palette nel modo 'async', quando si richiama

Palette.Builder(bitmap).generate(new Palette.PaletteAsyncListener() 

bitmap è valido, ma quando il Palette utilizza il bitmap la sua logica asincrona, la bitmap potrebbe essere null o non più valida (a causa di una manipolazione simultanea).

C'è una soluzione semplice per questo problema: dal momento che non c'è bisogno di un'immagine ad alta risoluzione per estrarre i colori chiave, basta fornire una bitmap a bassa risoluzione creato dal vostro originale:

if(bitmap == null || bitmap.getHeight() <= 0 || bitmap.getWidth() <= 0){ 
    //do something 
}else{ 
    //This resized bitmap is just an example: you should keep your bitmap 
    //aspect ratio, and keep width and height < 100 
    Bitmap resizedBitmap = Bitmap.createScaledBitmap(myBitmap, 100, 100, false); 
    Palette.Builder(resizedBitmap).generate(new Palette.PaletteAsyncListener() { 
..... 
} 
+0

Idea interessante, ci proverò. Grazie. – casolorz

+0

@mntgoat Non dimenticare di mantenere le proporzioni nella bitmap ridimensionata, oppure potresti ottenere colori chiave errati (sto forzando 100x100px nell'esempio) – bonnyz

+0

Sì, lo sono. Il codice che sto effettivamente vedendo per la classe Palette usa 192 come minimo. – casolorz

Problemi correlati