Added exception reporting for tag writing failures.

This commit is contained in:
Jan Christian Grünhage 2017-03-28 17:50:21 +02:00
parent bd7cd4d8ef
commit 3374b3f8d0
Signed by: jcgruenhage
GPG key ID: 321A67D9EE8BC3E1
3 changed files with 164 additions and 148 deletions

View file

@ -7,6 +7,11 @@ import android.net.Uri;
import android.os.PowerManager; import android.os.PowerManager;
import android.util.Log; import android.util.Log;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.NotSupportedException;
import com.mpatric.mp3agic.UnsupportedTagException;
import java.io.IOException;
import java.util.List; import java.util.List;
import ly.count.android.sdk.Countly; import ly.count.android.sdk.Countly;
@ -35,8 +40,7 @@ public class ExportAllService extends IntentService {
Log.i(TAG, "Intent sent!"); Log.i(TAG, "Intent sent!");
} }
public ExportAllService() public ExportAllService() {
{
super("AutoGPME-ExportService"); super("AutoGPME-ExportService");
} }
@ -80,7 +84,7 @@ public class ExportAllService extends IntentService {
} else { } else {
Log.i(TAG, "Failed to export Music Track: " + getStringForTrack(lTrack)); Log.i(TAG, "Failed to export Music Track: " + getStringForTrack(lTrack));
} }
} catch (IllegalArgumentException e) { } catch (IllegalArgumentException e) {
if (e.getMessage().contains("Invalid URI:")) { if (e.getMessage().contains("Invalid URI:")) {
/* /*
@ -90,19 +94,14 @@ public class ExportAllService extends IntentService {
*/ */
Log.i(TAG, "Automatic export failed, because the URI is invalid."); Log.i(TAG, "Automatic export failed, because the URI is invalid.");
} else throw e; } else throw e;
} } catch (Exception e) {
finally Countly.sharedInstance().logException(e);
{ e.printStackTrace();
if ( CPULock.isHeld())
{
CPULock.release();
}
} }
} }
} }
} }
if ( CPULock.isHeld()) if (CPULock.isHeld()) {
{
CPULock.release(); CPULock.release();
} }
} }

View file

