2012-03-15 141 views
0

嗨,我有在Android的HTTP一個奇怪的問題。 我試圖從遠程服務器獲取圖片並將其顯示在設備上。 如果圖片是一個小的JPEG,這不是一個問題。但如果圖片變大,它將不起作用(只顯示部分圖片)。HTTP GET請求缺少數據

這裏是我完整的演示代碼:

public class HTTP_testActivity extends Activity { 

private ImageView ivPicture; 
private Button btGetImage; 


/** Called when the activity is first created. */ 
@Override 
public void onCreate(Bundle savedInstanceState) { 
    super.onCreate(savedInstanceState); 
    setContentView(R.layout.main); 

    ivPicture = (ImageView) findViewById(R.id.ivpiture1); 
    btGetImage = (Button) findViewById(R.id.btGetPicture1); 
    btGetImage.setOnClickListener(new Button.OnClickListener() 
    { 
     public void onClick(View arg0) 
     { 
      URI uri; 
      try { 


       uri = new URI(""); 
       URLConnection connection = uri.toURL().openConnection(); 
       connection.setUseCaches(true); 
       connection.connect(); 

       BufferedInputStream bis = new BufferedInputStream(connection.getInputStream()); 
       Log.d("TEST","Length of Input " +bis.available()); 
       try { 
        Thread.sleep(2000); 
       } catch (InterruptedException e) { 
        // TODO Auto-generated catch block 
        e.printStackTrace(); 
       } 
       Log.d("TEST","Length of Input after wait " +bis.available()); 
       byte[] data = new byte[640*480*5]; 
       bis.read(data); 
       Bitmap bmp = BitmapFactory.decodeByteArray(data, 0, jdata.length); 
       if (bmp != null) 
       { 
        ivPicture.setImageBitmap(bmp); 
       } 
       bis.close(); 
     } catch (URISyntaxException e) { 
      // TODO Auto-generated catch block 
      Log.d("TEST", e.getMessage()); 
      e.printStackTrace(); 
     } catch (MalformedURLException e) { 
      // TODO Auto-generated catch block 
      Log.d("TEST", e.getMessage()); 
      e.printStackTrace(); 
     } catch (IOException e) { 
      // TODO Auto-generated catch block 
      Log.d("TEST", e.getMessage()); 
      e.printStackTrace(); 
     } 
     } 
    }); 
} 

有人可以看到我在做什麼錯? 我已經想通了,到目前爲止是:bis.available()返回從來沒有超過65KB以上。儘管InputStream本身具有正確的長度(見調試器)。

+0

請不要在UI線程做網絡I/O。當服務器變得有點慢時,你的應用程序將被OS關閉。有很多關於如何在Andriod上異步處理網絡的教程。 – 2012-03-15 13:15:20

+0

如果你真正閱讀量雙報告爲可用,並bis.available()則報告說,更多的是可用?換句話說,你有沒有考慮過一段時間(bis.available()> 0)循環?除非事先知道所需的大小,否則可能需要稍微調整一下字節緩衝區,在這種情況下,您可以創建足夠大的緩衝區以便開始使用,並且只需使用隨每次讀取而前進的開始偏移量。 – JTeagle 2012-03-15 13:17:51

回答

0

可用()

將返回CON被從InputStream無阻塞讀的字節數。所以它會返回可以從網絡中讀取而不會阻塞的數據。

嘗試:

  InputStream bis = new InputStream(connection.getInputStream()); 
      Log.d("TEST","Length of Input " +bis.available()); 
      try { 
       Thread.sleep(2000); 
      } catch (InterruptedException e) { 
       // TODO Auto-generated catch block 
       e.printStackTrace(); 
      } 
      int read = 0; 
      byte[] buffer = new byte[SIZE_OF_IMAGE]; 
      byte[] inBuff = new byte[32678] 
      while ((read = bis.read(inBuff, 0, 32768)) > 0) { 
        // copy in buffer what have been read 
        // from the input stream 
      } 

      // close the is 
      Bitmap bmp = BitmapFactory.decodeByteArray(buffer, 0, buffer.length); 

顯然不存在這樣做更有效的方式,但可能是一個切入點。讓我知道你是否需要更多的幫助。

編輯:當然,你必須避免在UI線程做阻塞調用,如人提議。

+0

謝謝,我現在就試試。我知道封鎖用戶界面Tread是一個壞主意,但這只是一個概念驗證應用程序,以使文件檔案正常工作。之後它將被放入一個現有的應用程序中,當然 - 非阻塞。 – user1271544 2012-03-15 14:10:00

0

認爲您需要知道 bis.available()將始終返回小於65Kb,因爲Max IP數據包大小爲65535字節。的InputStream將返回總規模

正如你在實時數據陣列中的任何點只給了一個讀語句總是小於65KB。 (即第一個數據包的數據)

你可以做的是使用BitmapFactory.decodeStream(InputStream is)並給予的InputStream二是將讀取數據流中的所有字節,並給你的位圖

EDITED

使用本功能

這會給你所有字節從InputStream中

public static byte[] ReadToEOF(InputStream stream) throws Exception 
    { 
     try { 
      ByteArrayOutputStream array = new ByteArrayOutputStream(); 
      int read = 0; 
      byte[] receivedData = new byte[5000]; 
      while((read = stream.read(receivedData)) > 0) 
      { 
       array.write(receivedData, 0, read); 
       if(!(stream instanceof FileInputStream) && stream.available() == 0) 
       { 
        try { 
         Thread.sleep(1000); 
        } catch (Exception e) { 
         // TODO: handle exception 
        } 
        if(stream.available() == 0) 
         break; 
       } 
      } 
      return array.toByteArray(); 
     } catch (Exception e) { 
      // TODO: handle exception 
      throw e; 
     } 
    } 

了Thread.Sleep是因爲通過互聯網來獲取下一個數據包可以有一些延遲

+0

謝謝,但我不能解碼InpuStream,因爲在下一步我從我自己的服務器獲取YUV422圖片並對其進行解碼。但在我解碼之前,我需要在字節數組中的整個圖片。所以我用這個簡單的例子來證明我的問題。 – user1271544 2012-03-15 14:07:35

+0

查看我編輯的答案以獲取所有字節 – 2012-03-15 14:14:02

+0

在您的while循環中,您應該檢查表示文件結尾的「!= -1」。讀取可能會返回0字節,但流中仍有數據要讀取。 – dmux 2017-09-01 16:32:22