1. 主Activity,显示需要下载的文件名,并通过ProgressDialog来显示下载进度。
2. 后台服务IntentService进行主要的下载操作,先通过HttpURLConnection来获取远程服务的InputStream, 然后将获取的InputStream写入设备的sdCard中。
3. 通过ResultReceiver传递下载的完成信息给ProgressDialog,使其能及时更新下载进度。
具体的代码:
1. 老样子,在AndroidManifest.xml中设置对因特网的访问权限,和对SDCard的操作权限
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission> <uses-permission android:name="android.permission.INTERNET"></uses-permission> <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
2. 其次,需要在AndroidManifest.xml中设置Activity和Service
<activity android:name="cn.sh.ideal.activity.DownloadActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> <service android:name="cn.sh.ideal.service.DownloadService"/>
3. 在DownloadActivity中,显示需要下载的文件名,点击文件名,调用DownloadService进行文件的下载,并在界面中产生ProgressDialog进度
if(fileRealName!=null && fileRealName.trim().length()>0){ fileName = fileRealName; try { url = ToolsUtil.getIpAddress() + URLEncoder.encode(fileRealName,"UTF-8"); } catch (UnsupportedEncodingException e) { e.printStackTrace(); } progressDialog = new ProgressDialog(DownloadActivity.this); progressDialog.setTitle(getResources().getString(R.string.download_title)); progressDialog.setMessage(getResources().getString(R.string.download_message)); progressDialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); progressDialog.show(); intent = new Intent(DownloadActivity.this, DownloadService.class); intent.putExtra("url", url); intent.putExtra("filename", fileName); intent.putExtra("receiver", new DownloadReceiver(new Handler())); intent.setAction("start"); startService(intent); }
4. DownloadService 对文件进行下载
protected void onHandleIntent(Intent intent) { String urlToDownload = intent.getStringExtra("url"); String filenameToSave = intent.getStringExtra("filename"); ResultReceiver receiver = (ResultReceiver) intent.getParcelableExtra("receiver"); String sdPath = ""; int results = 0; String infos = ""; InputStream input = null; OutputStream output = null; try { //设备中是否存在SDCard,如果不存在则抛出异常 isSDCard(); //设备是否可连接,如果不可链接则抛出异常 isConnected(); sdPath = Environment.getExternalStorageDirectory() + "/" + Constants.DOWNLOAD_PATH; // SDCard中的存储路径是否存在,如果不存在则创建 File dir = new File(sdPath); if(!dir.exists()) createSDDir(sdPath); sdPath = Environment.getExternalStorageDirectory() + "/" + Constants.DOWNLOAD_PATH + "/" + filenameToSave; // 计算需要下载的文件的长度 long totalSize = getRemoteFilesize(urlToDownload); // 计算SDCard的剩余空间是否足够保存下载文件。如果不够,则抛出异常 isSDCardFreeSizeAvailable((int)totalSize); URL url = new URL(urlToDownload); connection = (HttpURLConnection) url.openConnection(); connection.setConnectTimeout(CONNECT_TIME_OUT); connection.connect(); // 获取Http服务的返回信息,如果服务信息为HTTP_OK, HTTP_PARTIAL, 则可进行下载服务,否则抛出异常 int code = getHttpResponseMessage(connection); Log.i(TAG,"httpReturnType=" + code); input = new BufferedInputStream(connection.getInputStream()); output =new FileOutputStream(sdPath); byte data[] = new byte[1024]; long total = 0l; int count; while ((count = input.read(data)) != -1) { total += count; Bundle resultData = new Bundle(); resultData.putInt("progress" ,(int) (total * 100 / totalSize)); receiver.send(UPDATE_PROGRESS, resultData); output.write(data, 0, count); } output.flush(); output.close(); input.close(); results = DOWNLOAD_SUCCESS; } catch(SDCardNotAvailableException sdex){ results = DOWNLOAD_ERROR; infos = getResources().getString(R.string.download_error_sdcard_not_available); } catch(AndroidNoActiveConnectionException aex){ results = DOWNLOAD_ERROR; infos = getResources().getString(R.string.download_error_no_active_connection); } catch(SDCardFreeNotAvailableException sdfex){ infos = getResources().getString(R.string.download_error_sdcard_not_free); results = DOWNLOAD_ERROR; } catch(HttpServiceException rex){ results = DOWNLOAD_ERROR; infos = getResources().getString(R.string.download_error_http_service); } catch(FileNotFoundException fex){ results = DOWNLOAD_ERROR; infos = getResources().getString(R.string.download_error_file_not_found); }catch(IOException ioex){ results = DOWNLOAD_ERROR; infos = getResources().getString(R.string.download_error_io); } catch(Exception ex){ results = DOWNLOAD_ERROR; infos = getResources().getString(R.string.download_error_others); Log.e(TAG,ex.getLocalizedMessage()); } finally{ if(input!=null) try { input.close(); } catch (IOException e) { e.printStackTrace(); } if(output!=null) try { output.close(); } catch (IOException e) { e.printStackTrace(); } if(connection!=null) connection.disconnect(); Bundle resultData = new Bundle(); resultData.putInt("progress" ,results); if(infos!=null && infos.trim().length()>0) resultData.putString("resultMessage", infos); receiver.send(UPDATE_PROGRESS, resultData); }
5. 在DownloadActivity中添加DownloadReceiver类,用以接收DownloadService的下载进度信息和错误信息
private class DownloadReceiver extends ResultReceiver{ public DownloadReceiver(Handler handler) { super(handler); } protected void onReceiveResult(int resultCode, Bundle resultData) { super.onReceiveResult(resultCode, resultData); if (resultCode == DownloadService.UPDATE_PROGRESS) { int progress = resultData.getInt("progress"); if(progress == DownloadService.DOWNLOAD_ERROR){ String infos = resultData.getString("resultMessage"); progressDialog.dismiss(); Toast.makeText(DownloadActivity.this, infos, Toast.LENGTH_SHORT).show(); }else if(progress == DownloadService.DOWNLOAD_SUCCESS){ progressDialog.dismiss(); }else{ progressDialog.setProgress(progress); } } }
附件中提供了这个DEMO的完整代码。