- 浏览: 220822 次
文章分类
最新评论
-
lmjmn456:
为什么我的TestHall里面看不到RomeA RomeB R ...
Android 通过反射启动未安装的APK中的Activity -
wangleyiang:
uyerp 写道这样的话,只能将插件的元素显示到Hall中。有 ...
Android 通过反射启动未安装的APK中的Activity -
uyerp:
这样的话,只能将插件的元素显示到Hall中。有什么办法能在不安 ...
Android 通过反射启动未安装的APK中的Activity -
wangleyiang:
提高文学修养 写道不好意思,有时间尝试一下,谢谢!有问题提出来 ...
Android 主题之主题文件夹 -
提高文学修养:
不好意思,有时间尝试一下,谢谢!
Android 主题之主题文件夹
来源:http://1679554191.iteye.com/admin/blogs/1751065
Android开发中经常会遇到文件的下载,而下载的时间与网络状态和被下载文件的大小等因素有关。本文会对单线程下载和多线程下载做简要说明。无论哪种操作,最终都是基于HTTP(HTTPS)的网络访问。
先看看基本的一个操作流程,然后对于每一个操作步骤逐一实现就可以了。
基本流程:
- 设置连接属性;
- 建立连接;
- 获得需要的资源;
- 释放资源;
说明:这个流程是相对的,每个人可以根据具体情况而定。:)
1、在普通Java项目中下载文件: 为了简化问题,我们先不考虑在Android中实现过程,仅仅实现一个下载并保存网络资源的操作。
代码如下:
import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; public class FileDownload { /** * @param args */ public static void main(String[] args) { downloadFile("http://image.tianjimedia.com/uploadImages/2012/153/2H4Y79KZF2X3.jpg", "image.jpg"); downloadFile("http://www.google.com", "message.txt"); } private static void downloadFile(String urlPath, String filePath) { InputStream inputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; byte[] data = null; try { URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(6 * 1000); conn.connect(); if (conn.getResponseCode() == 200) { inputStream = conn.getInputStream(); byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length = -1; while ((length = inputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, length); } data = byteArrayOutputStream.toByteArray(); } } catch (Exception e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e1) { e1.printStackTrace(); } } if (byteArrayOutputStream != null) { try { byteArrayOutputStream.close(); } catch (IOException e1) { e1.printStackTrace(); } } } if (data != null) { File file = new File(filePath); FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(file); outputStream.write(data); } catch (Exception e) { e.printStackTrace(); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } } }
说明:
1、InputStream inputStream = null;和ByteArrayOutputStream byteArrayOutputStream = null;之所以在try-catch外定义,是为了可以在finally代码块中可以访问,并释放该资源。在回收资源时,最好把不同资源放在单独的 try-catch块中做资源释放操作,否则可能造成资源泄漏。
InputStream inputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; try { ...... } catch (Exception e) { e.printStackTrace(); } finally { try { if (inputStream != null) { inputStream.close(); } if (byteArrayOutputStream != null) { byteArrayOutputStream.close(); } } catch (Exception e) { e.printStackTrace(); } }
如果采用上述资源释放代码,当inputStream和byteArrayOutputStream都不为null时,如果 inputStream.close();发生异常,将导致byteArrayOutputStream.close();不被执行,从而没有释放该资 源。
2、conn.setRequestMethod("GET");和conn.setConnectTimeout(6 * 1000);是设置连接属性。还有其它属性,如果需要的话,可以进行设定。
3、conn.connect();建立连接。
4、conn.getInputStream();获得连接后的输入流,从中可以获得数据。
5、在finally代码块中对申请的资源进行释放。
运行该项目,会在项目的根目录下看到两个文件,image.jpg和message.txt,如图所示:
2、在Android项目中下载文件:
a、对UI的设计:
主Activity中有两个Button,分别启动另外的两个Activity,来实现图片的下载显示和网页内容的获得并显示。布局文件就补贴出来了,会在附件中提供源码。
b、主Activity没有什么好说的,下面对另外两个Activity做详细说明:
DownloadImageActivity:
package com.anhuioss.download; import java.io.ByteArrayOutputStream; import java.io.File; import java.io.FileOutputStream; import java.io.IOException; import java.io.InputStream; import java.net.HttpURLConnection; import java.net.URL; import android.app.Activity; import android.graphics.drawable.Drawable; import android.os.Bundle; import android.os.Environment; import android.os.Handler; import android.text.TextUtils; import android.view.View; import android.view.View.OnClickListener; import android.widget.Button; import android.widget.EditText; import android.widget.ImageView; public class DownloadImageActivity extends Activity implements OnClickListener { private EditText filePathEditText; private Button downloadButton; private ImageView imageDisplay; private Handler handler = new Handler(); @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.activity_download_image); filePathEditText = (EditText) findViewById(R.id.adi_image_path); downloadButton = (Button) findViewById(R.id.adi_button_download); imageDisplay = (ImageView) findViewById(R.id.adi_image); downloadButton.setOnClickListener(this); } @Override public void onClick(View v) { if (v == downloadButton) { if (!Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { return; } String path = filePathEditText.getText().toString(); if (!TextUtils.isEmpty(path)) { downloadButton.setEnabled(false); imageDisplay.setImageDrawable(null); downloadFile(path, Environment.getExternalStorageDirectory() + File.separator + "image.jpg"); } } } private void downloadFile(final String urlPath, final String filePath) { new Thread(new Runnable() { @Override public void run() { InputStream inputStream = null; ByteArrayOutputStream byteArrayOutputStream = null; byte[] data = null; try { URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("GET"); conn.setConnectTimeout(6 * 1000); conn.connect(); if (conn.getResponseCode() == 200) { inputStream = conn.getInputStream(); byteArrayOutputStream = new ByteArrayOutputStream(); byte[] buffer = new byte[1024]; int length = -1; while ((length = inputStream.read(buffer)) != -1) { byteArrayOutputStream.write(buffer, 0, length); } data = byteArrayOutputStream.toByteArray(); } } catch (Exception e) { e.printStackTrace(); } finally { if (inputStream != null) { try { inputStream.close(); } catch (IOException e1) { e1.printStackTrace(); } } if (byteArrayOutputStream != null) { try { byteArrayOutputStream.close(); } catch (IOException e1) { e1.printStackTrace(); } } } if (data != null) { File file = new File(filePath); FileOutputStream outputStream = null; try { outputStream = new FileOutputStream(file); outputStream.write(data); handler.post(new Runnable() { @Override public void run() { downloadButton.setEnabled(true); Drawable drawable = null; try { drawable = Drawable.createFromPath(filePath); } catch (Error e) { e.printStackTrace(); } imageDisplay.setImageDrawable(drawable); } }); } catch (Exception e) { e.printStackTrace(); } finally { if (outputStream != null) { try { outputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } } }).start(); } }
说明:
1、private Handler handler = new Handler();handler的作用是在下载线程中完成下载后在UI线程里面更新UI。
2、由于示例中需要用到SDCARD,所以在做下载操作时,如果没有挂载SDCARD时,不进行下载处理:
if (!Environment.getExternalStorageState().equals(android.os.Environment.MEDIA_MOUNTED)) { return; }
3、
handler.post(new Runnable() { @Override public void run() { downloadButton.setEnabled(true); Drawable drawable = null; try { drawable = Drawable.createFromPath(filePath); } catch (Error e) { e.printStackTrace(); } imageDisplay.setImageDrawable(drawable); } });
利用handler的post方法,在UI线程里面更新UI。首先使能按钮,其次创建drawable,最后显示图片。
3、运行项目,查看效果: 在运行前,不要忘记在Manifest文件中添加网络访问和访问SDCARD的权限哦!
<uses-permission android:name="android.permission.INTERNET" /> <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE" />
下载图片的效果如下:
获取网页内容的页面效果:
4、多线程文件下载,直接看普通Java项目中相关操作的代码:
import java.io.IOException; import java.io.InputStream; import java.io.RandomAccessFile; import java.net.HttpURLConnection; import java.net.URL; public class FileDownloadMultiThread { public static void main(String[] args) { downloadFile(); } private static void downloadFile() { String fileName = "mysql.chm"; String urlPath = "http://192.168.1.106/mysql.chm"; // 下载开始前,创建RandomAccessFile并设置文件大小 RandomAccessFile file = null; try { // 创建URL对象 URL url = new URL(urlPath); // 创建HttpURL连接 HttpURLConnection conn = (HttpURLConnection) url.openConnection(); // 设置请求属性 conn.setConnectTimeout(6 * 1000); conn.setRequestMethod("GET"); // 连接 conn.connect(); // 需要下载文件的长度 int fileLength = conn.getContentLength(); // 创建RandomAccessFile并设置文件大小 file = new RandomAccessFile(fileName, "rw"); file.setLength(fileLength); // 启动的线程数量 int threadCount = 6; // 计算每个线程需要下载数据的长度 int threadDownloadLength = fileLength % 3 == 0 ? fileLength / 3 : fileLength / 3 + 1; // 创建threadCount个下载线程 for (int i = 0; i < threadCount; i++) { // 计算开始位置 int startPosition = i * threadDownloadLength; // 创建匿名下载线程对象 new MultiDownloadThread(fileName, urlPath, startPosition).start(); } } catch (Exception e) { e.printStackTrace(); } finally { // 资源释放 if (file != null) { try { file.close(); } catch (IOException e) { e.printStackTrace(); } } } } static class MultiDownloadThread extends Thread { private String urlPath; private int startPosition; private RandomAccessFile accessFile; public MultiDownloadThread(String fileName, String urlPath, int startPosition) { this.urlPath = urlPath; this.startPosition = startPosition; try { accessFile = new RandomAccessFile(fileName, "rw"); accessFile.seek(startPosition); } catch (Exception e) { e.printStackTrace(); } } public void run () { InputStream inputStream = null; try { URL url = new URL(urlPath); HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setConnectTimeout(6 * 1000); conn.setRequestMethod("GET"); // 设置HTTP的Range字段,指定该线程从文件的什么位置开始下载 conn.setRequestProperty("Range", "bytes=" + startPosition + "-"); conn.connect(); inputStream = conn.getInputStream(); byte[] buffer = new byte[1024]; int readLength = -1; int totalLength = 0; while ((readLength = inputStream.read(buffer)) != -1) { accessFile.write(buffer, 0, readLength); totalLength = totalLength + readLength; } } catch (Exception e) { e.printStackTrace(); } finally { if (accessFile != null) { try { accessFile.close(); } catch (IOException e) { e.printStackTrace(); } } if (inputStream != null) { try { inputStream.close(); } catch (IOException e) { e.printStackTrace(); } } } } } }
说明:
1、RandomAccessFile类创建目标文件并设置文件大小;
2、HttpURLConnection.setRequestProperty("Range", "bytes=" + startPosition + "-");方法指定下载位置;
3、RandomAccessFile.seek();设置文件指针偏移量,保存下载内容到指定位置;
4、由于线程的创建和销毁过程,线程之间的上下文切换等都需要系统资源,所以threadCount不是越大越好,而是根据具体情况进行设定;
4、在Android上实现多线程下载的方法类似,注意Android环境的特性就可以了,再次不再赘述!:)
5、多说一句: HTTP(HTTPS)的连接到网络上的数据资源的方式和设置多种多样,本例仅仅是从一个角度进行说明,希望对你有所帮助!如果需要Android项目源码,请查看附件!:)
- DownloadFile.zip (72.7 KB)
- 下载次数: 3
发表评论
-
避免OOM的一种方式
2014-03-11 09:30 869从网上看到一个避免OOM的方式,创建图片时,使用decod ... -
锁屏操作
2013-11-01 11:29 949从API Level 8开始,添加了一个新的类Device ... -
让Surface中绘制的内容响应用户的交互(状态变化)
2013-10-28 16:54 893被绘制的内容响应用户的交互,简单的看就是绘制内容的状态在用 ... -
在自定义的SurfaceView中绘制内容
2013-10-28 16:53 2861View和SurfaceView都可以用于绘制图形,但各有 ... -
在自定义的View中绘制内容
2013-10-28 10:52 943程序开发中,常常需要完成某一个特殊效果而绘制一些内容。 ... -
获取Bitmap大小
2013-10-08 17:59 1009Bitmap的操作常常会导致OOM(内存溢出)。 在处理B ... -
隐藏键盘的一种处理方法
2013-10-08 15:18 667通过调用系统服务来隐藏键盘的一种处理方法: // 获 ... -
通过系统调用裁剪图片
2013-10-08 15:05 1053分享一个Android源码查看网页:http://andr ... -
拍照,相册获取图片,系统裁剪图片
2013-09-30 12:41 1604获取相册图片的一种写法: Intent intent = ... -
转-Android开发环境搭建篇详尽的教程实例汇
2013-09-27 13:50 754原文:http://wiki.eoe.cn/page/An ... -
一种更改包名的方式-Linux命令
2013-09-27 09:54 1141在Android应用程序中更改包名,可以从文件的角度来解决 ... -
Android 通过反射启动未安装的APK中的Activity
2013-02-05 16:32 8873JAVA反射机制是在运行状态中,对于任意一个类,都能够知道 ... -
Android 判断程序是否是系统程序
2013-02-04 14:12 1657获得Android手机中安装程序是否是系统程序,比较好的方式 ... -
Android R
2013-02-01 16:18 1248import java.lang.reflect.Fiel ... -
Android 主题之主题文件夹
2013-02-01 14:22 1709从文件夹中获得主题资源,然后在程序中做相关调整,下面看一个 ... -
Android 主题之安装的APK主题文件
2013-01-31 17:25 1843Android中应用主题设置 ... -
『转』Android Intent常见应用
2013-01-30 16:46 1362转自:http://blog.csdn.net/spy19 ... -
Android px sp dip转化
2013-01-30 12:53 977一个关于px, sp, dip转化的代码: public ... -
Android 布局
2013-01-30 11:19 1317对Android提供的基本布局控件进行组合,可以实现一些相 ... -
Android 添加动画的标签栏
2013-01-29 23:10 1113运行效果图: 实现原理:标签布局好了以后,标签所在V ...
相关推荐
一个Android文件下载Download程序示例,文件会下载至local端,远程安装程序(请输入URL),取得远程文件,取得URL,创建连接,InputStream 下载文件,创建临时文件,取得站存盘案路径,将文件写入暂存盘,在手机上打开文件的...
综上所述,实现Android文件的断点续传下载主要依赖于Java的RandomAccessFile类和多线程技术,通过精确控制文件的读写位置和下载范围,确保下载的连续性和可靠性。这种技术不仅提高了用户的下载体验,也在一定程度上...
与网上流传一个itcast的多线程下载的示例不同, ...可能需要进一步优化,本示例下载同样大小的文件需要6-7秒(下载速度都是200K左右) 暂不支持断点、多个文件同时下载, 架构清晰,可重复利用,如有问题欢迎斧正
本示例"Android文件下载Demo(可断点续传)"提供了一个实现多线程下载并且支持断点续传功能的源代码DEMO。下面将详细解释这个Demo中涉及的关键知识点。 1. **多线程下载**: 在Android中,为了提高文件下载速度,...
在Android平台上,开发一个应用程序以实现下载Word文档并顺利打开是一项常见的需求。下面将详细讲解这一过程中的关键知识点,以及如何结合给定的资源进行操作。 1. **Android权限管理**: 在Android中,访问网络和...
在Android平台上,文件下载是一项常见的任务,特别是在处理大型文件或多媒体资源时,为了提升用户体验,开发者通常会采用多线程下载并实现断点续传功能。断点续传允许用户在下载过程中暂停、恢复,避免因网络问题或...
最后,这个压缩包中的“android文件下载存储demo”项目,尽管可能需要自行调试才能运行,但它提供了一种基础结构,你可以从中学习如何组织代码、如何处理网络请求,以及如何在Android环境中实现文件的存取和解压。...
十分有用的共享资源十分有用的共享资源十分有用的共享资源。
Java 和 Android 文件下载断点续传概要 在本文中,我们将对 Java 和 Android 文件下载断点续传的概要进行详细的介绍。断点续传是一种常用的文件下载技术,它可以在下载过程中发生意外中断时,继续从中断的地方继续...
java和Android文件下载断点续传和图片下载代码实现, 可直接复制代码, 实现多种文件下载,
下载程序下载器,下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理器、文件下载管理...
在Android平台上实现文档下载功能,特别是对于Word文档的下载,是一项常见的需求,尤其对于移动应用开发者来说。这个“android文档下载”主题主要涉及到以下几个关键知识点: 1. **Android权限管理**: 在Android...
在Android开发中,断点下载是一项重要的功能,它允许用户在中断网络连接后从上次停止的位置继续下载大文件,如应用程序、音乐或视频。本文将深入探讨如何在Android平台上实现断点下载,包括其原理、步骤以及核心代码...
在Android平台上,利用Http协议进行文件下载是一项常见的任务,它涉及到网络编程、多线程、文件操作等多个技术领域。本文将深入探讨如何在Android中实现这个功能,主要围绕标题“Android利用Http下载文件”和提供的...
本教程将深入探讨如何利用Service组件在Android设备上实现文件的后台下载,确保即使用户退出应用程序,文件下载也能继续进行。 ### 1. Android Service基础知识 Service是Android四大组件之一,它在后台运行,没有...
Android 端本地预览 PDF 文件,使用 AS2.3.3 Gradle 4.1 下载下来可以直接编译运行,内部支持加载本地 File ,也可以加载一个 URL 类型的 PDF 文件,如果恰恰你的 APP 不想调用第三方软件的话 这个 DEMO 非常适合你...
这个demo演示从网上下载文件并保存到手机,demo中可以下载一个XML文件并在Console窗口输出,还可以下载一个MP3文件并保存到手机存储目录中的BoBoMusic文件夹中,下载保存成功会返回:0。(XML和MP3文件我已经传到...
该项目为基于Java开发的Android文件下载工具,命名为JarvisDownloader,设计源码包含69个文件,涵盖22个Java源代码文件、21个XML布局文件、10个PNG资源文件、4个Gradle配置文件、3个Git忽略配置文件及其他类型文件。...
官网最新Android API开发文档,为不方便下载的亲打包上传,一共6个分卷,解压任意一个,文档无加密。文档为HTML类型。
在Android开发中,TCP文件下载是一项常见的任务,它涉及到网络通信、多线程处理以及文件操作等技术。本文将详细讲解如何实现一个Android应用,利用TCP协议从PC服务器下载文件到Android设备。 首先,理解TCP...