diff --git a/.gitignore b/.gitignore index d57b415..e7c8a01 100644 --- a/.gitignore +++ b/.gitignore @@ -30,6 +30,7 @@ hs_err_pid* .idea/sqlDataSources.xml .idea/dynamic.xml .idea/uiDesigner.xml +.idea/misc.xml # Gradle: .idea/gradle.xml @@ -107,3 +108,4 @@ captures/ # Keystore files *.jks +gradle/wrapper/gradle-wrapper.properties diff --git a/.idea/misc.xml b/.idea/misc.xml deleted file mode 100644 index fbb6828..0000000 --- a/.idea/misc.xml +++ /dev/null @@ -1,46 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/PlayMusicExporter.iml b/PlayMusicExporter.iml deleted file mode 100644 index 0037bb5..0000000 --- a/PlayMusicExporter.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/PlayMusicExporterGit.iml b/PlayMusicExporterGit.iml deleted file mode 100644 index a25d277..0000000 --- a/PlayMusicExporterGit.iml +++ /dev/null @@ -1,19 +0,0 @@ - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/README.md b/README.md index a704588..b8273ca 100644 --- a/README.md +++ b/README.md @@ -1,21 +1,38 @@ # Play Music Exporter -This Android app exports your Play Music mp3 files directly to your sdcard using root permissions. +This Android app exports your Play Music mp3 files directly to your sdcard +or a documents provider using root permissions. +You can also setup automatic export, that exports all currently cached not yet exported music. ## About -This AndroidStudio project allow you to access the database from Google's PlayMusic and also allows you to export the music files as mp3 to your sdcard. There is also a nice library you can simply use in your projects. +This AndroidStudio project allow you to access the database from Google's PlayMusic +and also allows you to export the music files as mp3 to your sdcard or a documents provider. +There is also a nice library you can simply use in your projects. ### Requirements -**This app and its library will require root access to your device! If your device is not rooted you can't use this app neither the lib.** +**This app and the included library will require root access to your device! +If your device is not rooted you can neither use this app nor the library.** -This project uses the [mp3agic library](https://github.com/mpatric/mp3agic) by [Michael Patricios (mpatric)](https://github.com/mpatric). +This app uses API Level 21, which has been introduced by Android Lollipop. If you use KitKat +or lower, this app will not work. -### Notice +### Credits -I recently forked this repository and most of the work has been done by [David Schulte](https://www.david-schulte.de/). -You can find his old/inactive repository [here](https://github.com/Arcus92/PlayMusicExporter). +This is a fork off [David Schulte's original project](https://github.com/Arcus92/PlayMusicExporter). +Most of the work has been done by him, me and the other collaborators just have improved his work +in some minor ways, like making the app more usable and configurable. The exporting itself, the hard +part, has been done by him. + +This project uses the [mp3agic library](https://github.com/mpatric/mp3agic) +by [Michael Patricios (mpatric)](https://github.com/mpatric). + +### Contributing + +If you want to contribute to this project, fork off of develop, +implement what you want to implement, and submit a pull request back into develop. +After testing it, if enough of the collaborators like it, we will merge it. ### Copyright diff --git a/apk/playmusicexporter-release.apk b/apk/playmusicexporter-release.apk deleted file mode 100644 index 1c85ed2..0000000 Binary files a/apk/playmusicexporter-release.apk and /dev/null differ diff --git a/build.gradle b/build.gradle index b5ee179..7b35dc2 100644 --- a/build.gradle +++ b/build.gradle @@ -29,7 +29,7 @@ buildscript { jcenter() } dependencies { - classpath 'com.android.tools.build:gradle:2.2.3' + classpath 'com.android.tools.build:gradle:2.3.0-beta3' } } diff --git a/framework/build.gradle b/framework/build.gradle index 8d078a4..30cf240 100644 --- a/framework/build.gradle +++ b/framework/build.gradle @@ -42,5 +42,5 @@ android { dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) - compile 'com.android.support:appcompat-v7:25.1.0' + compile 'com.android.support:appcompat-v7:25.1.1' } diff --git a/framework/framework.iml b/framework/framework.iml deleted file mode 100644 index 9a58259..0000000 --- a/framework/framework.iml +++ /dev/null @@ -1,121 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/gradle/wrapper/gradle-wrapper.properties b/gradle/wrapper/gradle-wrapper.properties index aab9353..18481fd 100644 --- a/gradle/wrapper/gradle-wrapper.properties +++ b/gradle/wrapper/gradle-wrapper.properties @@ -1,6 +1,6 @@ -#Fri Nov 25 23:05:46 CET 2016 +#Sun Jan 22 21:19:51 CET 2017 distributionBase=GRADLE_USER_HOME distributionPath=wrapper/dists zipStoreBase=GRADLE_USER_HOME zipStorePath=wrapper/dists -distributionUrl=https\://services.gradle.org/distributions/gradle-2.14.1-all.zip +distributionUrl=https\://services.gradle.org/distributions/gradle-3.3-all.zip diff --git a/playmusicexporter/build.gradle b/playmusicexporter/build.gradle index 75a7a01..aece3d4 100644 --- a/playmusicexporter/build.gradle +++ b/playmusicexporter/build.gradle @@ -57,9 +57,9 @@ dependencies { compile fileTree(dir: 'libs', include: ['*.jar']) compile project(':framework') compile project(':playmusiclib') - compile 'com.android.support:appcompat-v7:25.1.0' - compile 'com.android.support:support-v4:25.1.0' - compile 'com.android.support:design:25.1.0' - compile 'com.android.support:support-vector-drawable:25.1.0' + compile 'com.android.support:appcompat-v7:25.1.1' + compile 'com.android.support:support-v4:25.1.1' + compile 'com.android.support:design:25.1.1' + compile 'com.android.support:support-vector-drawable:25.1.1' compile "com.github.paolorotolo:appintro:4.1.0" } diff --git a/playmusicexporter/playmusicexporter.iml b/playmusicexporter/playmusicexporter.iml deleted file mode 100644 index beffcb2..0000000 --- a/playmusicexporter/playmusicexporter.iml +++ /dev/null @@ -1,131 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/playmusicexporter/src/main/AndroidManifest.xml b/playmusicexporter/src/main/AndroidManifest.xml index 9b3075c..8075054 100644 --- a/playmusicexporter/src/main/AndroidManifest.xml +++ b/playmusicexporter/src/main/AndroidManifest.xml @@ -25,6 +25,7 @@ + lAlba = lAlbumDataSource.getAll(); for (Album lAlbum : lAlba) { for (MusicTrack lTrack : lAlbum.getMusicTrackList()) { if (lTrack.isOfflineAvailable()) { String lPath = MusicPathBuilder.Build(lTrack, lExportStructure); try { - if (!isAlreadyThere(lUri, lPath)) { - if (lPlayMusicManager.exportMusicTrack(lTrack, lUri, lPath)) { - Log.i(TAG, "Exported Music Track: " + getStringForTrack(lTrack)); - } else { - Log.i(TAG, "Failed to export Music Track: " + getStringForTrack(lTrack)); - } + if (lPlayMusicManager.exportMusicTrack(lTrack, lUri, lPath, PlayMusicExporterPreferences.getFileOverwritePreference())) { + Log.i(TAG, "Exported Music Track: " + getStringForTrack(lTrack)); } else { - Log.i(TAG, lPath + " already exists."); + Log.i(TAG, "Failed to export Music Track: " + getStringForTrack(lTrack)); } + } catch (IllegalArgumentException e) { if (e.getMessage().contains("Invalid URI:")) { /* @@ -87,22 +89,20 @@ public class ExportAllService extends IntentService { Log.i(TAG, "Automatic export failed, because the URI is invalid."); } else throw e; } + finally + { + if ( CPULock.isHeld()) + { + CPULock.release(); + } + } } } } - } - - private boolean isAlreadyThere(Uri pUri, String pPath) { - DocumentFile lDocumentFile = DocumentFile.fromTreeUri(this, pUri); - for (String lDisplayName: pPath.split("/")) { - if (lDocumentFile.findFile(lDisplayName) != null) { - lDocumentFile = lDocumentFile.findFile(lDisplayName); - } else { - Log.i(TAG, pPath + " does not exist yet."); - return false; - } + if ( CPULock.isHeld()) + { + CPULock.release(); } - return true; } private String getStringForTrack(MusicTrack pTrack) { diff --git a/playmusicexporter/src/main/java/re/jcg/playmusicexporter/services/ExportService.java b/playmusicexporter/src/main/java/re/jcg/playmusicexporter/services/ExportService.java index 9e10e90..e68545f 100644 --- a/playmusicexporter/src/main/java/re/jcg/playmusicexporter/services/ExportService.java +++ b/playmusicexporter/src/main/java/re/jcg/playmusicexporter/services/ExportService.java @@ -35,6 +35,7 @@ import re.jcg.playmusicexporter.R; import de.arcus.playmusiclib.PlayMusicManager; import de.arcus.playmusiclib.datasources.MusicTrackDataSource; import de.arcus.playmusiclib.items.MusicTrack; +import re.jcg.playmusicexporter.settings.PlayMusicExporterPreferences; /** * The export service @@ -199,7 +200,7 @@ public class ExportService extends IntentService { updateNotification(); // Exports the song - if(!playMusicManager.exportMusicTrack(mTrackCurrent, uri, path)) { + if(!playMusicManager.exportMusicTrack(mTrackCurrent, uri, path, PlayMusicExporterPreferences.getFileOverwritePreference())) { // Export failed mTracksFailed ++; } diff --git a/playmusicexporter/src/main/java/re/jcg/playmusicexporter/settings/PlayMusicExporterPreferences.java b/playmusicexporter/src/main/java/re/jcg/playmusicexporter/settings/PlayMusicExporterPreferences.java index 808a22f..cad79d5 100644 --- a/playmusicexporter/src/main/java/re/jcg/playmusicexporter/settings/PlayMusicExporterPreferences.java +++ b/playmusicexporter/src/main/java/re/jcg/playmusicexporter/settings/PlayMusicExporterPreferences.java @@ -16,6 +16,8 @@ public class PlayMusicExporterPreferences { public static final boolean AUTO_EXPORT_ENABLED_DEFAULT = false; public static final String AUTO_EXPORT_USES_DIFFERENT_PATH = "preference_auto_export_use_different_path"; public static final boolean AUTO_EXPORT_USES_DIFFERENT_PATH_DEFAULT = false; + private static final String FORCE_EXPORT_OVERWRITE = "preference_overwrite_existing_files"; + private static final boolean FORCE_EXPORT_OVERWRITE_DEFAULT = false; public static final String AUTO_EXPORT_USES_DIFFERENT_STRUCTURE = "preference_auto_export_use_different_structure"; public static final boolean AUTO_EXPORT_USES_DIFFERENT_STRUCTURE_DEFAULT = false; public static final String AUTO_EXPORT_FREQUENCY = "preference_auto_export_frequency"; @@ -63,6 +65,10 @@ public class PlayMusicExporterPreferences { } } + public static boolean getFileOverwritePreference() { + return preferences.getBoolean(FORCE_EXPORT_OVERWRITE, FORCE_EXPORT_OVERWRITE_DEFAULT); + } + public static boolean getAutoExportUsesDifferentPath() { return preferences.getBoolean(AUTO_EXPORT_USES_DIFFERENT_PATH, AUTO_EXPORT_USES_DIFFERENT_PATH_DEFAULT); } diff --git a/playmusicexporter/src/main/java/re/jcg/playmusicexporter/utils/MusicPathBuilder.java b/playmusicexporter/src/main/java/re/jcg/playmusicexporter/utils/MusicPathBuilder.java index d8bb18f..e2d43bf 100644 --- a/playmusicexporter/src/main/java/re/jcg/playmusicexporter/utils/MusicPathBuilder.java +++ b/playmusicexporter/src/main/java/re/jcg/playmusicexporter/utils/MusicPathBuilder.java @@ -85,7 +85,8 @@ public class MusicPathBuilder { if (!TextUtils.isEmpty(musicTrack.getAlbum())) value = musicTrack.getAlbum(); break; - case "group": + case "playlist": + case "group": //previous name, for compatability if (!TextUtils.isEmpty(musicTrack.getContainerName())) value = musicTrack.getContainerName(); break; diff --git a/playmusicexporter/src/main/res/values-de/strings.xml b/playmusicexporter/src/main/res/values-de/strings.xml index 90757ad..2f8c224 100644 --- a/playmusicexporter/src/main/res/values-de/strings.xml +++ b/playmusicexporter/src/main/res/values-de/strings.xml @@ -75,7 +75,8 @@ Verzeichnisbaum für Alben Setze den Verzeichnisbaum Beispiel: Beatles/Help!/13. Yesterday.mp3 - "Nutze / für einen neuen Order. Available Tags: - {album-artist} - {album} - {artist} - {title} - {disc=CD $} - {no=$$.} - {year} - {genre} " + Nutze / für einen neuen Order \n Available Tags: \n - {album-artist} \n - {album} \n - {artist} \n - {title} \n - {disc=CD $} \n - {no=$$.} \n - {year} \n - {genre} \n + Nutze / für einen neuen Order \n Available Tags: \n - {playlist} \n - {album-artist} \n - {album} \n - {artist} \n - {title} \n - {disc=CD $} \n - {no=$$.} \n - {year} \n - {genre} \n Setze den Verzeichnisbaum Beispiel: Great Songs/4. Beatles - Yesterday.mp3 Versionsnummer @@ -101,4 +102,8 @@ Administrator-Zugriff verweigert Der Play Music Exporter benötigt Administrator Rechte, ohne diese Rechte kann die App nicht genutzt werden. Verzeichnisbaum + Bestehende Dateien überschreiben + Dateiverarbeitung + Überschreiben Sie die exportierte Datei immer, auch wenn sie bereits existiert. + Bestehende Dateien überschreiben. \ No newline at end of file diff --git a/playmusicexporter/src/main/res/values/strings.xml b/playmusicexporter/src/main/res/values/strings.xml index f56ea0f..e7f388a 100644 --- a/playmusicexporter/src/main/res/values/strings.xml +++ b/playmusicexporter/src/main/res/values/strings.xml @@ -73,7 +73,7 @@ Export path and subdirectory structure Debug Export location albums - Export location groups + Export location playlists Version Number @@ -94,14 +94,14 @@ Export Location Export Base Path Use / for a new folder \n Available Tags: \n - {album-artist} \n - {album} \n - {artist} \n - {title} \n - {disc=CD $} \n - {no=$$.} \n - {year} \n - {genre} \n - + Use / for a new folder \n Available Tags: \n - {playlist} \n - {album-artist} \n - {album} \n - {artist} \n - {title} \n - {disc=CD $} \n - {no=$$.} \n - {year} \n - {genre} \n Export path for albums Subdirectory structure for albums Set your subdirectory structure Example: Beatles/Help!/13. Yesterday.mp3 - Export path for groups + Export path for playlists Subdirectory structure for playlists Set your subdirectory structure Example: Great Songs/4. Beatles - Yesterday.mp3 @@ -116,6 +116,7 @@ If the artwork original size is larger than this setting the app will size down the artwork to this size. Custom path + Overwrite existing files David-Schulte.de @@ -139,7 +140,10 @@ Debug {album-artist}/{album}/{disc=CD $}/{no=$$.} {title}.mp3 - {group}/{group-no=$$.} {artist} - {title}.mp3 + {playlist}/{artist} - {title}.mp3 Trigger ExportAllService now + File Handling + Always overwrite the exported file, even if it already exists. + Overwrite Existing Files diff --git a/playmusicexporter/src/main/res/xml/pref_export.xml b/playmusicexporter/src/main/res/xml/pref_export.xml index ffd2ae4..f4d4149 100644 --- a/playmusicexporter/src/main/res/xml/pref_export.xml +++ b/playmusicexporter/src/main/res/xml/pref_export.xml @@ -24,7 +24,7 @@ + + + diff --git a/playmusiclib/playmusiclib.iml b/playmusiclib/playmusiclib.iml deleted file mode 100644 index cfa6777..0000000 --- a/playmusiclib/playmusiclib.iml +++ /dev/null @@ -1,114 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - \ No newline at end of file diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/ArtworkLoader.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/ArtworkLoader.java index 528471e..eeaf483 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/ArtworkLoader.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/ArtworkLoader.java @@ -69,8 +69,13 @@ public class ArtworkLoader { if (!TextUtils.isEmpty(artworkUrl)) { // Tries to load the artwork via internet try { - URL url = new URL(artworkUrl); - bitmap = BitmapFactory.decodeStream(url.openStream()); + if (artworkUrl.contains("mediastore")) { + Logger.getInstance().logError("LoadArtwork", "mediastore artwork"); + //TODO handle mediastore album art using ContentResolver + } else { + URL url = new URL(artworkUrl); + bitmap = BitmapFactory.decodeStream(url.openStream()); + } } catch (Exception e) { // Error Logger.getInstance().logError("LoadArtwork", e.toString()); diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java index d78fb8a..bfc80d9 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java @@ -25,6 +25,7 @@ package de.arcus.playmusiclib; import android.content.Context; import android.content.pm.ApplicationInfo; import android.content.pm.PackageManager; +import android.database.Cursor; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; @@ -32,8 +33,10 @@ import android.net.Uri; import android.os.Build; import android.os.Environment; import android.os.ParcelFileDescriptor; +import android.support.v4.content.FileProvider; import android.support.v4.provider.DocumentFile; import android.text.TextUtils; +import android.util.Log; import com.mpatric.mp3agic.ID3v1Genres; import com.mpatric.mp3agic.ID3v1Tag; @@ -51,6 +54,7 @@ import java.io.FileOutputStream; import java.io.IOException; import java.util.ArrayList; import java.util.List; +import java.util.UUID; import de.arcus.framework.logger.Logger; import de.arcus.framework.superuser.SuperUser; @@ -137,7 +141,7 @@ public class PlayMusicManager { * @return Gets the temp path to the database */ private String getTempDatabasePath() { - return getTempPath() + "/music.db"; + return getTempPath() + "music.db"; } /** @@ -443,8 +447,8 @@ public class PlayMusicManager { String path; // Fix the path for Play Music 5.9.1854 - if (!artworkPath.startsWith("artwork2/folder/")) - artworkPath = "artwork2/folder/" + artworkPath; + if (!artworkPath.startsWith("artwork/")) + artworkPath = "artwork/" + artworkPath; // Search in the public data for (String publicData : mPathPublicData) { @@ -467,9 +471,10 @@ public class PlayMusicManager { * Exports a track to the sd card * @param musicTrack The music track you want to export * @param dest The destination path + * @param forceOverwrite Forces overwrite of the destination file * @return Returns whether the export was successful */ - public boolean exportMusicTrack(MusicTrack musicTrack, String dest) { + public boolean exportMusicTrack(MusicTrack musicTrack, String dest, boolean forceOverwrite ) { // Creates the destination directory File directory = new File(dest).getParentFile(); @@ -477,16 +482,17 @@ public class PlayMusicManager { // Filename String filename = new File(dest).getName(); - return exportMusicTrack(musicTrack, Uri.fromFile(directory), filename); + return exportMusicTrack(musicTrack, Uri.fromFile(directory), filename, forceOverwrite); } /** * Exports a track to the sd card * @param musicTrack The music track you want to export * @param uri The document tree + * @param forceOverwrite Forces overwrite of the destination file * @return Returns whether the export was successful */ - public boolean exportMusicTrack(MusicTrack musicTrack, Uri uri, String path) { + public boolean exportMusicTrack(MusicTrack musicTrack, Uri uri, String path, boolean forceOverwrite) { // Check for null if (musicTrack == null) return false; @@ -496,94 +502,113 @@ public class PlayMusicManager { // Could not find the source file if (srcFile == null) return false; - String fileTmp = getTempPath() + "/tmp.mp3"; + String uniqueID = UUID.randomUUID().toString(); - // Copy to temp path failed - if (!SuperUserTools.fileCopy(srcFile, fileTmp)) - return false; + if ( forceOverwrite || !isAlreadyThere(uri, path) ) + { - // Encrypt the file - if (musicTrack.isEncoded()) { - String fileTmpCrypt = getTempPath() + "/crypt.mp3"; + String fileTmp = getTempPath() + uniqueID +"_tmp.mp3"; - // Encrypts the file - if (trackEncrypt(musicTrack, fileTmp, fileTmpCrypt)) { - // Remove the old tmp file - FileTools.fileDelete(fileTmp); + // Copy to temp path failed + if (!SuperUserTools.fileCopy(srcFile, fileTmp)) + return false; - // New tmp file - fileTmp = fileTmpCrypt; - } else { - Logger.getInstance().logWarning("ExportMusicTrack", "Encrypting failed! Continue with decrypted file."); + // Encrypt the file + if (musicTrack.isEncoded()) { + String fileTmpCrypt = getTempPath() + uniqueID +"_crypt.mp3"; + + // Encrypts the file + if (trackEncrypt(musicTrack, fileTmp, fileTmpCrypt)) { + // Remove the old tmp file + FileTools.fileDelete(fileTmp); + + // New tmp file + fileTmp = fileTmpCrypt; + } else { + Logger.getInstance().logWarning("ExportMusicTrack", "Encrypting failed! Continue with decrypted file."); + } } - } - String dest; - Uri copyUri = null; - if (uri.toString().startsWith("file://")) { - // Build the full path - dest = uri.buildUpon().appendPath(path).build().getPath(); + String dest; + Uri copyUri = null; + if (uri.toString().startsWith("file://")) { + // Build the full path + dest = uri.buildUpon().appendPath(path).build().getPath(); - String parentDirectory = new File(dest).getParent(); - FileTools.directoryCreate(parentDirectory); - } else { - // Complex uri (Lollipop) - dest = getTempPath() + "/final.mp3"; + String parentDirectory = new File(dest).getParent(); + FileTools.directoryCreate(parentDirectory); + } else { + // Complex uri (Lollipop) + dest = getTempPath() + uniqueID +"_final.mp3"; - // The root - DocumentFile document = DocumentFile.fromTreeUri(mContext, uri); + // The root + DocumentFile document = DocumentFile.fromTreeUri(mContext, uri); - // Creates the subdirectories - String[] directories = path.split("\\/"); - for(int i=0; i= Build.VERSION_CODES.LOLLIPOP) { + try { + // Gets the file descriptor + ParcelFileDescriptor parcelFileDescriptor = mContext.getContentResolver().openFileDescriptor(copyUri, "w"); - // We need to copy the file to a uri - if (copyUri != null) { - // Lollipop only - if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP) { - try { - // Gets the file descriptor - ParcelFileDescriptor parcelFileDescriptor = mContext.getContentResolver().openFileDescriptor(copyUri, "w"); + // Gets the output stream + FileOutputStream fileOutputStream = new FileOutputStream(parcelFileDescriptor.getFileDescriptor()); - // Gets the output stream - FileOutputStream fileOutputStream = new FileOutputStream(parcelFileDescriptor.getFileDescriptor()); + // Gets the input stream + FileInputStream fileInputStream = new FileInputStream(dest); - // Gets the input stream - FileInputStream fileInputStream = new FileInputStream(dest); + // Copy the stream + FileTools.fileCopy(fileInputStream, fileOutputStream); - // Copy the stream - FileTools.fileCopy(fileInputStream, fileOutputStream); + // Close all streams + fileOutputStream.close(); + fileInputStream.close(); + parcelFileDescriptor.close(); - // Close all streams - fileOutputStream.close(); - fileInputStream.close(); - parcelFileDescriptor.close(); + } catch (FileNotFoundException e) { + Logger.getInstance().logError("ExportMusicTrack", "File not found!"); - } catch (FileNotFoundException e) { - Logger.getInstance().logError("ExportMusicTrack", "File not found!"); + // Could not copy the file + return false; + } catch (IOException e) { + Logger.getInstance().logError("ExportMusicTrack", "Failed to write the document: " + e.toString()); - // Could not copy the file - return false; - } catch (IOException e) { - Logger.getInstance().logError("ExportMusicTrack", "Failed to write the document: " + e.toString()); - - // Could not copy the file - return false; + // Could not copy the file + return false; + } } } + + // Delete temp files + cleanUp(uniqueID); + + // Adds the file to the media system + //new MediaScanner(mContext, dest); + + } else { + Logger.getInstance().logInfo("exportMusicTrack", path + " already exists, skipping." ); } - // Delete temp files - cleanUp(); - - // Adds the file to the media system - //new MediaScanner(mContext, dest); - // Done return true; } + /** + * Checks if the destination file already exists + * @param pUri the source file + * @param pPath The destination + * return true if the file already exists + */ + private boolean isAlreadyThere(Uri pUri, String pPath) { + if (pUri.toString().startsWith("file://")) { + //Old sdcard URI + return FileTools.fileExists(pUri.buildUpon().appendPath(pPath).build().toString()); + } else { + //Documents Provider URI + DocumentFile lDocumentFile = DocumentFile.fromTreeUri(mContext, pUri); + for (String lDisplayName : pPath.split("/")) { + if (lDocumentFile.findFile(lDisplayName) != null) { + lDocumentFile = lDocumentFile.findFile(lDisplayName); + if ( lDocumentFile.length() == 0 ) { + if ( !lDocumentFile.isDirectory() ) { + Logger.getInstance().logInfo("isAlreadyThere", pPath + " File exists, but is 0 bytes in size."); + } + } + } else { + Logger.getInstance().logInfo("isAlreadyThere", pPath + " does not exist yet."); + return false; + } + } + return true; + } + } + /** * Copies the music file to a new path and adds the mp3 meta data * @param musicTrack Track information @@ -792,9 +842,9 @@ public class PlayMusicManager { /** * Deletes all cache files */ - private void cleanUp() { - FileTools.fileDelete(getTempPath() + "/final.mp3"); - FileTools.fileDelete(getTempPath() + "/tmp.mp3"); - FileTools.fileDelete(getTempPath() + "/crypt.mp3"); + private void cleanUp(String theUniqueID) { + FileTools.fileDelete( getTempPath() + theUniqueID +"_final.mp3"); + FileTools.fileDelete( getTempPath() + theUniqueID +"_tmp.mp3"); + FileTools.fileDelete( getTempPath() + theUniqueID +"_crypt.mp3"); } }