【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
- 【Android基础】二、网络编程
- Android网络编程基础(二)
- 网络编程基础<二>
- android基础之二——网络编程(二)
- Android网络编程(二)
- Android基础之二——网络编程(一)
- Android-网络编程基础
- Android 网络编程基础
- android 网络编程基础
- Linux网络编程基础(二)
- Linux网络编程基础二
- 网络编程基础(二)
- Android网络编程二:Http
- Android网络编程基础简介
- Android网络编程基础简介
- Android基础之网络编程
- android网络编程-socket基础
- Day08-Android网络编程基础
- 练习3-O
- STL运用的C++技术(3)——模板实参推断
- docker相关
- STL运用的C++技术(4)——重载函数
- "House Robber" and "House Robber III"
- 【Android基础】二、网络编程
- 利用powerdesigner导出word文档即sql转pdm模型
- 2016-5-30 代码Review问题总结
- JAVA 对象深度复制实现
- 为什么有人不喜欢标准成本?
- getHibernateTemplate用法
- STL运用的C++技术(5)——重载操作符
- 运用ContactModel API来读取电话本信息
- 快消行业如何营销?