【Android基础】二、网络编程

原创 2016年05月31日 10:59:43

1、从网络中下载图片,使用HttpURLConnection进行访问网络的操作

2.访问网络的操作不能放在主线程中,开一个子线程通过发送消息到UI线程,在UI线程修改界面

Handler handler = new Handler(){
        @Override
        public void handleMessage(Message msg) {
            super.handleMessage(msg);
            switch (msg.what){
                case 0:
                    Toast.makeText(ImageActivity.this, "请求失败", Toast.LENGTH_SHORT).show();
                    break;
                case 1:
                    ImageView imageView = (ImageView) findViewById(R.id.iv_pic);
                    //把位图对象显示在ImageView
                    imageView.setImageBitmap((Bitmap) msg.obj);
                    break;
                default:
                    break;
            }
        }
    };
public void download(View v) {
        new Thread(new Runnable() {
            @Override
            public void run() {
                //1.确定网址
                String path = "http://192.168.56.1:8080/pic.jpg";
                try {
                    //2.把网址封装成一个URL对象
                    URL url = new URL(path);
                    //3.获取客户端和服务端的连接对象,此时还没有建立连接
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    //4.对连接对象进行初始化,设置请求方法,连接超时,读取超时
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);
                    //5.发送请求,与服务端建立连接
                    conn.connect();
                    //如果响应码为200,说明连接成功
                    if (conn.getResponseCode() == 200) {
                        //获取服务器响应头中的流,流的数据就是客户端请求的数据
                        InputStream is = conn.getInputStream();
                        //使用位图工厂对象从将流里的数据读取出来构造成位图对象
                        Bitmap bitmap = BitmapFactory.decodeStream(is);
                        Message msg = new Message();
                        msg.obj = bitmap;
                        msg.what = 1;
                        handler.sendMessage(msg);
                    } else {
                        Message msg = Message.obtain();
                        msg.what = 0;
                        handler.sendMessage(msg);
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }).start();

    }

3.图片缓存到本地,直接从本地读取
BtmapFactory对象直接从File中解压位图对象,参数为File文件的绝对路径

public void download(View v) {
        //1.确定网址
        final String path = "http://192.168.56.1:8080/pic.jpg";
        final File file = new File(getCacheDir(), "pic.jpg");
        if (file.exists()) {
            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
            imageView.setImageBitmap(bitmap);
        } else {
            new Thread(new Runnable() {
                @Override
                public void run() {

                    try {
                        //2.把网址封装成一个URL对象
                        URL url = new URL(path);
                        //3.获取客户端和服务端的连接对象,此时还没有建立连接
                        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                        //4.对连接对象进行初始化,设置请求方法,连接超时,读取超时
                        conn.setRequestMethod("GET");
                        conn.setConnectTimeout(5000);
                        conn.setReadTimeout(5000);
                        //5.发送请求,与服务端建立连接
                        conn.connect();
                        //如果响应码为200,说明连接成功
                        if (conn.getResponseCode() == 200) {
                            //获取服务器响应头中的流,流的数据就是客户端请求的数据
                            InputStream is = conn.getInputStream();
                            //使用位图工厂对象从将文件里的数据读取出来构造成位图对象
                            FileOutputStream fos = new FileOutputStream(file);
                            byte[] bytes = new byte[1024];
                            int len = 0;
                            if ((len = is.read(bytes)) != -1) {
                                fos.write(bytes,0,len);
                            }
                            fos.close();
                            Bitmap bitmap = BitmapFactory.decodeFile(file.getAbsolutePath());
                            Message msg = new Message();
                            msg.obj = bitmap;
                            msg.what = 1;
                            handler.sendMessage(msg);
                        } else {
                            Message msg = Message.obtain();
                            msg.what = 0;
                            handler.sendMessage(msg);
                        }

                    } catch (Exception e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
    }

3.从网络下载文本数据
这里使用字节数组输出流,读取输入流文本数据时,同步把数据写入字节数组输出流,直接通过字节数组输出流构造字符串返回,而不需要写入本地文件

 public String getTextFromStream(InputStream is){
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        byte[] b = new byte[1024];
        int len = 0;
        try {
            if((len = is.read(b))!=-1){
                bos.write(b,0,len);
            }
            String text = new String(bos.toByteArray());
            return text;
        } catch (IOException e) {
            e.printStackTrace();
        }
        return null;
    }

4.使用POST方法提交数据

 String data = "";
                        //添加POST请求的两行属性
                        conn.setRequestProperty("Content-Type","application/x-www-form-urlencoded");
                        conn.setRequestProperty("Content-Length",data.length() + "");
                        //设置打开输出流,拿到输出流
                        conn.setDoOutput(true);
                        OutputStream os = conn.getOutputStream();
                        //使用输出流往服务器提交数据
                        os.write(data.getBytes());

二、多线程下载
需要两次请求网络
第一次请求网络获得文件长度,并且创建一个RandomAccessFile对象生成空的临时文件,设置临时文件的大小为获取的资源文件的长度,并计算每一个线程下载文件的起始位置和结束位置。

public void download() {
        new Thread() {
            @Override
            public void run() {
                try {
                    URL url = new URL(path);
                    HttpURLConnection conn = (HttpURLConnection) url.openConnection();
                    conn.setRequestMethod("GET");
                    conn.setConnectTimeout(5000);
                    conn.setReadTimeout(5000);
                    conn.connect();
                    if (conn.getResponseCode() == 200) {
                        //获得网络请求返回的流的字节长度
                        int length = conn.getContentLength();
                        File file = new File(Environment.getExternalStorageDirectory(),"QQ.exe");
                        //使用随机存文件对象生成临时文件
                        RandomAccessFile raf = new RandomAccessFile(file, "rwd");
                        //设置临时文件的大小
                        raf.setLength(length);
                        //计算出每一个线程应该下载多少字节
                        int size = length / THREADCOUNT;
                        for (int i = 0; i < THREADCOUNT; i++) {
                            //计算每一个线程下载的起始位置和结束位置
                            int startIndex = i * size;
                            int endIndex = (i + 1) * size - 1;
                            if (i == THREADCOUNT - 1) {
                                endIndex = length - 1;
                            }
                            new DownloadThread(startIndex, endIndex, i).start();
                        }
                    }
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        }.start();

    }

第二次请求网络下载文件。通过Range属性设置线程的请求数据区间,请求部分数据成功的返回码为206,还需要设置写入文件的起始位置raf.seek()

断点续传:创建一个临时文件记录线程的下载进度,再次下载时读取临时文件,修改下载区间

class DownloadThread extends Thread {
    int startIndex;
    int endIndex;
    int threadId;

    public DownloadThread(int startIndex, int endIndex, int threadId) {
        this.startIndex = startIndex;
        this.endIndex = endIndex;
        this.threadId = threadId;
    }

    @Override
    public void run() {
        try {
            File progressFile = new File(threadId + ".txt");
            if (progressFile.exists()) {
                FileInputStream fis = new FileInputStream(progressFile);
                BufferedReader br = new BufferedReader(new InputStreamReader(fis));
                startIndex += Integer.parseInt(br.readLine());
            }

            URL url = new URL(MutiThreadActivity.path);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("GET");
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
            //设置本次请求的数据区间
            conn.setRequestProperty("Range", "bytes=" + startIndex + "-" + endIndex);
            if (conn.getResponseCode() == 206) {
                InputStream is = conn.getInputStream();
                byte[] b = new byte[1024];
                int len = 0;
                int total = 0;
                File file = new File(Environment.getExternalStorageDirectory(),"QQ.exe");
                RandomAccessFile raf = new RandomAccessFile(file, "rwd");
                //设置写入文件的开始位置
                raf.seek(startIndex);
                while ((len = is.read(b)) != -1) {
                    raf.write(b, 0, len);
                    total += len;
                    RandomAccessFile progressRaf = new RandomAccessFile(progressFile, "rwd");
                    progressRaf.write((total + "").getBytes());
                    progressRaf.close();
                }
                raf.close();
                //全部下载完毕后删除临时记录文件
                MutiThreadActivity.finishThread++;
                synchronized (MutiThreadActivity.path) {
                    for (int i = 0; i < MutiThreadActivity.THREADCOUNT; i++) {
                        File f = new File(threadId + ".txt");
                        f.delete();
                    }
                    MutiThreadActivity.finishThread = 0;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

使用到的输入输出流:
RandomAccessFile:可以设置写入的位置
FileOutputStream:直接写入文件中
ByteArrayOutputStream:写入的数据存储在一个字节数组中,转换成字节数组,创建字符串
InputStream:读取数据到一个字节数组中
BufferedReader:按行读取,返回一个String,参数是InputStreamReader(FileInputStream)

版权声明:本文为博主原创文章,未经博主允许不得转载。

Android网络编程基础(一) - 基础知识

内容介绍:Android网络编程基础 博客地址:http://blog.csdn.net/kevindgk 版权声明:本文为原创文章,未经允许不得转载 联系方式:815852777...
  • KevinDGK
  • KevinDGK
  • 2016年08月16日 17:45
  • 2285

网络编程基础概述

网络编程 网络编程对于很多的初学者来说,都是很向往的一种编程技能,但是很多的初学者却因为很长一段时间无法进入网络编程的大门而放弃了对于该部分技术的学习。 在 学...
  • w627782664
  • w627782664
  • 2011年12月27日 19:59
  • 6523

java网络编程基础知识

java网络编程基础知识 一、网络基本概念 1、计算机网络,就是把分布在不同地理区域的计算机与专门的外部设备用通信线路互连成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,...
  • wfgeqgeq
  • wfgeqgeq
  • 2011年09月19日 19:24
  • 3381

Android网络编程基础(二)

1 post方式提交数据乱码的解决Android端的默认编码是utf-8; 一般在公司开发客户端和服务端的编码要保持一致。 做url请求时需要对参数进行URLEncode编码. URL url = n...
  • qq_21923867
  • qq_21923867
  • 2017年06月04日 13:22
  • 212

全栈必备 网络编程基础

或许,老码农说的都是错的,了解了所谓的网络基础,也不一定写出漂亮的代码,不了解所谓的网络基础,也不一定写不出漂亮的代码,全当他自言自语吧。...
  • wireless_com
  • wireless_com
  • 2017年01月30日 00:00
  • 3916

JavaScript---网络编程(1)-介绍、变量、运算符与语句

JavaScript也是一种编程语言。并不是Java的分支哦。 可以直接在浏览器中运行的编程语言。JavaScript 的历史故事: 1、JavaScript语言与名称的由来(Netscape,S...
  • qq_26525215
  • qq_26525215
  • 2016年05月29日 18:39
  • 6087

Java基础之网络编程知识点总结

网络编程----Java语言涵盖的领域很广,对于网络方面,java也是相当棒的,java也是可以完成网络通讯的功能的...
  • u011460827
  • u011460827
  • 2014年12月01日 22:00
  • 1746

HttpClient批量上传文件(二)AsyncTask+HttpClient

请尊重他人的劳动成果,转载请注明出处:  Android网络编程之使用HttpClient批量上传文件(二)AsyncTask+HttpClient并实现上传进度监听  运行效果图: ...
  • Demon_huirong
  • Demon_huirong
  • 2016年07月11日 09:04
  • 256

网络编程学习笔记整理(二)

摘录笔记 《TCP/IP高效编程 改善网络程序的44个技巧》socket的创建函数int socket (int domain,int type, int protocol)参数说明protocol需...
  • stecdeng
  • stecdeng
  • 2017年02月23日 14:47
  • 247

Java 之JNI基础篇(一)

JNI,即Java Native Interface。它其实就是一套java与本地代码交互的接口或者说是一个协议。通俗的比喻,就是中国人讲中国话,日本人讲日本话,于是中国人碰到日本人,各说各话,无法交...
  • yingshukun
  • yingshukun
  • 2018年01月13日 18:51
  • 9999
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:【Android基础】二、网络编程
举报原因:
原因补充:

(最多只允许输入30个字)