문제 상황
파일 스트림을 통해서 pdf를 다운로드하는 과정에서 사용자에게 다운로드 상태나 메세지가 보이지 않습니다. 따라서 사용자는 다운로드의 진행 상태를 알 수 없어 해당 기능을 사용하는데 불편함을 느낄 수 있습니다.
따라서 pdf를 다운로드 하면 다운로드에 대한 정보가 사용자에게 제공되도록 개발을 하려고합니다.
생각한 방법
- downloadManager 사용
- 적합한 상황
- 주로 웹에서 직접 파일을 다운로드할 때 사용됩니다. 다운로드할 리소스는 웹상의 URI 형태로 제공되어야 하며, 이 URI는 HTTP 또는 HTTPS 프로토콜을 사용해 접근 가능한 파일이어야 합니다.
- 대용량 파일 다운로드: 대용량 파일이나 긴 다운로드 시간이 필요한 파일을 다운로드할 때 유용합니다.
- 앱 사용 중이 아닐 때도 다운로드 필요: 앱이 백그라운드에서 실행되거나 사용자가 다른 앱을 사용 중일 때도 다운로드가 계속 진행되어야 하는 경우.
- 장점
- 사용 편의성: API 사용이 간단하며 다운로드 관리가 용이합니다.
- 안정성과 효율성: 시스템에 의해 관리되므로 네트워크 상태 변화에 따른 자동 재개 등의 기능이 내장되어 있습니다.
- 단점
- 제한된 커스터마이제이션: UI나 알림 스타일 변경이 제한적입니다.
- 권한 요구: 사용자에게 파일과 네트워크 접근 권한을 요구해야 합니다.
- 적합한 상황
- NotificationManager 사용
- 적합한 상황
- 로컬 파일, 네트워크 상의 URI, 또는 앱 내부에서 생성된 데이터 등 다운로드할 대상의 형태에 구애받지 않습니다. 단, 개발자가 구현해야합니다.
- 다양한 알림의 필요성: 다운로드뿐만 아니라 다른 종류의 작업 진행 상태도 사용자에게 알리고 싶을 때 적합합니다.
- 고도의 사용자 경험 제공: 알림의 모양, 소리, 진동 등을 사용자의 기대에 맞춰 상세하게 조정해야 할 때.
- 장점
- 높은 커스터마이징: 사용자의 요구에 따라 다양하게 알림을 구성할 수 있습니다.
- 직접적인 사용자 인터랙션: 알림을 통해 사용자가 다운로드를 제어할 수 있습니다.
- 단점
- 개발 복잡성: 알림 관리, 상태 업데이트 등 모든 부분을 개발자가 직접 처리해야 합니다.
- 배터리와 자원 사용: 자주 업데이트되는 알림은 배터리와 자원 소모가 클 수 있습니다.
- 적합한 상황
1. DownloadManager 사용
DownloadManager는 안드로이드 시스템이 제공하는 API로, 네트워크를 통한 파일 다운로드를 관리하고 사용자에게 상태 바 알림을 통해 다운로드 진행 상태를 보여줍니다. 이 방법을 사용하면 다운로드 중, 완료, 실패 등의 상태를 자동으로 사용자에게 알릴 수 있습니다.
fun downloadFile(context: Context, url: String, title: String, description: String) {
val request = DownloadManager.Request(Uri.parse(url))
.setTitle(title)
.setDescription(description)
.setNotificationVisibility(DownloadManager.Request.VISIBILITY_VISIBLE_NOTIFY_COMPLETED)
.setDestinationInExternalPublicDir(Environment.DIRECTORY_DOWNLOADS, "filename.pdf")
val downloadManager = context.getSystemService(Context.DOWNLOAD_SERVICE) as DownloadManager
val downloadId = downloadManager.enqueue(request)
val query = DownloadManager.Query().setFilterById(downloadId)
val cursor = downloadManager.query(query)
if (cursor != null && cursor.moveToFirst()) {
val columnIndex = cursor.getColumnIndex(DownloadManager.COLUMN_STATUS)
if (columnIndex != -1) {
val status = cursor.getInt(columnIndex)
when (status) {
DownloadManager.STATUS_RUNNING -> {
// 다운로드 중 처리
}
DownloadManager.STATUS_SUCCESSFUL -> {
// 다운로드 완료 처리
}
DownloadManager.STATUS_FAILED -> {
// 다운로드 실패 처리
}
}
} else {
LogUtils.e("DownloadManager", "COLUMN_STATUS not found in cursor")
}
} else {
LogUtils.e("DownloadManager", "Cursor is null or empty")
}
cursor?.close()
}
2. 사용자 정의 알림 사용
파일 다운로드를 직접 관리하는 경우, NotificationManager를 사용하여 직접 사용자에게 다운로드 진행 상태를 알릴 수 있습니다. 이를 통해 다운로드 진행률 표시 막대를 포함하는 사용자 정의 알림을 만들 수 있습니다.
private fun showDownloadNotification(
context: Context,
file: File,
progress: Int,
) {
val channelId = "download_channel"
val notificationManager =
context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
val importance = NotificationManager.IMPORTANCE_DEFAULT
val channel = NotificationChannel(channelId, "Downloads", importance)
notificationManager.createNotificationChannel(channel)
val contentUri =
FileProvider.getUriForFile(context, "${context.packageName}.provider", file)
val intent =
Intent(Intent.ACTION_VIEW).apply {
setDataAndType(contentUri, "application/pdf")
flags = Intent.FLAG_ACTIVITY_NEW_TASK or Intent.FLAG_GRANT_READ_URI_PERMISSION
}
val pendingIntent =
PendingIntent.getActivity(
context,
0,
intent,
PendingIntent.FLAG_UPDATE_CURRENT or PendingIntent.FLAG_IMMUTABLE,
)
val notificationBuilder =
NotificationCompat.Builder(context, channelId).setContentTitle("Analysis PDF Download")
.setSmallIcon(android.R.drawable.stat_sys_download)
.setPriority(NotificationCompat.PRIORITY_DEFAULT).setOngoing(progress < 100)
.setProgress(100, progress, false).setAutoCancel(true)
.setContentIntent(pendingIntent)
if (progress == 0 || progress == 50) {
notificationBuilder.setContentText("Download in progress: $progress%")
notificationManager.notify(1, notificationBuilder.build())
} else if (progress == 100) {
notificationBuilder.setContentText("Download complete").setProgress(0, 0, false)
.setOngoing(false)
.setSmallIcon(android.R.drawable.stat_sys_download_done)
notificationManager.notify(1, notificationBuilder.build())
}
}
저는 서버에서 제공해주는 데이터의 형태가 uri가 아닌 file의 형태였기 때문에 2번째 방법을 사용해서 처리했습니다.
결론적으로, 다루는 리소스의 형태는 각 방법의 사용 및 구현에 큰 영향을 미치며, 개발 과정에서 이를 고려해 선택해야 합니다. DownloadManager는 웹 기반의 파일 다운로드에 최적화된 서비스를 제공하며, NotificationManager는 더 넓은 범위의 사용자 정의 기능과 함께 다양한 형태의 데이터 처리가 가능합니다.
'질문 정리' 카테고리의 다른 글
Compose BackHander, 앱 종료가 안되는 이유 (0) | 2024.06.05 |
---|---|
State와 StateFlow 차이 (0) | 2024.05.30 |
안드로이드 컴포즈 페이스북 로그인 연동 정리 (0) | 2024.05.26 |
위임하는 방식(By)과 직접 할당하는 방식(=)의 차이는 무엇일까? (0) | 2024.05.24 |
안드로이드 컴포즈 구글 로그인 연동 정리 (0) | 2024.04.28 |