From ffa329d978e15870e375372688684217955c26d3 Mon Sep 17 00:00:00 2001 From: Karim Abou Zeid Date: Sun, 27 Mar 2016 23:51:51 +0200 Subject: [PATCH] Made the TagEditor more reliable. --- .../gramophone/misc/DialogAsyncTask.java | 104 ++++++++ ...teToastMediaScannerCompletionListener.java | 59 +++++ .../tageditor/AbsTagEditorActivity.java | 222 ++++++++++-------- .../tageditor/AlbumTagEditorActivity.java | 31 +-- .../tageditor/SongTagEditorActivity.java | 2 +- .../mainactivity/folders/FoldersFragment.java | 160 +++---------- app/src/main/res/values/strings.xml | 2 +- 7 files changed, 327 insertions(+), 253 deletions(-) create mode 100644 app/src/main/java/com/kabouzeid/gramophone/misc/DialogAsyncTask.java create mode 100644 app/src/main/java/com/kabouzeid/gramophone/misc/UpdateToastMediaScannerCompletionListener.java diff --git a/app/src/main/java/com/kabouzeid/gramophone/misc/DialogAsyncTask.java b/app/src/main/java/com/kabouzeid/gramophone/misc/DialogAsyncTask.java new file mode 100644 index 00000000..8b60cded --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/misc/DialogAsyncTask.java @@ -0,0 +1,104 @@ +package com.kabouzeid.gramophone.misc; + +import android.app.Dialog; +import android.content.Context; +import android.os.AsyncTask; +import android.os.Handler; +import android.support.annotation.NonNull; +import android.support.annotation.Nullable; + +import java.lang.ref.WeakReference; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ +public abstract class DialogAsyncTask extends AsyncTask { + private final int delay; + private WeakReference contextWeakReference; + private WeakReference dialogWeakReference; + + private boolean supposedToBeDismissed; + + public DialogAsyncTask(Context context) { + this(context, 0); + } + + public DialogAsyncTask(Context context, int showDelay) { + this.delay = showDelay; + contextWeakReference = new WeakReference<>(context); + dialogWeakReference = new WeakReference<>(null); + } + + @Override + protected void onPreExecute() { + super.onPreExecute(); + if (delay > 0) { + new Handler().postDelayed(new Runnable() { + @Override + public void run() { + initAndShowDialog(); + } + }, delay); + } else { + initAndShowDialog(); + } + } + + private void initAndShowDialog() { + Context context = getContext(); + if (!supposedToBeDismissed && context != null) { + Dialog dialog = createDialog(context); + dialogWeakReference = new WeakReference<>(dialog); + dialog.show(); + } + } + + @SuppressWarnings("unchecked") + @Override + protected void onProgressUpdate(Progress... values) { + super.onProgressUpdate(values); + Dialog dialog = getDialog(); + if (dialog != null) { + onProgressUpdate(dialog, values); + } + } + + @SuppressWarnings("unchecked") + protected void onProgressUpdate(@NonNull Dialog dialog, Progress... values) { + } + + @Nullable + protected Context getContext() { + return contextWeakReference.get(); + } + + @Nullable + protected Dialog getDialog() { + return dialogWeakReference.get(); + } + + @Override + protected void onCancelled(Result result) { + super.onCancelled(result); + tryToDismiss(); + } + + @Override + protected void onPostExecute(Result result) { + super.onPostExecute(result); + tryToDismiss(); + } + + private void tryToDismiss() { + supposedToBeDismissed = true; + try { + Dialog dialog = getDialog(); + if (dialog != null) + dialog.dismiss(); + } catch (Exception e) { + e.printStackTrace(); + } + } + + protected abstract Dialog createDialog(@NonNull Context context); +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/misc/UpdateToastMediaScannerCompletionListener.java b/app/src/main/java/com/kabouzeid/gramophone/misc/UpdateToastMediaScannerCompletionListener.java new file mode 100644 index 00000000..72a5b029 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/misc/UpdateToastMediaScannerCompletionListener.java @@ -0,0 +1,59 @@ +package com.kabouzeid.gramophone.misc; + +import android.annotation.SuppressLint; +import android.app.Activity; +import android.media.MediaScannerConnection; +import android.net.Uri; +import android.widget.Toast; + +import com.kabouzeid.gramophone.R; + +import java.lang.ref.WeakReference; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ +public class UpdateToastMediaScannerCompletionListener implements MediaScannerConnection.OnScanCompletedListener { + int scanned = 0; + int failed = 0; + + private final String[] toBeScanned; + + private final String scannedFiles; + private final String couldNotScanFiles; + + private final WeakReference toastWeakReference; + private final WeakReference activityWeakReference; + + @SuppressLint("ShowToast") + public UpdateToastMediaScannerCompletionListener(Activity activity, String[] toBeScanned) { + this.toBeScanned = toBeScanned; + scannedFiles = activity.getString(R.string.scanned_files); + couldNotScanFiles = activity.getString(R.string.could_not_scan_files); + toastWeakReference = new WeakReference<>(Toast.makeText(activity, "", Toast.LENGTH_SHORT)); + activityWeakReference = new WeakReference<>(activity); + } + + @Override + public void onScanCompleted(final String path, final Uri uri) { + Activity activity = activityWeakReference.get(); + if (activity != null) { + activity.runOnUiThread(new Runnable() { + @Override + public void run() { + Toast toast = toastWeakReference.get(); + if (toast != null) { + if (uri == null) { + failed++; + } else { + scanned++; + } + String text = " " + String.format(scannedFiles, scanned, toBeScanned.length) + (failed > 0 ? " " + String.format(couldNotScanFiles, failed) : ""); + toast.setText(text); + toast.show(); + } + } + }); + } + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java index a13a3939..6b67e479 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java @@ -1,13 +1,14 @@ package com.kabouzeid.gramophone.ui.activities.tageditor; +import android.app.Activity; +import android.app.Dialog; import android.app.SearchManager; +import android.content.Context; import android.content.Intent; -import android.content.pm.ActivityInfo; import android.graphics.Bitmap; import android.graphics.BitmapFactory; import android.media.MediaScannerConnection; import android.net.Uri; -import android.os.Build; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; @@ -26,7 +27,9 @@ import com.kabouzeid.appthemehelper.ThemeStore; import com.kabouzeid.appthemehelper.util.ColorUtil; import com.kabouzeid.appthemehelper.util.TintHelper; import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.misc.DialogAsyncTask; import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks; +import com.kabouzeid.gramophone.misc.UpdateToastMediaScannerCompletionListener; import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity; import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.Util; @@ -41,10 +44,12 @@ import org.jaudiotagger.tag.FieldKey; import org.jaudiotagger.tag.Tag; import org.jaudiotagger.tag.TagException; import org.jaudiotagger.tag.images.Artwork; +import org.jaudiotagger.tag.images.ArtworkFactory; import java.io.File; +import java.io.FileOutputStream; import java.io.IOException; -import java.lang.ref.WeakReference; +import java.util.Collection; import java.util.List; import java.util.Map; @@ -89,7 +94,6 @@ public abstract class AbsTagEditorActivity extends AbsBaseActivity { } }; private List songPaths; - private MaterialDialog progressDialog; @Override protected void onCreate(Bundle savedInstanceState) { @@ -271,133 +275,145 @@ public abstract class AbsTagEditorActivity extends AbsBaseActivity { setTaskDescriptionColor(paletteColorPrimary); } - protected void writeValuesToFiles(@NonNull final Map fieldKeyValueMap) { - writeValuesToFiles(fieldKeyValueMap, null, false); + protected void writeValuesToFiles(@NonNull final Map fieldKeyValueMap, @Nullable final ArtworkInfo artworkInfo) { + Util.hideSoftKeyboard(this); + + new WriteTagsAsyncTask(this).execute(new WriteTagsAsyncTask.LoadingInfo(getSongPaths(), fieldKeyValueMap, artworkInfo)); } - protected void writeValuesToFiles(@NonNull final Map fieldKeyValueMap, @Nullable final Artwork artwork, final boolean deleteArtwork) { - Util.hideSoftKeyboard(this); - final String writingFileStr = getResources().getString(R.string.writing_file_number); - progressDialog = new MaterialDialog.Builder(AbsTagEditorActivity.this) - .title(R.string.saving_changes) - .cancelable(false) - .progress(true, 0) - .build(); - if (Build.VERSION.SDK_INT >= 18) - setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LOCKED); - progressDialog.show(); - new Thread(new Runnable() { - @Override - public void run() { - for (int i = 0; i < songPaths.size(); i++) { - String songPath = songPaths.get(i); - final int finalI = i; - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.setContent(writingFileStr + " " + ((finalI + 1) + "/" + songPaths.size())); - } - }); + private static class WriteTagsAsyncTask extends DialogAsyncTask { + Context applicationContext; + + public WriteTagsAsyncTask(Context context) { + super(context); + applicationContext = context; + } + + @Override + protected String[] doInBackground(LoadingInfo... params) { + try { + LoadingInfo info = params[0]; + + Artwork artwork = null; + File albumArtFile = null; + if (info.artworkInfo != null && info.artworkInfo.artwork != null) { try { - AudioFile audioFile = AudioFileIO.read(new File(songPath)); + albumArtFile = MusicUtil.createAlbumArtFile(String.valueOf(info.artworkInfo.albumId)).getCanonicalFile(); + info.artworkInfo.artwork.compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(albumArtFile)); + artwork = ArtworkFactory.createArtworkFromFile(albumArtFile); + } catch (IOException e) { + e.printStackTrace(); + } + } + + int counter = 0; + boolean wroteArtwork = false; + boolean deletedArtwork = false; + for (String filePath : info.filePaths) { + publishProgress(++counter, info.filePaths.size()); + try { + AudioFile audioFile = AudioFileIO.read(new File(filePath)); Tag tag = audioFile.getTagOrCreateAndSetDefault(); - for (Map.Entry entry : fieldKeyValueMap.entrySet()) { - try { - tag.setField(entry.getKey(), entry.getValue()); - } catch (NumberFormatException e) { - tag.deleteField(entry.getKey()); + + if (info.fieldKeyValueMap != null) { + for (Map.Entry entry : info.fieldKeyValueMap.entrySet()) { + try { + tag.setField(entry.getKey(), entry.getValue()); + } catch (Exception e) { + e.printStackTrace(); + } } } - if (deleteArtwork) { - tag.deleteArtworkField(); - } else if (artwork != null) { - tag.deleteArtworkField(); - tag.setField(artwork); + + if (info.artworkInfo != null) { + if (info.artworkInfo.artwork == null) { + tag.deleteArtworkField(); + deletedArtwork = true; + } else if (artwork != null) { + tag.deleteArtworkField(); + tag.setField(artwork); + wroteArtwork = true; + } } + audioFile.commit(); - } catch (@NonNull CannotReadException | IOException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) { - Log.e(TAG, "Error while reading audio file.", e); - } catch (CannotWriteException e) { - Log.e(TAG, "Error while writing audio file.", e); + } catch (@NonNull CannotReadException | IOException | CannotWriteException | TagException | ReadOnlyFileException | InvalidAudioFrameException e) { + e.printStackTrace(); } } - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.setContent(getString(R.string.rescanning_media)); + + Context context = getContext(); + if (context != null) { + if (wroteArtwork) { + MusicUtil.insertAlbumArt(context, info.artworkInfo.albumId, albumArtFile.getPath()); + } else if (deletedArtwork) { + MusicUtil.deleteAlbumArt(context, info.artworkInfo.albumId); } - }); - if (deleteArtwork) { - MusicUtil.deleteAlbumArt(AbsTagEditorActivity.this, getId()); - } else if (artwork != null) { - // AlbumTagEditorActivity already inserts the album cover for us } - rescanMediaAndQuitOnFinish(); + + return info.filePaths.toArray(new String[info.filePaths.size()]); + } catch (Exception e) { + e.printStackTrace(); + return null; } - }).start(); - } - - private static class FinishOnCompletedMediaScanner implements MediaScannerConnection.MediaScannerConnectionClient { - - private WeakReference activityWeakReference; - private MediaScannerConnection connection; - private String[] toBeScanned; - private int position; - - - private FinishOnCompletedMediaScanner(AbsTagEditorActivity activity, String[] toBeScanned) { - activityWeakReference = new WeakReference<>(activity); - this.toBeScanned = toBeScanned; - connection = new MediaScannerConnection(activity.getApplicationContext(), this); - } - - public void scan() { - connection.connect(); } @Override - public void onMediaScannerConnected() { - scanNextPath(); + protected void onPostExecute(String[] toBeScanned) { + super.onPostExecute(toBeScanned); + scan(toBeScanned); } @Override - public void onScanCompleted(String path, Uri uri) { - scanNextPath(); + protected void onCancelled(String[] toBeScanned) { + super.onCancelled(toBeScanned); + scan(toBeScanned); } - private void scanNextPath() { - if (position < toBeScanned.length) { - connection.scanFile(toBeScanned[position], null); - } - checkIsDone(); - position++; + private void scan(String[] toBeScanned) { + Context context = getContext(); + MediaScannerConnection.scanFile(applicationContext, toBeScanned, null, context instanceof Activity ? new UpdateToastMediaScannerCompletionListener((Activity) context, toBeScanned) : null); } - private void checkIsDone() { - if (position >= toBeScanned.length - 1) { - connection.disconnect(); - AbsTagEditorActivity activity = activityWeakReference.get(); - if (activity != null) { - activity.dismissDialogAndFinish(); - } + @Override + protected Dialog createDialog(@NonNull Context context) { + return new MaterialDialog.Builder(context) + .title(R.string.writing_files) + .cancelable(false) + .progress(false, 0) + .build(); + } + + @Override + protected void onProgressUpdate(@NonNull Dialog dialog, Integer... values) { + super.onProgressUpdate(dialog, values); + ((MaterialDialog) dialog).setMaxProgress(values[1]); + ((MaterialDialog) dialog).setProgress(values[0]); + } + + public static class LoadingInfo { + public final Collection filePaths; + @Nullable + public final Map fieldKeyValueMap; + @Nullable + private ArtworkInfo artworkInfo; + + private LoadingInfo(Collection filePaths, @Nullable Map fieldKeyValueMap, @Nullable ArtworkInfo artworkInfo) { + this.filePaths = filePaths; + this.fieldKeyValueMap = fieldKeyValueMap; + this.artworkInfo = artworkInfo; } } } - public void dismissDialogAndFinish() { - runOnUiThread(new Runnable() { - @Override - public void run() { - progressDialog.dismiss(); - finish(); - } - }); - } + public static class ArtworkInfo { + public final int albumId; + public final Bitmap artwork; - private void rescanMediaAndQuitOnFinish() { - String[] toBeScanned = new String[songPaths.size()]; - toBeScanned = songPaths.toArray(toBeScanned); - new FinishOnCompletedMediaScanner(this, toBeScanned).scan(); + public ArtworkInfo(int albumId, Bitmap artwork) { + this.albumId = albumId; + this.artwork = artwork; + } } protected int getId() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AlbumTagEditorActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AlbumTagEditorActivity.java index 06ee068c..1aa4841d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AlbumTagEditorActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AlbumTagEditorActivity.java @@ -10,7 +10,6 @@ import android.support.annotation.NonNull; import android.text.Editable; import android.text.TextUtils; import android.text.TextWatcher; -import android.util.Log; import android.widget.EditText; import android.widget.Toast; @@ -28,16 +27,10 @@ import com.kabouzeid.gramophone.lastfm.rest.model.LastFmAlbum; import com.kabouzeid.gramophone.loader.AlbumLoader; import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.util.LastFMUtil; -import com.kabouzeid.gramophone.util.MusicUtil; import com.kabouzeid.gramophone.util.PhonographColorUtil; import org.jaudiotagger.tag.FieldKey; -import org.jaudiotagger.tag.images.Artwork; -import org.jaudiotagger.tag.images.ArtworkFactory; -import java.io.File; -import java.io.FileOutputStream; -import java.io.IOException; import java.util.ArrayList; import java.util.EnumMap; import java.util.List; @@ -45,6 +38,7 @@ import java.util.Map; import butterknife.Bind; import butterknife.ButterKnife; +import hugo.weaving.DebugLog; import retrofit2.Call; import retrofit2.Callback; import retrofit2.Response; @@ -169,7 +163,6 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text @Override protected void save() { - Artwork artwork = null; Map fieldKeyValueMap = new EnumMap<>(FieldKey.class); fieldKeyValueMap.put(FieldKey.ALBUM, albumTitle.getText().toString()); //android seems not to recognize album_artist field so we additionally write the normal artist field @@ -178,18 +171,7 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text fieldKeyValueMap.put(FieldKey.GENRE, genre.getText().toString()); fieldKeyValueMap.put(FieldKey.YEAR, year.getText().toString()); - File albumArtFile = MusicUtil.createAlbumArtFile(String.valueOf(getId())); - - if (albumArtBitmap != null) { - try { - albumArtBitmap.compress(Bitmap.CompressFormat.PNG, 0, new FileOutputStream(albumArtFile)); - artwork = ArtworkFactory.createArtworkFromFile(albumArtFile); - MusicUtil.insertAlbumArt(this, getId(), albumArtFile.getAbsolutePath()); - } catch (IOException e) { - Log.e(TAG, "error while trying to create the artwork from file", e); - } - } - writeValuesToFiles(fieldKeyValueMap, artwork, deleteAlbumArt); + writeValuesToFiles(fieldKeyValueMap, deleteAlbumArt ? new ArtworkInfo(getId(), null) : albumArtBitmap == null ? null : new ArtworkInfo(getId(), albumArtBitmap)); } @Override @@ -216,7 +198,7 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text .transcode(new BitmapPaletteTranscoder(AlbumTagEditorActivity.this), BitmapPaletteWrapper.class) .diskCacheStrategy(DiskCacheStrategy.NONE) .skipMemoryCache(true) - .into(new SimpleTarget(4097, 4097) { + .into(new SimpleTarget() { @Override public void onLoadFailed(Exception e, Drawable errorDrawable) { super.onLoadFailed(e, errorDrawable); @@ -251,6 +233,7 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text dataChanged(); } + @DebugLog private static Bitmap getResizedAlbumCover(@NonNull Bitmap src, int maxForSmallerSize) { int width = src.getWidth(); int height = src.getHeight(); @@ -274,11 +257,7 @@ public class AlbumTagEditorActivity extends AbsTagEditorActivity implements Text dstHeight = maxForSmallerSize; } - Bitmap scaledBitmap = Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false); - if (scaledBitmap != src) { - src.recycle(); - } - return scaledBitmap; + return Bitmap.createScaledBitmap(src, dstWidth, dstHeight, false); } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/SongTagEditorActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/SongTagEditorActivity.java index 7f3b470e..74a7f522 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/SongTagEditorActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/SongTagEditorActivity.java @@ -98,7 +98,7 @@ public class SongTagEditorActivity extends AbsTagEditorActivity implements TextW fieldKeyValueMap.put(FieldKey.GENRE, genre.getText().toString()); fieldKeyValueMap.put(FieldKey.YEAR, year.getText().toString()); fieldKeyValueMap.put(FieldKey.TRACK, trackNumber.getText().toString()); - writeValuesToFiles(fieldKeyValueMap); + writeValuesToFiles(fieldKeyValueMap, null); } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/folders/FoldersFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/folders/FoldersFragment.java index eab0990d..8dd5125a 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/folders/FoldersFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/folders/FoldersFragment.java @@ -1,20 +1,14 @@ package com.kabouzeid.gramophone.ui.fragments.mainactivity.folders; -import android.annotation.SuppressLint; -import android.app.Activity; import android.app.Dialog; import android.content.Context; import android.content.DialogInterface; import android.media.MediaScannerConnection; -import android.net.Uri; -import android.os.AsyncTask; import android.os.Bundle; import android.os.Environment; -import android.os.Handler; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.annotation.StringRes; import android.support.design.widget.AppBarLayout; import android.support.design.widget.CoordinatorLayout; import android.support.design.widget.Snackbar; @@ -46,6 +40,8 @@ import com.kabouzeid.gramophone.helper.MusicPlayerRemote; import com.kabouzeid.gramophone.helper.menu.SongMenuHelper; import com.kabouzeid.gramophone.helper.menu.SongsMenuHelper; import com.kabouzeid.gramophone.interfaces.CabHolder; +import com.kabouzeid.gramophone.misc.DialogAsyncTask; +import com.kabouzeid.gramophone.misc.UpdateToastMediaScannerCompletionListener; import com.kabouzeid.gramophone.misc.WrappedAsyncTaskLoader; import com.kabouzeid.gramophone.model.Song; import com.kabouzeid.gramophone.ui.activities.MainActivity; @@ -485,52 +481,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi if (toBeScanned == null || toBeScanned.length < 1) { Toast.makeText(getActivity(), R.string.nothing_to_scan, Toast.LENGTH_SHORT).show(); } else { - MediaScannerConnection.scanFile(getActivity().getApplicationContext(), toBeScanned, null, new UpdateToastCompletionListener(getActivity(), toBeScanned)); - } - } - - private static class UpdateToastCompletionListener implements MediaScannerConnection.OnScanCompletedListener { - int scanned = 0; - int failed = 0; - - private final String[] toBeScanned; - - private final String scannedFiles; - private final String couldNotScanFiles; - - private final WeakReference toastWeakReference; - private final WeakReference activityWeakReference; - - @SuppressLint("ShowToast") - public UpdateToastCompletionListener(Activity activity, String[] toBeScanned) { - this.toBeScanned = toBeScanned; - scannedFiles = activity.getString(R.string.scanned_files); - couldNotScanFiles = activity.getString(R.string.could_not_scan_files); - toastWeakReference = new WeakReference<>(Toast.makeText(activity, "", Toast.LENGTH_SHORT)); - activityWeakReference = new WeakReference<>(activity); - } - - @Override - public void onScanCompleted(final String path, final Uri uri) { - Activity activity = activityWeakReference.get(); - if (activity != null) { - activity.runOnUiThread(new Runnable() { - @Override - public void run() { - Toast toast = toastWeakReference.get(); - if (toast != null) { - if (uri == null) { - failed++; - } else { - scanned++; - } - String text = " " + String.format(scannedFiles, scanned, toBeScanned.length) + (failed > 0 ? " " + String.format(couldNotScanFiles, failed) : ""); - toast.setText(text); - toast.show(); - } - } - }); - } + MediaScannerConnection.scanFile(getActivity().getApplicationContext(), toBeScanned, null, new UpdateToastMediaScannerCompletionListener(getActivity(), toBeScanned)); } } @@ -585,13 +536,13 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi } } - private static class ListSongsAsyncTask extends DialogAsyncTask> { + private static class ListSongsAsyncTask extends ListingFilesDialogAsyncTask> { private WeakReference contextWeakReference; private WeakReference callbackWeakReference; private final Object extra; public ListSongsAsyncTask(Context context, Object extra, OnSongsListedCallback callback) { - super(context, R.string.listing_files); + super(context); this.extra = extra; contextWeakReference = new WeakReference<>(context); callbackWeakReference = new WeakReference<>(callback); @@ -668,11 +619,11 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi } } - private static class ListPathsAsyncTask extends DialogAsyncTask { + private static class ListPathsAsyncTask extends ListingFilesDialogAsyncTask { private WeakReference onPathsListedCallbackWeakReference; public ListPathsAsyncTask(Context context, OnPathsListedCallback callback) { - super(context, R.string.listing_files); + super(context); onPathsListedCallbackWeakReference = new WeakReference<>(callback); } @@ -753,76 +704,41 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi } } - private static abstract class DialogAsyncTask extends AsyncTask { - private final int title; - private WeakReference contextWeakReference; - private WeakReference dialogWeakReference; + private static abstract class ListingFilesDialogAsyncTask extends DialogAsyncTask { + public ListingFilesDialogAsyncTask(Context context) { + super(context); + } - private boolean supposedToBeDismissed; - - public DialogAsyncTask(Context context, @StringRes int title) { - contextWeakReference = new WeakReference<>(context); - dialogWeakReference = new WeakReference<>(null); - this.title = title; + public ListingFilesDialogAsyncTask(Context context, int showDelay) { + super(context, showDelay); } @Override - protected void onPreExecute() { - super.onPreExecute(); - new Handler().postDelayed(new Runnable() { - @Override - public void run() { - if (!supposedToBeDismissed && contextWeakReference.get() != null) { - Dialog dialog = new MaterialDialog.Builder(contextWeakReference.get()) - .title(title) - .progress(true, 0) - .progressIndeterminateStyle(true) - .cancelListener(new DialogInterface.OnCancelListener() { - @Override - public void onCancel(DialogInterface dialog) { - cancel(false); - } - }) - .dismissListener(new DialogInterface.OnDismissListener() { - @Override - public void onDismiss(DialogInterface dialog) { - cancel(false); - } - }) - .negativeText(android.R.string.cancel) - .onNegative(new MaterialDialog.SingleButtonCallback() { - @Override - public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { - cancel(false); - } - }) - .show(); - dialogWeakReference = new WeakReference<>(dialog); - } - } - }, 200); - } - - @Override - protected void onCancelled(Result result) { - super.onCancelled(result); - tryToDismiss(); - } - - @Override - protected void onPostExecute(Result result) { - super.onPostExecute(result); - tryToDismiss(); - } - - private void tryToDismiss() { - supposedToBeDismissed = true; - try { - if (dialogWeakReference.get() != null) - dialogWeakReference.get().dismiss(); - } catch (Exception e) { - e.printStackTrace(); - } + protected Dialog createDialog(@NonNull Context context) { + return new MaterialDialog.Builder(context) + .title(R.string.listing_files) + .progress(true, 0) + .progressIndeterminateStyle(true) + .cancelListener(new DialogInterface.OnCancelListener() { + @Override + public void onCancel(DialogInterface dialog) { + cancel(false); + } + }) + .dismissListener(new DialogInterface.OnDismissListener() { + @Override + public void onDismiss(DialogInterface dialog) { + cancel(false); + } + }) + .negativeText(android.R.string.cancel) + .onNegative(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + cancel(false); + } + }) + .show(); } } } \ No newline at end of file diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 54a700e6..8df03601 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -46,7 +46,7 @@ Track "Track (2 for track 2 or 3004 for CD3 track 4)" The title or artist is empty. - Writing file + Writing files Saving changes… Saving to file… Details