diff --git a/.idea/dictionaries/david.xml b/.idea/dictionaries/david.xml new file mode 100644 index 0000000..8409230 --- /dev/null +++ b/.idea/dictionaries/david.xml @@ -0,0 +1,7 @@ + + + + simpel + + + \ No newline at end of file diff --git a/framework/src/main/java/de/arcus/framework/activities/DirectoryBrowserActivity.java b/framework/src/main/java/de/arcus/framework/activities/DirectoryBrowserActivity.java index dcc0c1e..9d475b0 100644 --- a/framework/src/main/java/de/arcus/framework/activities/DirectoryBrowserActivity.java +++ b/framework/src/main/java/de/arcus/framework/activities/DirectoryBrowserActivity.java @@ -22,12 +22,19 @@ package de.arcus.framework.activities; +import android.content.Context; +import android.content.Intent; +import android.net.Uri; +import android.os.Build; import android.os.Bundle; +import android.os.Environment; import android.support.v7.app.ActionBar; import android.support.v7.app.AppCompatActivity; import android.view.Menu; import android.view.MenuItem; +import java.io.File; + import de.arcus.framework.R; /** @@ -46,7 +53,7 @@ public class DirectoryBrowserActivity extends AppCompatActivity { /** * The current path */ - private String mPath = "/"; + private File mPath; @Override protected void onCreate(Bundle savedInstanceState) { @@ -63,8 +70,17 @@ public class DirectoryBrowserActivity extends AppCompatActivity { mTitle = bundle.getString(EXTRA_TITLE); // Reads the start path - if (bundle.containsKey(EXTRA_PATH)) - mPath = bundle.getString(EXTRA_PATH); + if (bundle.containsKey(EXTRA_PATH)) { + String path = bundle.getString(EXTRA_PATH); + if (path != null) { + mPath = new File(path); + + // Default directory + if (!mPath.exists()) { + mPath = Environment.getExternalStorageDirectory(); + } + } + } } // Setup the actionbar @@ -72,7 +88,7 @@ public class DirectoryBrowserActivity extends AppCompatActivity { if (actionBar != null) { // Set the title actionBar.setTitle(mTitle); - actionBar.setSubtitle(mPath); + actionBar.setSubtitle(mPath.getAbsolutePath()); } @@ -94,7 +110,52 @@ public class DirectoryBrowserActivity extends AppCompatActivity { // as you specify a parent activity in AndroidManifest.xml. int id = item.getItemId(); + if (id == R.id.action_accept) { + // Result the path + getIntent().setData(Uri.fromFile(mPath)); + setResult(RESULT_OK, getIntent()); + finish(); + + return true; + } return super.onOptionsItemSelected(item); } + + /** + * Opens the directory browser (use the Lollipop API if it's available) + * @param context The Context + * @param defaultPath The default path + * @param title The title + */ + public static Intent openDirectoryBrowser(Context context, Uri defaultPath, String title) { + return openDirectoryBrowser(context, defaultPath, title, false); + } + + /** + * Opens the directory browser (use the Lollipop API if it's available) + * @param context The Context + * @param defaultPath The default path + * @param title The title + * @param forceBuildInBrowser Set this to true to use the build-in browser even for Lollipop + */ + public static Intent openDirectoryBrowser(Context context, Uri defaultPath, String title, boolean forceBuildInBrowser) { + Intent intent; + + // Check for Lollipop + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP && !forceBuildInBrowser) { + // Opens the Lollipop directory browser + + intent = new Intent(Intent.ACTION_OPEN_DOCUMENT_TREE); + } else { + // Opens the build-in directory browser + intent = new Intent(context, DirectoryBrowserActivity.class); + + // The current path + intent.putExtra(DirectoryBrowserActivity.EXTRA_PATH, defaultPath.getPath()); + intent.putExtra(DirectoryBrowserActivity.EXTRA_TITLE, title); + } + + return intent; + } } diff --git a/framework/src/main/java/de/arcus/framework/settings/AppSettings.java b/framework/src/main/java/de/arcus/framework/settings/AppSettings.java index 90e1616..109df5b 100644 --- a/framework/src/main/java/de/arcus/framework/settings/AppSettings.java +++ b/framework/src/main/java/de/arcus/framework/settings/AppSettings.java @@ -24,6 +24,7 @@ package de.arcus.framework.settings; import android.content.Context; import android.content.SharedPreferences; +import android.net.Uri; /** * Helper class to read and write app settings without to care about to open and close an editor @@ -105,6 +106,18 @@ public class AppSettings { return mSharedPreferences.getLong(key, defValue); } + /** + * Gets a uri from the settings + * @param key Key of the setting + * @param defValue Default value which is returned if the key doesn't exists + * @return Value + */ + public Uri getUri(String key, Uri defValue) { + if (mSharedPreferences.contains(key)) + return Uri.parse(mSharedPreferences.getString(key, "")); + else return defValue; + } + /** * Gets an enum value from the settings * @param key Key of the setting @@ -226,6 +239,20 @@ public class AppSettings { editor.commit(); } + /** + * Saves a uri to the settings + * @param key Key of the setting + * @param value Value + */ + public void setUri(String key, Uri value) { + // Opens the editor + SharedPreferences.Editor editor = mSharedPreferences.edit(); + + editor.putString(key, value.toString()); + + // Commits the change + editor.commit(); + } /** * Saves an enum value to the settings diff --git a/framework/src/main/java/de/arcus/framework/utils/FileTools.java b/framework/src/main/java/de/arcus/framework/utils/FileTools.java index d52dbfe..7e4173c 100644 --- a/framework/src/main/java/de/arcus/framework/utils/FileTools.java +++ b/framework/src/main/java/de/arcus/framework/utils/FileTools.java @@ -119,18 +119,48 @@ public class FileTools { return fileSrc.renameTo(fileDest); } + /** + * Copies a stream + * @param inputStream Source stream + * @param outputStream Destination stream + * @return Return whether the stream was copied successful + */ + public static boolean fileCopy(InputStream inputStream, OutputStream outputStream) { + // The buffer size + final int BUFFER_SIZE = 1024; + + // Will be set on true if the file was copied correctly + boolean success = false; + + try { + // The copy buffer + byte[] buffer = new byte[BUFFER_SIZE]; + int length; + + // Copy block by block + while ((length = inputStream.read(buffer)) > 0) { + outputStream.write(buffer, 0, length); + } + + // Copy was successful + success = true; + } catch (IOException ex) { + // Failed + Logger.getInstance().logError("FileCopy", "Failed: " + ex.toString()); + } + + return success; + } + /** * Copies a file - * @param src Soruce path + * @param src Source path * @param dest Destination path * @return Return whether the file was copied successful */ public static boolean fileCopy(String src, String dest) { Logger.getInstance().logVerbose("FileCopy", "From " + src + " to " + dest); - // The buffer size - final int BUFFER_SIZE = 1024; - // Will be set on true if the file was copied correctly boolean success = false; @@ -142,17 +172,7 @@ public class FileTools { inputStream = new FileInputStream(src); outputStream = new FileOutputStream(dest); - // The copy buffer - byte[] buffer = new byte[BUFFER_SIZE]; - int length; - - // Copy block by block - while ((length = inputStream.read(buffer)) > 0) { - outputStream.write(buffer, 0, length); - } - - // Copy was successful - success = true; + success = fileCopy(inputStream, outputStream); } catch (IOException ex) { // Failed Logger.getInstance().logError("FileCopy", "Failed: " + ex.toString()); diff --git a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/actionmode/ActionModeTitle.java b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/actionmode/ActionModeTitle.java index a155198..fb8b428 100644 --- a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/actionmode/ActionModeTitle.java +++ b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/actionmode/ActionModeTitle.java @@ -28,11 +28,9 @@ import android.view.Menu; import android.view.MenuInflater; import android.view.MenuItem; -import de.arcus.framework.logger.Logger; import de.arcus.playmusicexporter2.R; import de.arcus.playmusicexporter2.activities.MusicTrackListActivity; import de.arcus.playmusicexporter2.activities.MusicContainerListActivity; -import de.arcus.playmusicexporter2.items.SelectedTrack; import de.arcus.playmusicexporter2.items.SelectedTrackList; /** diff --git a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/activities/SettingsActivity.java b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/activities/SettingsActivity.java index 115ff39..d69b7b2 100644 --- a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/activities/SettingsActivity.java +++ b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/activities/SettingsActivity.java @@ -23,14 +23,16 @@ package de.arcus.playmusicexporter2.activities; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; -import android.preference.ListPreference; import android.preference.Preference; import android.preference.PreferenceActivity; import android.preference.PreferenceManager; -import android.text.TextUtils; + +import java.io.File; import de.arcus.framework.activities.DirectoryBrowserActivity; +import de.arcus.framework.logger.Logger; import de.arcus.framework.utils.FileTools; import de.arcus.playmusicexporter2.R; import de.arcus.playmusicexporter2.settings.PlayMusicExporterSettings; @@ -45,7 +47,7 @@ public class SettingsActivity extends PreferenceActivity { private PlayMusicExporterSettings mSettings; // Preferences - private ListPreference mPrefExportPath; + private Preference mPrefExportPath; @Override public void onCreate(Bundle savedInstanceState) { @@ -63,41 +65,22 @@ public class SettingsActivity extends PreferenceActivity { addPreferencesFromResource(R.xml.preferences); // The export path preference - mPrefExportPath = (ListPreference)findPreference("preference_export_path"); - mPrefExportPath.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + mPrefExportPath = findPreference("preference_export_path"); + mPrefExportPath.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { @Override - public boolean onPreferenceChange(Preference preference, Object newValue) { - // The new value - String selectedPath = newValue.toString(); + public boolean onPreferenceClick(Preference preference) { + // Current path + Uri currentPath = mSettings.getUri(PlayMusicExporterSettings.PREF_EXPORT_URI, Uri.EMPTY); - boolean ret = true; + // Starts the directory browser activity + Intent intent = DirectoryBrowserActivity.openDirectoryBrowser(getApplicationContext(), currentPath, getString(R.string.settings_export_path)); + startActivityForResult(intent, REQUEST_EXPORT_PATH); - // Empty = custom - if (TextUtils.isEmpty(selectedPath)) { - // Opens the directory browser - Intent intent = new Intent(getApplicationContext(), DirectoryBrowserActivity.class); - - // The current path - intent.putExtra(DirectoryBrowserActivity.EXTRA_PATH, mSettings.getString(PlayMusicExporterSettings.PREF_EXPORT_PATH, "")); - intent.putExtra(DirectoryBrowserActivity.EXTRA_TITLE, getString(R.string.settings_export_path)); - - // Starts the activity - startActivityForResult(intent, REQUEST_EXPORT_PATH); - - // Do not apply the empty value. - // We wait vor the activity result instead. - ret = false; - } else { - // Saves the path - mSettings.setString(PlayMusicExporterSettings.PREF_EXPORT_PATH, selectedPath); - } - - // Update the entry - updatePrefExportPath(); - - return ret; + // We wait for the activity result + return true; } }); + updatePrefExportPath(); } @@ -106,47 +89,34 @@ public class SettingsActivity extends PreferenceActivity { */ private void updatePrefExportPath() { // Get the path from the settings - String selectedPath = mSettings.getString(PlayMusicExporterSettings.PREF_EXPORT_PATH, ""); + Uri selectedPath = mSettings.getUri(PlayMusicExporterSettings.PREF_EXPORT_URI, Uri.EMPTY); // Get all storage String[] storage = FileTools.getStorages(); String[] storageValues = new String[storage.length + 1]; - String[] storageNames = new String[storage.length + 1]; - int storageSelected = storage.length; - for(int i=0; i 0) { - selectedPath = storageValues[0]; - storageSelected = 0; + if (selectedPath == Uri.EMPTY && storageValues.length > 0) { + selectedPath = Uri.fromFile(new File(storageValues[0])); } - // Custom entry - storageValues[storage.length] = ""; - storageNames[storage.length] = getString(R.string.settings_export_path_custom); + String label; - // Custom is selected - if (storageSelected == storage.length) { - // Adds the custom path to the label - storageNames[storage.length] += "\n" + selectedPath; + if (selectedPath.toString().startsWith("file://")) { + // Simple path + label = selectedPath.getPath(); + } else { + // Uri TODO: Add a nice readable label + label = selectedPath.getPath(); } - mPrefExportPath.setEntries(storageNames); - mPrefExportPath.setEntryValues(storageValues); - mPrefExportPath.setValueIndex(storageSelected); - mPrefExportPath.setSummary(selectedPath); + mPrefExportPath.setSummary(label); } /** @@ -164,6 +134,14 @@ public class SettingsActivity extends PreferenceActivity { // Export path was changed if (requestCode == REQUEST_EXPORT_PATH) { // TODO + Uri uri = data.getData(); + + Logger.getInstance().logInfo("Uri", uri.toString()); + + mSettings.setUri(PlayMusicExporterSettings.PREF_EXPORT_URI, uri); + + // Update the label + updatePrefExportPath(); } } } diff --git a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/fragments/MusicContainerListFragment.java b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/fragments/MusicContainerListFragment.java index 218b6be..a206d66 100644 --- a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/fragments/MusicContainerListFragment.java +++ b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/fragments/MusicContainerListFragment.java @@ -25,7 +25,6 @@ package de.arcus.playmusicexporter2.fragments; import android.app.Activity; import android.os.Bundle; import android.support.v4.app.ListFragment; -import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.ListView; @@ -34,7 +33,6 @@ import java.util.ArrayList; import java.util.List; import de.arcus.playmusicexporter2.adapter.MusicContainerListAdapter; -import de.arcus.playmusicexporter2.items.SelectedTrackList; import de.arcus.playmusiclib.items.MusicTrackList; /** diff --git a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/fragments/MusicTrackListFragment.java b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/fragments/MusicTrackListFragment.java index 8e9c0d7..cb46b52 100644 --- a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/fragments/MusicTrackListFragment.java +++ b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/fragments/MusicTrackListFragment.java @@ -22,11 +22,10 @@ package de.arcus.playmusicexporter2.fragments; +import android.net.Uri; import android.os.Bundle; -import android.os.Environment; import android.support.design.widget.FloatingActionButton; import android.support.v4.app.Fragment; -import android.support.v7.app.AppCompatActivity; import android.text.TextUtils; import android.view.LayoutInflater; import android.view.View; @@ -37,13 +36,13 @@ import android.widget.ListView; import android.widget.TextView; import android.widget.Toast; -import de.arcus.framework.logger.Logger; import de.arcus.playmusicexporter2.R; import de.arcus.playmusicexporter2.activities.MusicContainerListActivity; import de.arcus.playmusicexporter2.activities.MusicTrackListActivity; import de.arcus.playmusicexporter2.adapter.MusicTrackListAdapter; import de.arcus.playmusicexporter2.items.SelectedTrack; import de.arcus.playmusicexporter2.items.SelectedTrackList; +import de.arcus.playmusicexporter2.settings.PlayMusicExporterSettings; import de.arcus.playmusicexporter2.utils.ArtworkViewLoader; import de.arcus.playmusicexporter2.utils.MusicPathBuilder; import de.arcus.playmusiclib.PlayMusicManager; @@ -242,6 +241,9 @@ public class MusicTrackListFragment extends Fragment { // Track is available if (musicTrack.isOfflineAvailable()) { + // Gets the settings + PlayMusicExporterSettings settings = new PlayMusicExporterSettings(getActivity()); + // Default structure String pathStructure = "{album-artist}/{album}/{disc=CD $}/{no=$$.} {title}.mp3"; @@ -254,21 +256,22 @@ public class MusicTrackListFragment extends Fragment { // Build the path String path = MusicPathBuilder.Build(musicTrack, pathStructure); - // Path to the public music folder - path = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC) + "/" + path; + // Gets the root uri + Uri uri = settings.getUri(PlayMusicExporterSettings.PREF_EXPORT_URI, Uri.EMPTY); + // Prevent the closing SelectedTrackList.getInstance().setDoNotCloseActionMode(true); switch (state) { case Select: - SelectedTrackList.getInstance().setSelected(new SelectedTrack(musicTrack.getId(), path), true, view); + SelectedTrackList.getInstance().setSelected(new SelectedTrack(musicTrack.getId(), uri, path), true, view); break; case Deselect: - SelectedTrackList.getInstance().setSelected(new SelectedTrack(musicTrack.getId(), path), false, view); + SelectedTrackList.getInstance().setSelected(new SelectedTrack(musicTrack.getId(), uri, path), false, view); break; case Toggle: - SelectedTrackList.getInstance().toggle(new SelectedTrack(musicTrack.getId(), path), view); + SelectedTrackList.getInstance().toggle(new SelectedTrack(musicTrack.getId(), uri, path), view); break; } diff --git a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/items/SelectedTrack.java b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/items/SelectedTrack.java index 961ffaa..fd5c665 100644 --- a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/items/SelectedTrack.java +++ b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/items/SelectedTrack.java @@ -24,6 +24,7 @@ package de.arcus.playmusicexporter2.items; import android.content.Context; import android.content.Intent; +import android.net.Uri; import de.arcus.playmusicexporter2.services.ExportService; @@ -36,6 +37,11 @@ public class SelectedTrack { */ private long mId; + /** + * The uri of the track + */ + private Uri mUri; + /** * The path of the track */ @@ -45,8 +51,9 @@ public class SelectedTrack { mId = id; } - public SelectedTrack(long id, String path) { + public SelectedTrack(long id, Uri uri, String path) { mId = id; + mUri = uri; mPath = path; } @@ -58,6 +65,7 @@ public class SelectedTrack { // Puts the export parameter intent.putExtra(ExportService.ARG_EXPORT_TRACK_ID, mId); + intent.putExtra(ExportService.ARG_EXPORT_URI, mUri.toString()); intent.putExtra(ExportService.ARG_EXPORT_PATH, mPath); // Starts the service diff --git a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/services/ExportService.java b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/services/ExportService.java index accd82b..4ccdbfc 100644 --- a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/services/ExportService.java +++ b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/services/ExportService.java @@ -26,6 +26,7 @@ import android.app.IntentService; import android.app.Notification; import android.app.NotificationManager; import android.content.Intent; +import android.net.Uri; import android.os.Bundle; import android.support.v4.app.NotificationCompat; @@ -43,6 +44,7 @@ public class ExportService extends IntentService { * Constants for the server instance */ public static final String ARG_EXPORT_TRACK_ID = "track_id"; + public static final String ARG_EXPORT_URI = "uri"; public static final String ARG_EXPORT_PATH = "path"; /** @@ -181,6 +183,7 @@ public class ExportService extends IntentService { // Gets the track information long trackID = bundle.getLong(ARG_EXPORT_TRACK_ID); + Uri uri = Uri.parse(bundle.getString(ARG_EXPORT_URI)); String path = bundle.getString(ARG_EXPORT_PATH); PlayMusicManager playMusicManager = PlayMusicManager.getInstance(); @@ -196,7 +199,7 @@ public class ExportService extends IntentService { updateNotification(); // Exports the song - if(!playMusicManager.exportMusicTrack(mTrackCurrent, path)) { + if(!playMusicManager.exportMusicTrack(mTrackCurrent, uri, path)) { // Export failed mTracksFailed ++; } diff --git a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/settings/PlayMusicExporterSettings.java b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/settings/PlayMusicExporterSettings.java index 6716390..9820a81 100644 --- a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/settings/PlayMusicExporterSettings.java +++ b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/settings/PlayMusicExporterSettings.java @@ -23,6 +23,7 @@ package de.arcus.playmusicexporter2.settings; import android.content.Context; +import android.net.Uri; import android.os.Environment; import de.arcus.framework.settings.AppSettings; @@ -39,7 +40,7 @@ public class PlayMusicExporterSettings extends AppSettings { // Preference constants public static final String PREF_ID3 = "pref_id3"; public static final String PREF_ID3_ARTWORK_SIZE = "pref_id3_artwork_size"; - public static final String PREF_EXPORT_PATH = "pref_export_path"; + public static final String PREF_EXPORT_URI = "pref_export_uri"; public static final String PREF_STRUCTURE_ALBUMS = "pref_structure_albums"; public static final String PREF_STRUCTURE_GROUPS = "pref_structure_groups"; public static final String PREF_DRAWER_LEARNED = "pref_drawer_learned"; @@ -64,8 +65,9 @@ public class PlayMusicExporterSettings extends AppSettings { setInt(PREF_ID3_ARTWORK_SIZE, 512); // Export path - if (!contains(PREF_EXPORT_PATH)) - setString(PREF_EXPORT_PATH, Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC).getAbsolutePath()); + if (!contains(PREF_EXPORT_URI)) + setUri(PREF_EXPORT_URI, Uri.fromFile(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_MUSIC))); + } diff --git a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/utils/ArtworkViewLoader.java b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/utils/ArtworkViewLoader.java index e14381e..3c0e570 100644 --- a/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/utils/ArtworkViewLoader.java +++ b/playmusicexporter/src/main/java/de/arcus/playmusicexporter2/utils/ArtworkViewLoader.java @@ -27,7 +27,6 @@ import android.widget.ImageView; import java.lang.ref.WeakReference; -import de.arcus.framework.logger.Logger; import de.arcus.playmusicexporter2.R; import de.arcus.playmusiclib.ArtworkLoader; import de.arcus.playmusiclib.ArtworkLoaderCallback; diff --git a/playmusicexporter/src/main/res/xml/preferences.xml b/playmusicexporter/src/main/res/xml/preferences.xml index 2081647..73cc15a 100644 --- a/playmusicexporter/src/main/res/xml/preferences.xml +++ b/playmusicexporter/src/main/res/xml/preferences.xml @@ -25,7 +25,7 @@ - diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java index 7f0373f..84aebe2 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/PlayMusicManager.java @@ -28,7 +28,11 @@ import android.content.pm.PackageManager; import android.database.SQLException; import android.database.sqlite.SQLiteDatabase; import android.graphics.Bitmap; +import android.net.Uri; +import android.os.Build; import android.os.Environment; +import android.os.ParcelFileDescriptor; +import android.support.v4.provider.DocumentFile; import android.text.TextUtils; import com.mpatric.mp3agic.ID3v1Genres; @@ -41,6 +45,10 @@ import com.mpatric.mp3agic.Mp3File; import java.io.ByteArrayOutputStream; import java.io.File; +import java.io.FileInputStream; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; import java.util.ArrayList; import java.util.List; @@ -48,7 +56,6 @@ import de.arcus.framework.logger.Logger; import de.arcus.framework.superuser.SuperUser; import de.arcus.framework.superuser.SuperUserTools; import de.arcus.framework.utils.FileTools; -import de.arcus.framework.utils.MediaScanner; import de.arcus.playmusiclib.enums.ID3v2Version; import de.arcus.playmusiclib.exceptions.CouldNotOpenDatabaseException; import de.arcus.playmusiclib.exceptions.NoSuperUserException; @@ -447,6 +454,7 @@ public class PlayMusicManager { return path; } + /** * Exports a track to the sd card * @param musicTrack The music track you want to export @@ -454,6 +462,24 @@ public class PlayMusicManager { * @return Returns whether the export was successful */ public boolean exportMusicTrack(MusicTrack musicTrack, String dest) { + // Creates the destination directory + File directory = new File(dest).getParentFile(); + + + // Filename + String filename = new File(dest).getName(); + + return exportMusicTrack(musicTrack, Uri.fromFile(directory), filename); + } + + /** + * Exports a track to the sd card + * @param musicTrack The music track you want to export + * @param uri The document tree + * @return Returns whether the export was successful + */ + public boolean exportMusicTrack(MusicTrack musicTrack, Uri uri, String path) { + // Check for null if (musicTrack == null) return false; @@ -484,10 +510,64 @@ public class PlayMusicManager { } } - // Creates the destination directory - String directory = new File(dest).getParent(); - if (directory != null && !FileTools.directoryExists(directory)) - FileTools.directoryCreate(directory); + + + 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"; + + // 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"); + + // Gets the output stream + FileOutputStream fileOutputStream = new FileOutputStream(parcelFileDescriptor.getFileDescriptor()); + + // Gets the input stream + FileInputStream fileInputStream = new FileInputStream(dest); + + // Copy the stream + FileTools.fileCopy(fileInputStream, fileOutputStream); + + // Close all streams + fileOutputStream.close(); + fileInputStream.close(); + parcelFileDescriptor.close(); + + } 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; + } + } + } + + // Delete temp files cleanUp(); // Adds the file to the media system - new MediaScanner(mContext, dest); + //new MediaScanner(mContext, dest); // Done return true; @@ -624,6 +741,7 @@ public class PlayMusicManager { // Save the file mp3File.save(dest); + // Done return true; } catch (Exception e) { @@ -667,6 +785,7 @@ 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"); } diff --git a/playmusiclib/src/main/java/de/arcus/playmusiclib/items/ArtworkEntry.java b/playmusiclib/src/main/java/de/arcus/playmusiclib/items/ArtworkEntry.java index 7223d43..1bc9f5f 100644 --- a/playmusiclib/src/main/java/de/arcus/playmusiclib/items/ArtworkEntry.java +++ b/playmusiclib/src/main/java/de/arcus/playmusiclib/items/ArtworkEntry.java @@ -25,7 +25,7 @@ package de.arcus.playmusiclib.items; import de.arcus.playmusiclib.PlayMusicManager; /** - * Created by david on 14.05.15. + * Artwork entry */ public class ArtworkEntry { /**