0

Je suis assez nouveau sur Android et faire une application qui nécessite un jpg d'une URL à télécharger et mis en cache pour l'utilisation.Problème OutputStream ... OutofBoundsException

J'ai jusqu'à présent de multiples références (et moi-même bricoler) obtenu à ceci:

public class download_image extends AsyncTask<String, Void, String> { 
    int count; 
    @Override 
    protected String doInBackground(String... urls) { 
     try { 
      String root = getFilesDir().toString(); 
      URL imgurl = new URL(urls[0]); // Form a URL object from string. 
      URLConnection c = imgurl.openConnection(); //Open connection. 
      int length_of_file = c.getContentLength();  // Get size of target jpg 
      Log.v("Background Response","Length fo target img = "+length_of_file); 
      InputStream i = new BufferedInputStream(imgurl.openStream(),length_of_file); 

      //Make target image file... 
      final File image = new File(getApplicationContext().getCacheDir().toString(),"image.jpg"); 

      OutputStream o = new FileOutputStream(image); 
      byte data[] = new byte[length_of_file]; 
      long total = 0; 
      while ((count = i.read(data))!=1){ 
       total+=count; 
       o.write(data,0,count); 
      } 

      o.flush(); 
      o.close(); 
      i.close(); 

     } catch (MalformedURLException m) { 
      Log.e("Exception", m.toString()); 
     } catch (IOException i) { 
      Log.e("Exception", i.toString()); 
     } 

     return null; 
    } 

    @Override 
    protected void onPostExecute(String s) { 
     System.out.println("Downloaded"); 
     super.onPostExecute(s); 
    } 

    @Override 
    protected void onPreExecute() { 
     super.onPreExecute(); 
    } 
} 

Le problème semble être que les données du tableau [] sur les flux ou quelque chose? Je ne peux pas tout à fait comprendre. J'ai essayé de faire le tampon d'InputStream égal à la taille de fichier de length_of_file = getContentLength();

Toute aide serait grandement appréciée! J'ai déjà été assez satisfait d'autres problèmes (comme obtenir le dossier interne à écrire et quelle est la tâche asynchrone ... que je ne savais pas à l'origine pour HTTPConnections).

08-04 15:51:22.938 13454-13486/com.example.johnny.fibre V/Background Response: Length fo target img = 106620 
08-04 15:51:23.058 13454-13486/com.example.johnny.fibre E/AndroidRuntime: FATAL EXCEPTION: AsyncTask #2 
                      Process: com.example.johnny.fibre, PID: 13454 
                      java.lang.RuntimeException: An error occurred while executing doInBackground() 
                       at android.os.AsyncTask$3.done(AsyncTask.java:325) 
                       at java.util.concurrent.FutureTask.finishCompletion(FutureTask.java:354) 
                       at java.util.concurrent.FutureTask.setException(FutureTask.java:223) 
                       at java.util.concurrent.FutureTask.run(FutureTask.java:242) 
                       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243) 
                       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133) 
                       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607) 
                       at java.lang.Thread.run(Thread.java:761) 
                      Caused by: java.lang.ArrayIndexOutOfBoundsException: length=106620; regionStart=0; regionLength=-1 
                       at java.util.Arrays.checkOffsetAndCount(Arrays.java:4857) 
                       at libcore.io.IoBridge.write(IoBridge.java:490) 
                       at java.io.FileOutputStream.write(FileOutputStream.java:316) 
                       at com.example.johnny.fibre.Home$download_image.doInBackground(Home.java:476) 
                       at com.example.johnny.fibre.Home$download_image.doInBackground(Home.java:456) 
                       at android.os.AsyncTask$2.call(AsyncTask.java:305) 
                       at java.util.concurrent.FutureTask.run(FutureTask.java:237) 
                       at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:243)  
                       at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1133)  
                       at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:607)  
                       at java.lang.Thread.run(Thread.java:761)  

Répondre

0

getContentLength() renvoie le length of the content header, et non la taille de l'image que vous téléchargez. Dans ce cas, il est très probable que vous allouer un tableau qui n'est pas assez grand pour correspondre à l'image que vous avez l'intention d'écrire!

Au lieu d'attribuer un tableau byte, pourquoi diffuser pas les données que vous lisez dans un ByteArrayOutputStream, et aller chercher le résultat en appelant getBytes() sur le flux une fois que vous avez terminé?

En faisant cela, vous n'aurez pas besoin de connaître la longueur de l'image; tout ce que vous devez faire est de continuer à lire les données jusqu'à ce que vous atteigniez la fin du InputStream.

Click here for an example of how to use a ByteArrayOutputStream. En guise d'alternative, vous voudrez peut-être profiter de certains helper utilities intégrés au moteur d'exécution Android, spécialement conçus pour extraire des données d'image à partir d'une URL.

+0

Merci. Je vais regarder dans le ByteArrayOutputStream et retourner si j'ai des problèmes. Je veux mettre en cache les images pour une utilisation future plutôt que d'avoir à utiliser une prise Internet active chaque fois que j'ai besoin d'une image ... donc les utilitaires Helper semblent être hors. – Jcov

+0

Si vous utilisez les utilitaires auxiliaires que j'ai référencés, vous pouvez effectuer l'appel en ligne une fois lors de l'initialisation ou au besoin, puis stocker une référence à l'image dans un modèle local afin de ne plus avoir à interroger le réseau. –