【Android基础】二、网络编程

来源:互联网 发布:税务查账软件 编辑:程序博客网 时间:2024/06/06 19:25

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)

0 0