PC_android通信之傳輸圖片並顯示在手機端【轉】


 

從服務器 (PC 端 ) 發送圖片到客戶端 (android 手機端 ) ,並在手機頁面上顯示該圖片。(注:本文旨在實現功能,並未考慮效率,有待后續跟進。)

 

1、服務器端

Java代碼   
  1. int port=9090;  
  2.   
  3.   
  4. /** 
  5.  * 發送文件的方法 
  6.  * 此處定義服務器端口為9090,ip地址為192.168.1.1 
  7.  * 設定被傳輸圖片的路徑為"images/icon.png" 
  8.  * images文件夾放在此工程的根目錄下,我們就可以通過相對路徑訪問這個圖片文件了 
  9.  */  
  10.   
  11.   
  12. private void sendPic() {  
  13.   
  14.     try {  
  15.   
  16.         // 創建服務器  
  17.         java.net.ServerSocket ss = new java.net.ServerSocket(port);  
  18.         // 等待客戶機接入,此處會阻塞,直到有客戶機接入服務器  
  19.         java.net.Socket client = ss.accept();  
  20.         //創建將要被發送的圖片的文件輸入流  
  21.         java.io.FileInputStream fin = new java.io.FileInputStream("images/icon.png");  
  22.         //獲得套接字的輸出流,並包裝成數據輸出流  
  23.         java.io.DataOutputStream dou = new java.io.DataOutputStream(client  
  24.                 .getOutputStream());  
  25.         // 向輸出流中寫入文件數據長度  
  26.         dou.writeInt(fin.available());//注:此處未考慮圖片太大超出int范圍,以至於出現內存溢出的情況       
  27.         // 將實際的圖片數據讀取到byte[] data中  
  28.         byte[] data = new byte[fin.available()];  
  29.         fin.read(data);  
  30.         // 將圖片數據寫入到輸出流中  
  31.         dou.write(data);  
  32.         dou.flush();  
  33.     } catch (IOException e) {  
  34.         e.printStackTrace();  
  35.     }  
  36.   
  37.   
  38. }  

 

 

2 、 客戶端(android手機)

Java代碼   
  1. public class FrontPage extends android.app.Activity implements Runnable {  
  2.   
  3.     public void onCreate(android.os.Bundle savedInstanceState) {  
  4.   
  5.         super.onCreate(savedInstanceState);  
  6.         setContentView(R.layout.frontpage);  
  7.   
  8.         // 啟動讀取套接字中數據並進行處理的線程  
  9.                 new Thread(this).start();// 本類繼承了Runnable接口,所以創建線程時將本類的對象傳入即可  
  10.     }  
  11.   
  12.     String ip = "192.168.1.1";  
  13.     int port = 9090;  
  14.     android.widget.ImageView image;// 用於顯示接收到的圖片的ImageView對象  
  15.   
  16.     /** 
  17.      * 由於輸入流的read方法會阻塞,為了避免它影響主界面的其他數據處理, 啟動一個線程來讀取輸入流中的數據,並對數據進行相應的處理 
  18.      */  
  19.     public void run() {  
  20.   
  21.         try {  
  22.             // 創建與服務器的連結  
  23.             java.net.Socket sc = new java.net.Socket(ip, port);  
  24.             // 獲得界面顯示圖片的ImageView對象  
  25.             image = (android.widget.ImageView) findViewById(R.id.image);  
  26.             // 獲得套接字的輸入流並包裝成基本數據輸入流  
  27.             java.io.DataInputStream din = new java.io.DataInputStream(sc  
  28.                     .getInputStream());  
  29.   
  30.             // 不斷監聽輸入流的數據情況  
  31.             while (true) {  
  32.                 // 當流中有數據時,讀取數據並進行處理  
  33.                 if (din.available() > 0) {  
  34.   
  35.                     // 創建data數組並將流中數據讀取到數組中  
  36.                     byte[] data = new byte[din.readInt()];// 注此處同樣沒有處理圖片大小超過int的范圍的情況  
  37.                     din.read(data);  
  38.   
  39.                     // 根據讀到的文件數據創建Bitmap對象bitmap,因為將要在后面的內部類中使用bitmap,所以定義為  
  40.                     // final型  
  41.                     final android.graphics.Bitmap bitmap = android.graphics.BitmapFactory  
  42.                             .decodeByteArray(data, 0, data.length);  
  43.   
  44.                     // 將圖片顯示到ImageView上  
  45.                     // 此處由於view中的組件都是線程不安全的,使用android提供的這個辦法處理(詳見下文“附2”)  
  46.                     image.post(new Runnable() {  
  47.   
  48.                         public void run() {  
  49.                             // 將bitmap顯示到界面上  
  50.                                image.setImageBitmap(bitmap);  
  51.                         }  
  52.                     });  
  53.                 }  
  54.   
  55.                 // 線程休息1s  
  56.                 Thread.sleep(1000);  
  57.             }  
  58.   
  59.         } catch (Exception e) {  
  60.             e.printStackTrace();  
  61.         }  
  62.     }  
  63.   
  64. }  

 

 

3、main.xml

Xml代碼   
  1. <?xml version="1.0" encoding="utf-8"?>  
  2. <LinearLayout android:orientation="vertical"  
  3.               android:layout_width="fill_parent"   
  4.               android:layout_height="fill_parent"  
  5.               xmlns:android1="http://schemas.android.com/apk/res/android"  
  6.               xmlns:android="http://schemas.android.com/apk/res/android">  
  7.     <ImageView android:layout_width="wrap_content"  
  8.               android:layout_height="wrap_content"   
  9.               android:id="@+id/image"  
  10.               android:gravity="center" />                
  11. </LinearLayout>  

 

附1 、android做通信時需要在AndroidMainFest中添加一個permission:

Java代碼   
  1. <uses-permission android:name="android.permission.INTERNET"></uses-permission>  

 

 

 

附2 、關於android中view的組件線程不安全,已經有很多前輩對此做了詳盡的分析,在此我就不再贅述,只給大家提供一個可供參考的地址:http://www.cnblogs.com/playing/archive/2011/03/24/1993583.html

 

 

 

附3 、發送和接收數據時,有很多種方法可選,此處使用的byte數組方法有幾點需要注意:

       a、new byte[]時,傳入的數組大小是int型的,所以我們必須考慮到當文件數據超出整型的范圍時,需要輔以別的方法來保證數據的完整性。

       b、從文件讀取數據,並寫入到輸出流時,文中使用的代碼是:

Java代碼   
  1. byte[] data = new byte[fin.available()];//創建用於存放文件數據數組  
  2.   
  3. fin.read(data);//將文件數據讀取到數組中  
  4.   
  5. dou.write(data);// 將數組寫入到輸出流中  

      可是不乏有偷懶的碼友這樣寫:

Java代碼   
  1. dou.write(fin.read(new byte[fin.available()]));  
  2.   
  3. //只要我們稍微查看一下JDK就會發現:read()如果因為已經到達文件末尾而沒有更多的數據,則返回 <code>-1,這樣一來寫入到輸出流中的可就不是我們的文件數據了哦!</code>  

      更有甚者會這樣寫:

Java代碼  
  1. dou.write(new byte[fin.available()]);//根本就沒有將文件數據讀入到數組中  

 

以上幾種錯誤都是我自己遇到過的,這類很細節的問題要檢查出來都會比較費時間,希望各位碼友引以為戒!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM