最近做了一个DEMO, 是通过httpURLConnection服务来下载文件。 大致的设计思路是这样的:
1. 主Activity,显示需要下载的文件名,并通过ProgressDialog来显示下载进度。
2. 后台服务IntentService进行主要的下载操作,先通过HttpURLConnection来获取远程服务的InputStream, 然后将获取的InputStream写入设备的sdCard中。
3. 通过ResultReceiver传递下载的完成信息给ProgressDialog,使其能及时更新下载进度。
具体的代码:
1. 老样子,在AndroidManifest.xml中设置对因特网的访问权限,和对SDCard的操作权限
2. 其次,需要在AndroidManifest.xml中设置Activity和Service
3. 在DownloadActivity中,显示需要下载的文件名,点击文件名,调用DownloadService进行文件的下载,并在界面中产生ProgressDialog进度
4. DownloadService 对文件进行下载
5. 在DownloadActivity中添加DownloadReceiver类,用以接收DownloadService的下载进度信息和错误信息
附件中提供了这个DEMO的完整代码。
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的完整代码。