마스터Q&A 안드로이드는 안드로이드 개발자들의 질문과 답변을 위한 지식 커뮤니티 사이트입니다. 안드로이드펍에서 운영하고 있습니다. [사용법, 운영진]

파일 다운로드할 때 어떤 클래스를 사용할까요?

0 추천

안녕하세요.

현재 저에게 주어진건 파일다운로드가 가능한 링크 뿐입니다.

요걸 가지고 폰 내부 혹은 외부 메모리등에 저장하는 기능을 만들고 있는데요..

현재 사용하고 있는건 HttpURLConnection 클래스 입니다.

찾아보니 downloadManager라는 클래스도 있더군요. 

api레벨 2.3부터 사용이 가능하고 다운로드를 편하게(?)할 수 있다는 설명이 적혀있네요..

현재는 아래와 같이 AsyncTask와 HttpURLConnection를 사용해서 파일을 받고있습니다.

(중간에 progress는 프로그레스바를 진행시키기 위해 짜놓은 것입니다.)

파일 용량은 최소 50MB~최대 1.2GB정도 됩니다..

이런 대용량 파일을 받을 때 어느 쪽이 더 효율(?)적이고 관리하기 좋은지 궁금합니다.

conn = (HttpURLConnection) NewUrl.openConnection();
conn.setRequestProperty("Accept-Encoding", "identity");// add
long fileSize = conn.getContentLength();// 다운받을 파일 크기
					if (fileSize < 0) {
						conn.disconnect();
						suc = 1;

					}

					else if (emptyStorage <= fileSize) {
						suc = 4;
					} else {
						df = file.createFile("*/*", "filename");//따옴표안이 파일네임.
						fosFile = getContentResolver().openOutputStream(df.getUri());
						byte[] data = new byte[1024];// lenth
						int read;
						long total = 0;
						int progress = 0;
						InputStream is = conn.getInputStream();
						
						for (;;) {
							read = is.read(data);
							total += read;
							int progress_temp = (int) ((double) total / fileSize * 100);
							publishProgress("" + progress_temp);
							if (progress_temp % 10 == 0 && progress != progress_temp) {
								progress = progress_temp;
							}
							if (read <= 0) {
								break;
							}
							fosFile.write(data, 0, read); 
							
							if (isCancelled()) 
							{
								Log.e("취소되었다", "취소되었다");
								return 5;
							}
						}
						is.close();
						fosFile.close();
						conn.disconnect();

 

망고사탕 (5,000 포인트) 님이 2017년 8월 18일 질문

1개의 답변

+1 추천
 
채택된 답변

https://github.com/kittinunf/Fuel
개인적으로는 Kotlin+RxKotlin 조합을 사용하여 사용하는 것이 가장 편했는데, Java로도 간단하게 사용할 수 있는걸로 알고 있습니다. 기본적으로 Async인걸로 알고있습니다.

DownloadManager도 사용해보면 굉장히 편한 구조로 되어 있습니다.

프로그래스 수치가 뚝뚝 끊겨서 콜백된다는 단점만 빼고는 기본 DownloadManager를 사용하는게 더 효율적이었습니다.

minor (13,710 포인트) 님이 2017년 8월 18일 답변
망고사탕님이 2017년 8월 18일 채택됨
답변감사드립니다.
깃헙라이브러리는 시간이 부족해서 당장 사용하긴 어려울것 같고..
일단은 Downloadmanager와 HttpURLConnection중 하나를 선택해서 수정하려고 했습니다. 궁금한 것이 있는데 프로그래스 수치가 뚝뚝 끊긴다는게, 프로그레스바 진행이 매끄럽지 않다는 뜻인가요? 다운로드매니저 속도가 HttpURLConnection에 비해 빠르다는 것인가요?
진행은 제대로 됩니다만, 프로그래스 수치를 받아보면 0, 0, 0, 0, 0, 113023, 113023, 113023, 202323, 202323 이런 방식으로 연속적인 값으로 오지 않습니다. 따라서 바형 프로그래스를 직접 구현할때 매끄럽게 진행되는것처럼 느껴지지는 않습니다.
다운로드 매니저 속도가 개인적으로 느끼기에는 HttpURLConnection을 직접 구현하는 것보다도 빠르다고 느껴졌었습니다. DownloadManager를 사용할 때는 Progress가 Status 창에 노티 형태로 나오는 것이 디폴트라서 다운로드가 직관적으로 이루어지는 것도 좋았구요 :)
아..말씀인 즉, bar 형으로 차오를 때 1씩 증가하는 것처럼 매끄럽게 증가되지 않고 증가는 하지만 그 사이의 갭이있다 이 말씀이시죠?
현재 실내 wifi로만 테스트를 하고 있는데 물론 wifi기기마다 속도가 다르긴 하지만.. 1GB일 경우엔 4,5분씩 걸리더라고요 ㅠ httpurlconnection쪽의 성능도 영향을 미치는지 궁금했었습니다. 좋은 답변 감사드립니다. downloadmanager로도 테스트를 해봐야겠네요.
네 맞습니다. 정확히 이해하신 것 같습니다.
DownloadManager 클래스를 사용할 때의 또다른 이점은 다운로드 완료 노티를 스테이터스바에 표시할 수 있는 옵션이 있습니다. 디폴트는 다운로드 완료 시 알림 없이 프로그래스 노티가 종료됩니다. 프로그래스를 숨기고 따로 프로그래스 노티를 만드셔도 되는데 그렇게 할 경우에는 따로 permission이 필요한걸로 알고있습니다.
오 그런 옵션도 잇군요..감사합니다 많이 배우네요 오늘^^..
혹시 실례 되지 않는다면 질문 드려도 될까요..?
1.다운로드매니저로 대용량 파일도 안정적으로 받을 수 있는지요?
2. httpurlconnection으론 exception을 사용했는데 다운로드매니저 설명을 보니  브로드캐스트리시버를 사용해서 따로 실패시 처리를 해야한다고 해서요.. 예외처리면에선 어떤지 궁금합니다.[인터넷이 끊겨서 다운로드가 안되는 경우 등]
DownloadManager 사용 시 에러 발생은 생각보다 종종 있는 편입니다
대용량 파일도 잘 받아지기는 하는데 말씀해주신 상황 이외에도 알 수 없는 현상들이 종종 있습니다.
BroadcastReceiver를 사용해서 재다운로드나 에러 핸들링하는건 다룰만 한데 Activity(View)에 영향을 주어야 한다면 로직을 신중하게 고민해 봐야겠죠 :) 그 부분을 제외하고는 사용하기 편하다고 생각합니다.
답변 감사합니다.매번 답해주셔서 넘 감사한..ㅠㅠ
액티비티 뷰는 화면단을 말씀하시는것인가요?
일단 세분화?까지는 아직 고려를 안했고 전체적으로는
다운로드하는동안 프로그레스 다이얼로그를 띄워서 다운로드 현황을 알려주고만 있습니다. 그래서 위에 프로그레스바에 대해 여쭤본 것이기도 하고요.
이 다이얼로그가 종료되는건 성공적으로 완수/실패했을 때 뿐입니다.
(toast로도 성공/실패만을 알려줍니다.) 여기서 실패햇을 시 인터넷이 연결된 상황이라면 재다운로드(이어받기) 구현까지라도 해보려고 하거든요.
네 제가 구현했던 프로젝트중에는 화면에 다운로드 상황을 표시해야 하는 프로젝트가 있었어서요 :) 다이얼로그만 띄우는거면 DownloadManager 클래스를 사용하시는게 가장 이상적인 선택일 것 같습니다. 재다운로드에 대한 로직 역시 마찬가지구요 :)
답변 정말 감사드립니다(_ _)
조언해주신대로 짬짬히 downloadmanager로 바꿔봐야겠네요.
좋은하루 보내세요. 정말 감사합니다.
...