@ -30,6 +30,12 @@ import android.net.Uri;
import android.os.Bundle; import android.os.Bundle;
import android.support.v4.app.NotificationCompat; import android.support.v4.app.NotificationCompat;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.NotSupportedException;
import com.mpatric.mp3agic.UnsupportedTagException;
import java.io.IOException;
import de.arcus.framework.logger.Logger; import de.arcus.framework.logger.Logger;
import ly.count.android.sdk.Countly; import ly.count.android.sdk.Countly;
import re.jcg.playmusicexporter.R; import re.jcg.playmusicexporter.R;
@ -201,11 +207,16 @@ public class ExportService extends IntentService {
updateNotification(); updateNotification();
// Exports the song // Exports the song
if (playMusicManager.exportMusicTrack(mTrackCurrent, uri, path, PlayMusicExporterPreferences.getFileOverwritePreference())) { try {
Countly.sharedInstance().recordEvent("Exported Song", 1); if (playMusicManager.exportMusicTrack(mTrackCurrent, uri, path, PlayMusicExporterPreferences.getFileOverwritePreference())) {
} else { Countly.sharedInstance().recordEvent("Exported Song", 1);
// Export failed } else {
mTracksFailed ++; // Export failed
mTracksFailed ++;
}
} catch (Exception e) {
Countly.sharedInstance().logException(e);
e.printStackTrace();
} }
} else { } else {
// Export failed // Export failed

View file

@ -44,7 +44,10 @@ import com.mpatric.mp3agic.ID3v2;
import com.mpatric.mp3agic.ID3v22Tag; import com.mpatric.mp3agic.ID3v22Tag;
import com.mpatric.mp3agic.ID3v23Tag; import com.mpatric.mp3agic.ID3v23Tag;
import com.mpatric.mp3agic.ID3v24Tag; import com.mpatric.mp3agic.ID3v24Tag;
import com.mpatric.mp3agic.InvalidDataException;
import com.mpatric.mp3agic.Mp3File; import com.mpatric.mp3agic.Mp3File;
import com.mpatric.mp3agic.NotSupportedException;
import com.mpatric.mp3agic.UnsupportedTagException;
import java.io.ByteArrayOutputStream; import java.io.ByteArrayOutputStream;
import java.io.File; import java.io.File;
@ -138,6 +141,7 @@ public class PlayMusicManager {
/** /**
* The database will be copied to a temp folder to access from the app * The database will be copied to a temp folder to access from the app
*
* @return Gets the temp path to the database * @return Gets the temp path to the database
*/ */
private String getTempDatabasePath() { private String getTempDatabasePath() {
@ -297,6 +301,7 @@ public class PlayMusicManager {
/** /**
* Creates a new PlayMusic manager * Creates a new PlayMusic manager
*
* @param context App context * @param context App context
*/ */
public PlayMusicManager(Context context) { public PlayMusicManager(Context context) {
@ -307,8 +312,9 @@ public class PlayMusicManager {
/** /**
* Loads all needed information and opens the database * Loads all needed information and opens the database
* @throws PlayMusicNotFoundException PlayMusic is not installed *
* @throws NoSuperUserException No super user permissions * @throws PlayMusicNotFoundException PlayMusic is not installed
* @throws NoSuperUserException No super user permissions
* @throws CouldNotOpenDatabaseException Could not open the database * @throws CouldNotOpenDatabaseException Could not open the database
*/ */
public void startUp() throws PlayMusicNotFoundException, NoSuperUserException, CouldNotOpenDatabaseException { public void startUp() throws PlayMusicNotFoundException, NoSuperUserException, CouldNotOpenDatabaseException {
@ -345,7 +351,8 @@ public class PlayMusicManager {
/** /**
* Copies the database to a temp directory and opens it * Copies the database to a temp directory and opens it
* @throws NoSuperUserException No super user permissions *
* @throws NoSuperUserException No super user permissions
* @throws de.arcus.playmusiclib.exceptions.CouldNotOpenDatabaseException Could not open the database * @throws de.arcus.playmusiclib.exceptions.CouldNotOpenDatabaseException Could not open the database
*/ */
private void loadDatabase() throws NoSuperUserException, CouldNotOpenDatabaseException { private void loadDatabase() throws NoSuperUserException, CouldNotOpenDatabaseException {
@ -370,7 +377,8 @@ public class PlayMusicManager {
/** /**
* Reloads the database from PlayMusic * Reloads the database from PlayMusic
* @throws NoSuperUserException No super user permissions *
* @throws NoSuperUserException No super user permissions
* @throws CouldNotOpenDatabaseException Could not open the database * @throws CouldNotOpenDatabaseException Could not open the database
*/ */
public void reloadDatabase() throws NoSuperUserException, CouldNotOpenDatabaseException { public void reloadDatabase() throws NoSuperUserException, CouldNotOpenDatabaseException {
@ -403,6 +411,7 @@ public class PlayMusicManager {
/** /**
* Gets the path to the music track * Gets the path to the music track
*
* @param localCopyPath The local copy path * @param localCopyPath The local copy path
* @return The path to the music file * @return The path to the music file
*/ */
@ -437,6 +446,7 @@ public class PlayMusicManager {
/** /**
* Gets the full path to the artwork * Gets the full path to the artwork
*
* @param artworkPath The artwork path * @param artworkPath The artwork path
* @return The full path to the artwork * @return The full path to the artwork
*/ */
@ -469,12 +479,13 @@ public class PlayMusicManager {
/** /**
* Exports a track to the sd card * Exports a track to the sd card
* @param musicTrack The music track you want to export *
* @param dest The destination path * @param musicTrack The music track you want to export
* @param forceOverwrite Forces overwrite of the destination file * @param dest The destination path
* @param forceOverwrite Forces overwrite of the destination file
* @return Returns whether the export was successful * @return Returns whether the export was successful
*/ */
public boolean exportMusicTrack(MusicTrack musicTrack, String dest, boolean forceOverwrite ) { public boolean exportMusicTrack(MusicTrack musicTrack, String dest, boolean forceOverwrite) throws InvalidDataException, IOException, UnsupportedTagException, NotSupportedException {
// Creates the destination directory // Creates the destination directory
File directory = new File(dest).getParentFile(); File directory = new File(dest).getParentFile();
@ -487,12 +498,13 @@ public class PlayMusicManager {
/** /**
* Exports a track to the sd card * Exports a track to the sd card
* @param musicTrack The music track you want to export *
* @param uri The document tree * @param musicTrack The music track you want to export
* @param forceOverwrite Forces overwrite of the destination file * @param uri The document tree
* @param forceOverwrite Forces overwrite of the destination file
* @return Returns whether the export was successful * @return Returns whether the export was successful
*/ */
public boolean exportMusicTrack(MusicTrack musicTrack, Uri uri, String path, boolean forceOverwrite) { public boolean exportMusicTrack(MusicTrack musicTrack, Uri uri, String path, boolean forceOverwrite) throws InvalidDataException, IOException, UnsupportedTagException, NotSupportedException {
// Check for null // Check for null
if (musicTrack == null) return false; if (musicTrack == null) return false;
@ -504,10 +516,9 @@ public class PlayMusicManager {
String uniqueID = UUID.randomUUID().toString(); String uniqueID = UUID.randomUUID().toString();
if ( forceOverwrite || !isAlreadyThere(uri, path) ) if (forceOverwrite || !isAlreadyThere(uri, path)) {
{
String fileTmp = getTempPath() + uniqueID +"_tmp.mp3"; String fileTmp = getTempPath() + uniqueID + "_tmp.mp3";
// Copy to temp path failed // Copy to temp path failed
if (!SuperUserTools.fileCopy(srcFile, fileTmp)) if (!SuperUserTools.fileCopy(srcFile, fileTmp))
@ -515,7 +526,7 @@ public class PlayMusicManager {
// Encrypt the file // Encrypt the file
if (musicTrack.isEncoded()) { if (musicTrack.isEncoded()) {
String fileTmpCrypt = getTempPath() + uniqueID +"_crypt.mp3"; String fileTmpCrypt = getTempPath() + uniqueID + "_crypt.mp3";
// Encrypts the file // Encrypts the file
if (trackEncrypt(musicTrack, fileTmp, fileTmpCrypt)) { if (trackEncrypt(musicTrack, fileTmp, fileTmpCrypt)) {
@ -530,7 +541,6 @@ public class PlayMusicManager {
} }
String dest; String dest;
Uri copyUri = null; Uri copyUri = null;
if (uri.toString().startsWith("file://")) { if (uri.toString().startsWith("file://")) {
@ -541,19 +551,19 @@ public class PlayMusicManager {
FileTools.directoryCreate(parentDirectory); FileTools.directoryCreate(parentDirectory);
} else { } else {
// Complex uri (Lollipop) // Complex uri (Lollipop)
dest = getTempPath() + uniqueID +"_final.mp3"; dest = getTempPath() + uniqueID + "_final.mp3";
// The root // The root
DocumentFile document = DocumentFile.fromTreeUri(mContext, uri); DocumentFile document = DocumentFile.fromTreeUri(mContext, uri);
// Creates the subdirectories // Creates the subdirectories
String[] directories = path.split("\\/"); String[] directories = path.split("\\/");
for(int i=0; i<directories.length - 1; i++) { for (int i = 0; i < directories.length - 1; i++) {
String directoryName = directories[i]; String directoryName = directories[i];
boolean found = false; boolean found = false;
// Search all sub elements // Search all sub elements
for (DocumentFile subDocument: document.listFiles()) { for (DocumentFile subDocument : document.listFiles()) {
// Directory exists // Directory exists
if (subDocument.isDirectory() && subDocument.getName().equalsIgnoreCase(directoryName)) { if (subDocument.isDirectory() && subDocument.getName().equalsIgnoreCase(directoryName)) {
document = subDocument; document = subDocument;
@ -571,12 +581,12 @@ public class PlayMusicManager {
// Gets the filename // Gets the filename
String filename = directories[directories.length - 1]; String filename = directories[directories.length - 1];
for (DocumentFile subDocument: document.listFiles()) { for (DocumentFile subDocument : document.listFiles()) {
// Directory exists // Directory exists
if (subDocument.isFile() ){ if (subDocument.isFile()) {
if ( filename != null && subDocument.getName().equalsIgnoreCase(filename)) { if (filename != null && subDocument.getName().equalsIgnoreCase(filename)) {
// Delete the file // Delete the file
if ( forceOverwrite ) { if (forceOverwrite) {
Logger.getInstance().logWarning("ExportMusicTrack", "(forceOverwrite) Deleting original file: " + filename); Logger.getInstance().logWarning("ExportMusicTrack", "(forceOverwrite) Deleting original file: " + filename);
} }
subDocument.delete(); subDocument.delete();
@ -660,7 +670,7 @@ public class PlayMusicManager {
//new MediaScanner(mContext, dest); //new MediaScanner(mContext, dest);
} else { } else {
Logger.getInstance().logInfo("exportMusicTrack", path + " already exists, skipping." ); Logger.getInstance().logInfo("exportMusicTrack", path + " already exists, skipping.");
} }
// Done // Done
@ -669,9 +679,10 @@ public class PlayMusicManager {
/** /**
* Checks if the destination file already exists * Checks if the destination file already exists
* @param pUri the source file *
* @param pUri the source file
* @param pPath The destination * @param pPath The destination
* return true if the file already exists * return true if the file already exists
*/ */
private boolean isAlreadyThere(Uri pUri, String pPath) { private boolean isAlreadyThere(Uri pUri, String pPath) {
if (pUri.toString().startsWith("file://")) { if (pUri.toString().startsWith("file://")) {
@ -683,8 +694,8 @@ public class PlayMusicManager {
for (String lDisplayName : pPath.split("/")) { for (String lDisplayName : pPath.split("/")) {
if (lDocumentFile.findFile(lDisplayName) != null) { if (lDocumentFile.findFile(lDisplayName) != null) {
lDocumentFile = lDocumentFile.findFile(lDisplayName); lDocumentFile = lDocumentFile.findFile(lDisplayName);
if ( lDocumentFile.length() == 0 ) { if (lDocumentFile.length() == 0) {
if ( !lDocumentFile.isDirectory() ) { if (!lDocumentFile.isDirectory()) {
Logger.getInstance().logInfo("isAlreadyThere", pPath + " File exists, but is 0 bytes in size."); Logger.getInstance().logInfo("isAlreadyThere", pPath + " File exists, but is 0 bytes in size.");
} }
} }
@ -699,122 +710,117 @@ public class PlayMusicManager {
/** /**
* Copies the music file to a new path and adds the mp3 meta data * Copies the music file to a new path and adds the mp3 meta data
*
* @param musicTrack Track information * @param musicTrack Track information
* @param src The source mp3 file * @param src The source mp3 file
* @param dest The destination path * @param dest The destination path
* return Return if the operation was successful * return Return if the operation was successful
*/ */
private boolean trackWriteID3(MusicTrack musicTrack, String src, String dest) { private boolean trackWriteID3(MusicTrack musicTrack, String src, String dest) throws InvalidDataException, IOException, UnsupportedTagException, NotSupportedException {
try { // Opens the mp3
// Opens the mp3 Mp3File mp3File = new Mp3File(src);
Mp3File mp3File = new Mp3File(src);
// Removes all existing tags // Removes all existing tags
mp3File.removeId3v1Tag(); mp3File.removeId3v1Tag();
mp3File.removeId3v2Tag(); mp3File.removeId3v2Tag();
mp3File.removeCustomTag(); mp3File.removeCustomTag();
// We want to add a fallback ID3v1 tag
if (mID3EnableFallback) {
// Create a new tag with ID3v1
ID3v1Tag tagID3v1 = new ID3v1Tag();
// Set all tag values
tagID3v1.setTrack(musicTrack.getTitle());
tagID3v1.setArtist(musicTrack.getArtist());
tagID3v1.setAlbum(musicTrack.getAlbum());
tagID3v1.setYear(musicTrack.getYear());
// Search the genre
for(int n=0; n<ID3v1Genres.GENRES.length; n++) {
// Genre found
if (ID3v1Genres.GENRES[n].equals(musicTrack.getGenre())) {
tagID3v1.setGenre(n);
break;
}
}
mp3File.setId3v1Tag(tagID3v1);
}
// It can't be null
final ID3v2 tagID3v2;
// Creates the requested version
switch(mID3v2Version) {
case ID3v22:
tagID3v2 = new ID3v22Tag();
break;
case ID3v23:
tagID3v2 = new ID3v23Tag();
break;
case ID3v24:
tagID3v2 = new ID3v24Tag();
break;
default:
tagID3v2 = null;
break;
}
// We want to add a fallback ID3v1 tag
if (mID3EnableFallback) {
// Create a new tag with ID3v1
ID3v1Tag tagID3v1 = new ID3v1Tag();
// Set all tag values // Set all tag values
tagID3v2.setTitle(musicTrack.getTitle()); tagID3v1.setTrack(musicTrack.getTitle());
tagID3v2.setArtist(musicTrack.getArtist()); tagID3v1.setArtist(musicTrack.getArtist());
tagID3v2.setAlbum(musicTrack.getAlbum()); tagID3v1.setAlbum(musicTrack.getAlbum());
tagID3v2.setAlbumArtist(musicTrack.getAlbumArtist()); tagID3v1.setYear(musicTrack.getYear());
tagID3v2.setTrack("" + musicTrack.getTrackNumber());
tagID3v2.setPartOfSet("" + musicTrack.getDiscNumber());
tagID3v2.setYear(musicTrack.getYear());
if (!TextUtils.isEmpty(musicTrack.getGenre())) { // Search the genre
try { for (int n = 0; n < ID3v1Genres.GENRES.length; n++) {
// Maybe the genre is not supported // Genre found
tagID3v2.setGenreDescription(musicTrack.getGenre()); if (ID3v1Genres.GENRES[n].equals(musicTrack.getGenre())) {
} catch (IllegalArgumentException e) { tagID3v1.setGenre(n);
Logger.getInstance().logWarning("TrackWriteID3", e.getMessage()); break;
} }
} }
// Add the artwork to the meta data mp3File.setId3v1Tag(tagID3v1);
if (mID3EnableArtwork) {
// Load the artwork
Bitmap bitmap = ArtworkLoader.loadArtwork(musicTrack, mID3ArtworkMaximumSize);
if (bitmap != null) {
// JPEG is default
String mimeType = "image/jpeg";
// Load the bitmap into a byte array
ByteArrayOutputStream artworkDataStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, artworkDataStream);
// Adds the artwork to the meta data
tagID3v2.setAlbumImage(artworkDataStream.toByteArray(), mimeType);
}
}
mp3File.setId3v2Tag(tagID3v2);
// Save the file
mp3File.save(dest);
// Done
return true;
} catch (Exception e) {
Logger.getInstance().logError("TrackWriteId3", e.toString());
} }
// Failed // It can't be null
return false; final ID3v2 tagID3v2;
// Creates the requested version
switch (mID3v2Version) {
case ID3v22:
tagID3v2 = new ID3v22Tag();
break;
case ID3v23:
tagID3v2 = new ID3v23Tag();
break;
case ID3v24:
tagID3v2 = new ID3v24Tag();
break;
default:
tagID3v2 = null;
break;
}
// Set all tag values
tagID3v2.setTitle(musicTrack.getTitle());
tagID3v2.setArtist(musicTrack.getArtist());
tagID3v2.setAlbum(musicTrack.getAlbum());
tagID3v2.setAlbumArtist(musicTrack.getAlbumArtist());
tagID3v2.setTrack("" + musicTrack.getTrackNumber());
tagID3v2.setPartOfSet("" + musicTrack.getDiscNumber());
tagID3v2.setYear(musicTrack.getYear());
if (!TextUtils.isEmpty(musicTrack.getGenre())) {
try {
// Maybe the genre is not supported
tagID3v2.setGenreDescription(musicTrack.getGenre());
} catch (IllegalArgumentException e) {
Logger.getInstance().logWarning("TrackWriteID3", e.getMessage());
}
}
// Add the artwork to the meta data
if (mID3EnableArtwork) {
// Load the artwork
Bitmap bitmap = ArtworkLoader.loadArtwork(musicTrack, mID3ArtworkMaximumSize);
if (bitmap != null) {
// JPEG is default
String mimeType = "image/jpeg";
// Load the bitmap into a byte array
ByteArrayOutputStream artworkDataStream = new ByteArrayOutputStream();
bitmap.compress(Bitmap.CompressFormat.JPEG, 90, artworkDataStream);
// Adds the artwork to the meta data
tagID3v2.setAlbumImage(artworkDataStream.toByteArray(), mimeType);
}
}
mp3File.setId3v2Tag(tagID3v2);
// Save the file
mp3File.save(dest);
// Done
return true;
} }
/** /**
* Encrypts a track and save it to a new path * Encrypts a track and save it to a new path
*
* @param musicTrack The music track * @param musicTrack The music track
* @param src The source mp3 file * @param src The source mp3 file
* @param dest The destination path * @param dest The destination path
* @return Return if the operation was successful * @return Return if the operation was successful
*/ */
private boolean trackEncrypt(MusicTrack musicTrack, String src, String dest) { private boolean trackEncrypt(MusicTrack musicTrack, String src, String dest) {
@ -843,8 +849,8 @@ public class PlayMusicManager {
* Deletes all cache files * Deletes all cache files
*/ */
private void cleanUp(String theUniqueID) { private void cleanUp(String theUniqueID) {
FileTools.fileDelete( getTempPath() + theUniqueID +"_final.mp3"); FileTools.fileDelete(getTempPath() + theUniqueID + "_final.mp3");
FileTools.fileDelete( getTempPath() + theUniqueID +"_tmp.mp3"); FileTools.fileDelete(getTempPath() + theUniqueID + "_tmp.mp3");
FileTools.fileDelete( getTempPath() + theUniqueID +"_crypt.mp3"); FileTools.fileDelete(getTempPath() + theUniqueID + "_crypt.mp3");
} }
} }