• 从服务器 (PC 端 ) 发送图片到客户端 (android 手机端 ) [转]


    从服务器 (PC 端 ) 发送图片到客户端 (android 手机端 ) ,并在手机页面上显示该图片。(注:本文旨在实现功能,并未考虑效率,有待后续跟进。)

    1、服务器端

     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手机)

     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

     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()]);//根本就没有将文件数据读入到数组中  

    以上几种错误都是我自己遇到过的,这类很细节的问题要检查出来都会比较费时间,希望各位码友引以为戒!

  • 相关阅读:
    A Simple Problem with Integers poj 3468 多树状数组解决区间修改问题。
    Fliptile 开关问题 poj 3279
    Face The Right Way 一道不错的尺取法和标记法题目。 poj 3276
    Aggressive cows 二分不仅仅是查找
    Cable master(二分题 注意精度)
    B. Pasha and String
    Intervals poj 1201 差分约束系统
    UITextField的快速基本使用代码块
    将UIImage转换成圆形图片image
    color转成image对象
  • 原文地址:https://www.cnblogs.com/zhouwenJS/p/3732212.html
Copyright © 2020-2023  润新知