Made the TagEditor more reliable.
This commit is contained in:
parent
fc4b3846c5
commit
ffa329d978
7 changed files with 324 additions and 250 deletions
|
|
@ -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<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
|
||||
private final int delay;
|
||||
private WeakReference<Context> contextWeakReference;
|
||||
private WeakReference<Dialog> 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);
|
||||
}
|
||||
|
|
@ -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<Toast> toastWeakReference;
|
||||
private final WeakReference<Activity> 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();
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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<String> 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<FieldKey, String> fieldKeyValueMap) {
|
||||
writeValuesToFiles(fieldKeyValueMap, null, false);
|
||||
protected void writeValuesToFiles(@NonNull final Map<FieldKey, String> fieldKeyValueMap, @Nullable final ArtworkInfo artworkInfo) {
|
||||
Util.hideSoftKeyboard(this);
|
||||
|
||||
new WriteTagsAsyncTask(this).execute(new WriteTagsAsyncTask.LoadingInfo(getSongPaths(), fieldKeyValueMap, artworkInfo));
|
||||
}
|
||||
|
||||
protected void writeValuesToFiles(@NonNull final Map<FieldKey, String> 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<WriteTagsAsyncTask.LoadingInfo, Integer, String[]> {
|
||||
Context applicationContext;
|
||||
|
||||
public WriteTagsAsyncTask(Context context) {
|
||||
super(context);
|
||||
applicationContext = context;
|
||||
}
|
||||
});
|
||||
|
||||
@Override
|
||||
protected String[] doInBackground(LoadingInfo... params) {
|
||||
try {
|
||||
AudioFile audioFile = AudioFileIO.read(new File(songPath));
|
||||
LoadingInfo info = params[0];
|
||||
|
||||
Artwork artwork = null;
|
||||
File albumArtFile = null;
|
||||
if (info.artworkInfo != null && info.artworkInfo.artwork != null) {
|
||||
try {
|
||||
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<FieldKey, String> entry : fieldKeyValueMap.entrySet()) {
|
||||
|
||||
if (info.fieldKeyValueMap != null) {
|
||||
for (Map.Entry<FieldKey, String> entry : info.fieldKeyValueMap.entrySet()) {
|
||||
try {
|
||||
tag.setField(entry.getKey(), entry.getValue());
|
||||
} catch (NumberFormatException e) {
|
||||
tag.deleteField(entry.getKey());
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
}
|
||||
}
|
||||
if (deleteArtwork) {
|
||||
}
|
||||
|
||||
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));
|
||||
}
|
||||
});
|
||||
if (deleteArtwork) {
|
||||
MusicUtil.deleteAlbumArt(AbsTagEditorActivity.this, getId());
|
||||
} else if (artwork != null) {
|
||||
// AlbumTagEditorActivity already inserts the album cover for us
|
||||
}
|
||||
rescanMediaAndQuitOnFinish();
|
||||
}
|
||||
}).start();
|
||||
}
|
||||
|
||||
private static class FinishOnCompletedMediaScanner implements MediaScannerConnection.MediaScannerConnectionClient {
|
||||
|
||||
private WeakReference<AbsTagEditorActivity> 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);
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public void scan() {
|
||||
connection.connect();
|
||||
return info.filePaths.toArray(new String[info.filePaths.size()]);
|
||||
} catch (Exception e) {
|
||||
e.printStackTrace();
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void dismissDialogAndFinish() {
|
||||
runOnUiThread(new Runnable() {
|
||||
@Override
|
||||
public void run() {
|
||||
progressDialog.dismiss();
|
||||
finish();
|
||||
}
|
||||
});
|
||||
protected Dialog createDialog(@NonNull Context context) {
|
||||
return new MaterialDialog.Builder(context)
|
||||
.title(R.string.writing_files)
|
||||
.cancelable(false)
|
||||
.progress(false, 0)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void rescanMediaAndQuitOnFinish() {
|
||||
String[] toBeScanned = new String[songPaths.size()];
|
||||
toBeScanned = songPaths.toArray(toBeScanned);
|
||||
new FinishOnCompletedMediaScanner(this, toBeScanned).scan();
|
||||
@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<String> filePaths;
|
||||
@Nullable
|
||||
public final Map<FieldKey, String> fieldKeyValueMap;
|
||||
@Nullable
|
||||
private ArtworkInfo artworkInfo;
|
||||
|
||||
private LoadingInfo(Collection<String> filePaths, @Nullable Map<FieldKey, String> fieldKeyValueMap, @Nullable ArtworkInfo artworkInfo) {
|
||||
this.filePaths = filePaths;
|
||||
this.fieldKeyValueMap = fieldKeyValueMap;
|
||||
this.artworkInfo = artworkInfo;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public static class ArtworkInfo {
|
||||
public final int albumId;
|
||||
public final Bitmap artwork;
|
||||
|
||||
public ArtworkInfo(int albumId, Bitmap artwork) {
|
||||
this.albumId = albumId;
|
||||
this.artwork = artwork;
|
||||
}
|
||||
}
|
||||
|
||||
protected int getId() {
|
||||
|
|
|
|||
|
|
@ -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<FieldKey, String> 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<BitmapPaletteWrapper>(4097, 4097) {
|
||||
.into(new SimpleTarget<BitmapPaletteWrapper>() {
|
||||
@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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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<Toast> toastWeakReference;
|
||||
private final WeakReference<Activity> 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<ListSongsAsyncTask.LoadingInfo, Void, ArrayList<Song>> {
|
||||
private static class ListSongsAsyncTask extends ListingFilesDialogAsyncTask<ListSongsAsyncTask.LoadingInfo, Void, ArrayList<Song>> {
|
||||
private WeakReference<Context> contextWeakReference;
|
||||
private WeakReference<OnSongsListedCallback> 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<ListPathsAsyncTask.LoadingInfo, String, String[]> {
|
||||
private static class ListPathsAsyncTask extends ListingFilesDialogAsyncTask<ListPathsAsyncTask.LoadingInfo, String, String[]> {
|
||||
private WeakReference<OnPathsListedCallback> onPathsListedCallbackWeakReference;
|
||||
|
||||
public ListPathsAsyncTask(Context context, OnPathsListedCallback callback) {
|
||||
super(context, R.string.listing_files);
|
||||
super(context);
|
||||
onPathsListedCallbackWeakReference = new WeakReference<>(callback);
|
||||
}
|
||||
|
||||
|
|
@ -753,28 +704,19 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi
|
|||
}
|
||||
}
|
||||
|
||||
private static abstract class DialogAsyncTask<Params, Progress, Result> extends AsyncTask<Params, Progress, Result> {
|
||||
private final int title;
|
||||
private WeakReference<Context> contextWeakReference;
|
||||
private WeakReference<Dialog> dialogWeakReference;
|
||||
private static abstract class ListingFilesDialogAsyncTask<Params, Progress, Result> extends DialogAsyncTask<Params, Progress, Result> {
|
||||
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)
|
||||
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() {
|
||||
|
|
@ -797,32 +739,6 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi
|
|||
}
|
||||
})
|
||||
.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();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -46,7 +46,7 @@
|
|||
<string name="track">Track</string>
|
||||
<string name="track_hint">"Track (2 for track 2 or 3004 for CD3 track 4)"</string>
|
||||
<string name="album_or_artist_empty">The title or artist is empty.</string>
|
||||
<string name="writing_file_number">Writing file</string>
|
||||
<string name="writing_files">Writing files</string>
|
||||
<string name="saving_changes">Saving changes…</string>
|
||||
<string name="saving_to_file">Saving to file…</string>
|
||||
<string name="label_details">Details</string>
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue