77import android .content .Context ;
88import android .content .Intent ;
99import android .content .IntentFilter ;
10+ import android .database .Cursor ;
1011import android .net .Uri ;
1112import android .os .Build ;
1213import android .os .Bundle ;
14+ import android .os .Handler ;
15+ import android .os .Looper ;
16+ import android .os .Message ;
1317import android .util .Log ;
1418import android .view .MenuItem ;
1519import android .view .View ;
2731import java .io .IOException ;
2832import java .io .InputStream ;
2933import java .io .OutputStream ;
34+ import java .util .concurrent .ExecutorService ;
35+ import java .util .concurrent .Executors ;
3036import java .util .zip .ZipEntry ;
3137import java .util .zip .ZipInputStream ;
3238
3743public class DownloadActivity extends BaseActivity {
3844
3945 private static final String TAG = DownloadActivity .class .getSimpleName ();
46+ private static final int UPDATE_DOWNLOAD_PROGRESS = 1 ;
4047
4148 private static final String OPENANDROMAPS_MAP_HOST = "ftp.gwdg.de" ;
4249 private static final String OPENANDROMAPS_THEME_HOST = "www.openandromaps.org" ;
@@ -50,9 +57,10 @@ public class DownloadActivity extends BaseActivity {
5057 private Uri downloadUri ;
5158 private DownloadType downloadType = DownloadType .MAP ;
5259 private ActivityDownloadBinding binding ;
53- private long downloadID ;
60+ private Long downloadId = null ;
5461 private DownloadManager downloadManager ;
5562 private DownloadBroadcastReceiver downloadBroadcastReceiver ;
63+ private final ExecutorService executor = Executors .newFixedThreadPool (1 );
5664
5765 @ SuppressLint ("UnspecifiedRegisterReceiverFlag" )
5866 @ Override
@@ -109,7 +117,9 @@ protected void onCreate(Bundle savedInstanceState) {
109117
110118 binding .downloadInfo .setText (downloadUri .toString ());
111119 binding .startDownloadButton .setOnClickListener ((view ) -> {
112- startDownload ();
120+ if (downloadId == null ) {
121+ startDownload ();
122+ }
113123 });
114124 } else {
115125 binding .downloadInfo .setText (R .string .no_download_uri_found );
@@ -147,7 +157,7 @@ public void startDownload() {
147157 }
148158 }
149159
150- var filesDir = getFilesDir ( ).toPath ();
160+ var filesDir = getExternalFilesDir ( null ).toPath ();
151161 var downloadDir = filesDir .resolve (downloadType .subdir );
152162 downloadDir .toFile ().mkdir ();
153163 var filename = downloadUri .getLastPathSegment ();
@@ -159,6 +169,7 @@ public void startDownload() {
159169 .setMessage (getString (downloadType .getOverwriteMessageId (), filename ))
160170 .setPositiveButton (android .R .string .ok , (dialog , which ) -> {
161171 file .toFile ().delete ();
172+ dialog .dismiss ();
162173 startDownload ();
163174 })
164175 .setNegativeButton (android .R .string .cancel , null )
@@ -175,56 +186,72 @@ public void startDownload() {
175186 .setAllowedOverMetered (true )
176187 .setAllowedOverRoaming (true );
177188 downloadManager = (DownloadManager ) getSystemService (DOWNLOAD_SERVICE );
178- downloadID = downloadManager .enqueue (request );
179- observeProgress ( downloadManager , downloadID );
189+ downloadId = downloadManager .enqueue (request );
190+ observeDownload ( );
180191 }
181192
182- private void observeProgress (DownloadManager downloadManager , long downloadId ) {
183- var query = new DownloadManager .Query ().setFilterById (downloadId );
184- var downloading = true ;
193+ private void observeDownload () {
194+ binding .progressBar .setVisibility (View .VISIBLE );
185195 binding .progressBar .setIndeterminate (false );
186196 binding .progressBar .setMax (100 );
187-
188- while (downloading ) {
189- binding .progressBar .setVisibility (View .VISIBLE );
190- try (var cursor = downloadManager .query (query )) {
191- if (cursor .moveToFirst ()) {
192- var statusIndex = cursor .getColumnIndex (DownloadManager .COLUMN_STATUS );
193- var progressIndex = cursor .getColumnIndex (DownloadManager .COLUMN_BYTES_DOWNLOADED_SO_FAR );
194- var totalIndex = cursor .getColumnIndex (DownloadManager .COLUMN_TOTAL_SIZE_BYTES );
195-
196- int status = cursor .getInt (statusIndex );
197- long downloaded = cursor .getLong (progressIndex );
198- long total = cursor .getLong (totalIndex );
199- int progress = (int ) ((downloaded * 100L ) / total );
200-
201- if (status == DownloadManager .STATUS_SUCCESSFUL || status == DownloadManager .STATUS_FAILED ) {
202- downloading = false ;
203- }
204-
205- if (total >= 0 ) {
206- binding .progressBar .setProgress (progress );
197+ binding .progressBar .setProgress (0 );
198+
199+ executor .execute (() -> {
200+ int progress = 0 ;
201+ boolean isDownloadFinished = false ;
202+ while (!isDownloadFinished ) {
203+ try (Cursor cursor = downloadManager .query (new DownloadManager .Query ().setFilterById (downloadId ))) {
204+ if (cursor .moveToFirst ()) {
205+ int downloadStatus = cursor .getInt (cursor .getColumnIndexOrThrow (DownloadManager .COLUMN_STATUS ));
206+ switch (downloadStatus ) {
207+ case DownloadManager .STATUS_RUNNING :
208+ long totalBytes = cursor .getLong (cursor .getColumnIndexOrThrow (DownloadManager .COLUMN_TOTAL_SIZE_BYTES ));
209+ if (totalBytes > 0 ) {
210+ long downloadedBytes = cursor .getLong (cursor .getColumnIndexOrThrow (DownloadManager .COLUMN_BYTES_DOWNLOADED_SO_FAR ));
211+ progress = (int ) (downloadedBytes * 100 / totalBytes );
212+ }
213+
214+ break ;
215+ case DownloadManager .STATUS_SUCCESSFUL :
216+ progress = 100 ;
217+ isDownloadFinished = true ;
218+ break ;
219+ case DownloadManager .STATUS_PAUSED :
220+ case DownloadManager .STATUS_PENDING :
221+ break ;
222+ case DownloadManager .STATUS_FAILED :
223+ isDownloadFinished = true ;
224+ break ;
225+ }
226+ var message = Message .obtain ();
227+ message .what = UPDATE_DOWNLOAD_PROGRESS ;
228+ message .arg1 = progress ;
229+ mainHandler .sendMessage (message );
207230 }
208231 }
209232 }
233+ });
234+ }
210235
211- try {
212- Thread .sleep (1000 ); // Wait for 1 second before querying again
213- } catch (InterruptedException ignored ) {
214-
236+ private final Handler mainHandler = new Handler (Looper .getMainLooper (), new Handler .Callback () {
237+ @ Override
238+ public boolean handleMessage (@ NonNull Message msg ) {
239+ if (msg .what == UPDATE_DOWNLOAD_PROGRESS ) {
240+ int downloadProgress = msg .arg1 ;
241+ binding .progressBar .setProgress (downloadProgress );
215242 }
243+ return true ;
216244 }
217- binding .progressBar .setVisibility (View .GONE );
218- }
245+ });
219246
220247 private class DownloadBroadcastReceiver extends BroadcastReceiver {
221248 @ Override
222249 public void onReceive (Context context , Intent intent ) {
223250 var id = intent .getLongExtra (DownloadManager .EXTRA_DOWNLOAD_ID , -1 );
224- if (downloadID != id ) {
251+ if (downloadId != id ) {
225252 return ;
226253 }
227- try (var cursor = downloadManager .query (new DownloadManager .Query ().setFilterById (downloadID ))) {
254+ try (var cursor = downloadManager .query (new DownloadManager .Query ().setFilterById (downloadId ))) {
228255 if (cursor .moveToFirst ()) {
229256 int status = cursor .getInt (cursor .getColumnIndexOrThrow (DownloadManager .COLUMN_STATUS ));
230257 if (status == DownloadManager .STATUS_SUCCESSFUL ) {
@@ -237,6 +264,8 @@ public void onReceive(Context context, Intent intent) {
237264 }
238265
239266 private void downloadEnded (Uri downloadedUri ) {
267+ executor .shutdown ();
268+ mainHandler .removeCallbacksAndMessages (null );
240269 var destinationDir = downloadType .getDirectoryUri ();
241270 if (destinationDir == null ) {
242271 if (downloadType .isExtractMapFromZIP ()) {
@@ -286,6 +315,7 @@ private void downloadEnded(Uri downloadedUri) {
286315 }
287316
288317 binding .progressBar .setVisibility (View .GONE );
318+ downloadId = null ;
289319 Toast .makeText (this , downloadType .getSuccessMessageId (), Toast .LENGTH_LONG ).show ();
290320 }
291321
0 commit comments