我正在尝试写一个简单的应用,然后应用可以进行更新。为了做成这个,我需要一个简单的功能,就是可以进行下载一个文件,同时在一个ProgressDialog显示出当前的下载进度。我知道如何做ProgressDialog,但是我不知道在同一个地方怎么既下载一个文件又显示当前的进度。
3条回答
- liangchichexin 2012-09-21 02:38关注
有很多下载文件的方法,接下来我将贴出最常用的一些方法;究竟哪一种对你的应用来说最实用取决于你。
- 使用AsyncTask,在一个对话框中显示下载进度
这个方法可以让你进行后台处理的同时更新UI(在这种情况下,我们将更新一个进度条)
这是实例代码:// 声明对话框是你activity的成员字段 ProgressDialog mProgressDialog; // 举例说明在onCreate中的方法 mProgressDialog = new ProgressDialog(YourActivity.this); mProgressDialog.setMessage("A message"); mProgressDialog.setIndeterminate(false); mProgressDialog.setMax(100); mProgressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); DownloadFile downloadFile = new DownloadFile(); downloadFile.execute("the url to the file you want to download");
AsyncTask像这样:
// 通常,AsyncTask子类在activity类中进行声明 // 这样,你可以很容易在这里修改UI线程 private class DownloadFile extends AsyncTask<String, Integer, String> { @Override protected String doInBackground(String... sUrl) { try { URL url = new URL(sUrl[0]); URLConnection connection = url.openConnection(); connection.connect(); //这将是有用的,这样你可以显示一个典型的0-100%的进度条 int fileLength = connection.getContentLength(); // 下载文件 InputStream input = new BufferedInputStream(url.openStream()); OutputStream output = new FileOutputStream("/sdcard/file_name.extension"); byte data[] = new byte[1024]; long total = 0; int count; while ((count = input.read(data)) != -1) { total += count; publishProgress((int) (total * 100 / fileLength)); output.write(data, 0, count); } output.flush(); output.close(); input.close(); } catch (Exception e) { } return null; }
上边的方法(doInBackground)一直在一个后台线程中进行。你不需要做任何UI的任务。另一方面,onProgressUpdate和onPreExecute在UI线程上运行,因此你可以改变进度条
@Override protected void onPreExecute() { super.onPreExecute(); mProgressDialog.show(); } @Override protected void onProgressUpdate(Integer... progress) { super.onProgressUpdate(progress); mProgressDialog.setProgress(progress[0]); } }
一旦文件已经下载完,如果你想要执行一些代码(例如mProgressDialog.dismiss()),你也可能想要重写onPostExecute方法。
2.从服务器下载
这个大的问题是:我如何从服务器上更新我的activity?在下个示例中,我们将使用两个你可能没有太注意过的类:ResultReceiver和IntentService. ResultReceiver允许我们从服务器上更新我们的线程的类,IntentService 是Service的一个子类,从那,它可以产生一个线程来处理后台任务(你应该知道,你的应用的Service在同样的进程运行;当你继承Service时,你必须手动生成新的线程来运行CPU的阻塞操作)
可以像这样:public class DownloadService extends IntentService { public static final int UPDATE_PROGRESS= 8344;‘ public DownloadService() { super("DownloadService"); } @Override protected void onHandleIntent(Intent intent) { String urlToDownload= intent.getStringExtra("url"); ResultReceiver receiver= (ResultReceiver) intent.getParcelableExtra("receiver"); try { URL url= new URL(urlToDownload); URLConnection connection= url.openConnection(); connection.connect(); // 这将是有用的,这样你可以显示一个典型的0-100%的进度条 int fileLength= connection.getContentLength(); // 下载文件 InputStream input= new BufferedInputStream(url.openStream()); OutputStream output= new FileOutputStream("/sdcard/BarcodeScanner-debug.apk"); byte data[] = new byte[1024]; long total= 0; int count; while ((count= input.read(data)) != -1) { total+= count; Bundle resultData= new Bundle(); resultData.putInt("progress" ,(int) (total* 100 / fileLength)); receiver.send(UPDATE_PROGRESS, resultData); output.write(data, 0, count); } output.flush(); output.close(); input.close(); }catch (IOException e) { e.printStackTrace(); } Bundle resultData= new Bundle(); resultData.putInt("progress" ,100); receiver.send(UPDATE_PROGRESS, resultData); } }
向你的manifest中加service
<service android:name=".DownloadService"/>
Activity将像这样
// 像第一个例子那样初始化进度条 //这是你怎么启动下载器 mProgressDialog.show(); Intent intent = new Intent(this, DownloadService.class); intent.putExtra("url", "url of the file to download"); intent.putExtra("receiver", new DownloadReceiver(new Handler())); startService(intent);
这是ResultReceiver开始起作用
private class DownloadReceiver extends ResultReceiver{ public DownloadReceiver(Handler handler) { super(handler); } @Override protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); if (resultCode == DownloadService.UPDATE_PROGRESS) { int progress = resultData.getInt("progress"); mProgressDialog.setProgress(progress); if (progress == 100) { mProgressDialog.dismiss(); } } } }
3.使用DownloadManager 类(GingerBread ,而且仅仅是最新的)
这个方法是可怕的,你不用担心手动下载文件,处理线程,数据流,等等。GingerBread有一个新的特点,DownloadManager可以让你很容易的下载文件,然后将辛苦的工作给系统做。/** * @ param上下文用来检查设备的版本和DownloadManager信息 * @如果下载管理器可以用,则返回true */ public static boolean isDownloadManagerAvailable(Context context) { try { if (Build.VERSION.SDK_INT< Build.VERSION_CODES.GINGERBREAD) { return false; } Intent intent= new Intent(Intent.ACTION_MAIN); intent.addCategory(Intent.CATEGORY_LAUNCHER); intent.setClassName("com.android.providers.downloads.ui", "com.android.providers.downloads.ui.DownloadList"); List<ResolveInfo> list= context.getPackageManager().queryIntentActivities(intent, PackageManager.MATCH_DEFAULT_ONLY); return list.size() > 0; } catch (Exception e) { return false; } }
方法的名字直接就解释了。一旦你确定DownloadManager是可用的,你可以做下边这些:
String url= "url you want to download"; DownloadManager.Request request= new DownloadManager.Request(Uri.parse(url)); request.setDescription("Some descrition");request.setTitle("Some title"); // 如果为了让它运行,你必须用android3.2编译你的应用程序 if (Build.VERSION.SDK_INT>= Build.VERSION_CODES.HONEYCOMB) { request.allowScanningByMediaScanner(); request.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED); } request.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "name-of-the-file.ext"); // 获得下载服务和队列文件 DownloadManager manager= (DownloadManager) getSystemService(Context.DOWNLOAD_SERVICE); manager.enqueue(request);
下载进度条将在通知栏显示
结语
第一个和第二个方法仅仅是冰山一角。如果你想要你的app是健壮的,这有很多事情需要你记住。这是一个简短的列表:你必须检查用户是否有可用的网络链接。
确定你有权限((INTERNET and
WRITE_EXTERNAL_STORAGE);如果你想要检查网络是否可用也可以用ACCESS_NETWORK_STATE确保你要下载的文件的目录存在,有读写权限
如果下载包太大,之前的下载失败了,你可能需要实现一种方法来恢复下载
如果你允许用户中断下载,他们会很感激你。
除非你已经完全控制了下载过程,否则我强烈建议你使用DownloadManager ,它已经实现了上边列出的大部分功能。
本回答被题主选为最佳回答 , 对您是否有帮助呢?解决 无用评论 打赏 举报
悬赏问题
- ¥15 用comsol模拟大气湍流通过底部加热(温度不同)的腔体
- ¥50 安卓adb backup备份子用户应用数据失败
- ¥20 有人能用聚类分析帮我分析一下文本内容嘛
- ¥15 请问Lammps做复合材料拉伸模拟,应力应变曲线问题
- ¥30 python代码,帮调试
- ¥15 #MATLAB仿真#车辆换道路径规划
- ¥15 java 操作 elasticsearch 8.1 实现 索引的重建
- ¥15 数据可视化Python
- ¥15 要给毕业设计添加扫码登录的功能!!有偿
- ¥15 kafka 分区副本增加会导致消息丢失或者不可用吗?