2016-06-02 2 views
0

내 앱에서 DownloadManager를 통해 데이터 파일을 다운로드하는 메커니즘을 구현 중입니다. 사용자가 다운로드를 시작하면 진행중인 다운로드를 취소 할 수있는 취소 버튼이 옆에 나타납니다.Android DownloadManager, 백업 파일 및 취소 된 다운로드

이러한 데이터 파일은 서버에서 주기적으로 업데이트되므로 사용자는 수시로 동일한 파일을 다시 다운로드하려고합니다. 파일 이름은 업데이트를 통해 안정적으로 유지됩니다.

다운로드 중에 사용자가 언제든지 취소를 클릭 할 수 있기 때문에 다운로드가 성공적으로 완료 될 때까지 이전 버전을 유지하려고합니다. 이를 위해 기존 파일의 이름을 바꾼 다음 다운로드를 시작합니다. 사용자가 다운로드를 취소 한 경우 (다운로드가 실패한 경우에도) 백업 파일을 원래 위치로 복원하려고합니다.

if (downloadManager.remove(reference) > 0) { 
    if (destFile.exists()) 
     destFile.delete(); 
    backupFile.renameTo(destFile); 
} 

내가 파일을 새로

는, 이전 파일이 다운로드를 시작하기 전에 이름이 변경됩니다 : 취소 버튼을 클릭하면 취소의 경우를 들어

, 나는 원래 실행하려면 다음 코드를 추가했다. 그러나 다운로드를 취소하면 부분 파일과 백업이 모두 사라집니다.

나는 이미 FileObserver을 사용하여 다운로드 진행 상황을 모니터링하므로 파일 삭제를 감시하고 로그 메시지를 생성하도록 확장했습니다. logcat에서 부분적으로 다운로드 한 파일이 삭제되고 백업의 이름이 변경된 다음 이름이 변경된 백업도 삭제된다는 것을 나타내는 동일한 파일에 대한 두 개의 삭제 이벤트가 표시됩니다.

충분히 생각해 보면, 분명히 DownloadManager는 백그라운드에서 삭제를 처리하기 때문에, 나는 그것이 일어날 것을 지켜봐야 할 필요가 있습니다. 그래서 위의 이벤트 처리기를 수정하여 파일 경로를 목록에 저장하고 아직 파일 작업을 수행하지 않았습니다. 그런 다음 내 FileObserver을 수정하여 삭제 된 모든 파일을 목록과 비교했습니다. 일치하는 경우 백업 파일의 이름을 바꿉니다. 또한 각 작업에 로그 출력을 추가했습니다.

그러나 이벤트 순서는 여전히 동일합니다. 이제 부분적으로 다운로드 한 파일이 다운로드 관리자에 의해 삭제되고 FileObserver이 트리거되어 백업 파일의 이름이 바뀝니다. 그 후에 백업 파일이 삭제됩니다.

다운로드 관리자가 지나치게 많은 것처럼 보입니다. 다운로드가 취소되면 다운로드 한 파일을 삭제 한 다음 실제로 사라 졌는지 확인한 다음 해당 경로의 파일을 계속 찾으면 삭제를 다시 시도합니다.

어떻게하면이 문제를 해결하고 다운로드 관리자가 다운로드하지 않은 파일을 삭제하지 못하게 할 수 있습니까?

답변

0

안드로이드 다운로드 관리자가 기존 파일을 덮어 쓰지 않고 다운로드 대상 자체를 아직 사용할 수있는 이름으로 바꾸지 않음을 이용하여 여러 삭제 문제를 해결했습니다.

파일을 다시 다운로드 할 때 이전 파일을 이동하지 않아도됩니다. 다운로드 관리자는 파일이 이미 있는지 감지하고 다운로드 할 때 다른 이름을 지정합니다. 다운로드가 성공적으로 끝나면 이전 파일을 삭제하고 새 파일의 이름을 바꿉니다.

유일한 도전 과제는 다운로드 관리자가 선택한 파일 이름을 확인하는 것이 었습니다. Android는 이에 대한 명시적인 알림이 부족한 것처럼 보였습니다. 다운로드가 시작될 때 의도가 시작되지 않으므로 다시 FileObserver에 의지해야합니다.

FileObserver.CREATE을 보는 것은 가장 직접적인 방법처럼 보입니다. 그러나이 시점에서 다운로드 목록을 쿼리 할 때 쿼리는 로컬 경로에 대한 null 값을 반환합니다.

그래서 나는 파일에 대한 모든 수정시 발생하는 FileObserver.MODIFY에 의지했습니다. 이미 다운로드 진행률을 표시하는 데이 파일을 사용하고 있으며이 시점에서 로컬 파일이 있어야합니다. 이 이벤트가 다운로드 관리자에 의해 이름이 변경된 파일에 대해 처음으로 발생하면 아직 내 목록에없는 파일 이름이 표시됩니다.

 // File file: the file being downloaded 
     // DownloadInfo info: information about a download in progress 
     /* First progress report for a renamed file */ 
     DownloadManager.Query query = new DownloadManager.Query(); 
     query.setFilterByStatus(~(DownloadManager.STATUS_FAILED | DownloadManager.STATUS_SUCCESSFUL)); 
     Cursor cursor = downloadManager.query(query); 
     if (!cursor.moveToFirst()) { 
      cursor.close(); 
      return; 
     } 
     do { 
      Long reference = cursor.getLong(cursor.getColumnIndex(DownloadManager.COLUMN_ID)); 
      String path = cursor.getString(cursor.getColumnIndex(DownloadManager.COLUMN_LOCAL_FILENAME)); 
      if (file.equals(new File(path))) { 
       info = downloadsByReference.get(reference); 
       if (info != null) { 
        info.downloadFile = file; 
        downloadsByFile.put(info.downloadFile, info); 
       } 
      } 
     } while (cursor.moveToNext()); 
     cursor.close(); 

진행의 각 다운로드가 다른 사람의 사이에서, 참조를 모두 파일 이름을 가지고하는 DownloadInfo 인스턴스에 의해 설명 : 나는 다음 코드를 실행합니다. 나는 3 Map의에 보관 :

  • downloadsByReference는 다음과 같이 다운로드 관리자의 ID를 사용하는
  • downloadsByFile가 키
  • downloadsByUri로 로컬 파일을 사용하는 키

로 URI를 사용하는 키 다운로드가 끝나면 두 파일 이름을 얻기 위해 downloadsByReference에 ID를 찾습니다. 파일이 다를 경우 이전 파일을 삭제 한 다음 새 파일의 이름을 변경합니다.