mirror of
https://github.com/playmusicexporter/playmusicexporter
synced 2024-05-14 16:46:42 +00:00
Adds support for Lollipop file api (access to external sdcard)
This commit is contained in:
parent
76138eb1f6
commit
0286f2994a
7
.idea/dictionaries/david.xml
Normal file
7
.idea/dictionaries/david.xml
Normal file
|
@ -0,0 +1,7 @@
|
|||
<component name="ProjectDictionaryState">
|
||||
<dictionary name="david">
|
||||
<words>
|
||||
<w>simpel</w>
|
||||
</words>
|
||||
</dictionary>
|
||||
</component>
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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());
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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<storage.length; i++) {
|
||||
String path = storage[i] + "/Music";
|
||||
storageValues[i] = path;
|
||||
storageNames[i] = path;
|
||||
|
||||
// Is storage selected?
|
||||
if (selectedPath.equals(path)) {
|
||||
storageSelected = i;
|
||||
}
|
||||
}
|
||||
|
||||
// If the path is not set, we use the first default value.
|
||||
// This should not happen, because we set the default value in the
|
||||
// PlayMusicExporterSettings constructor, but i want to be sure.
|
||||
if (selectedPath.equals("") && storageValues.length > 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();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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 ++;
|
||||
}
|
||||
|
|
|
@ -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)));
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -25,7 +25,7 @@
|
|||
<!-- Export settings -->
|
||||
<PreferenceCategory android:title="@string/settings_category_export">
|
||||
<!-- Export path -->
|
||||
<ListPreference android:title="@string/settings_export_path"
|
||||
<Preference android:title="@string/settings_export_path"
|
||||
android:key="preference_export_path"/>
|
||||
|
||||
<!-- Path structure for albums -->
|
||||
|
|
|
@ -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<directories.length - 1; i++) {
|
||||
String directoryName = directories[i];
|
||||
boolean found = false;
|
||||
|
||||
// Search all sub elements
|
||||
for (DocumentFile subDocument: document.listFiles()) {
|
||||
// Directory exists
|
||||
if (subDocument.isDirectory() && subDocument.getName().equals(directoryName)) {
|
||||
document = subDocument;
|
||||
found = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!found) {
|
||||
// Create the directory
|
||||
document = document.createDirectory(directoryName);
|
||||
}
|
||||
}
|
||||
|
||||
// Gets the filename
|
||||
String filename = directories[directories.length - 1];
|
||||
|
||||
for (DocumentFile subDocument: document.listFiles()) {
|
||||
// Directory exists
|
||||
if (subDocument.isFile() && subDocument.getName().equals(filename)) {
|
||||
// Delete the file
|
||||
subDocument.delete();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
// Create the mp3 file
|
||||
document = document.createFile("music/mp3", filename);
|
||||
|
||||
// Create the directories
|
||||
copyUri = document.getUri();
|
||||
}
|
||||
|
||||
|
||||
// We want to export the ID3 tags
|
||||
if (mID3Enable) {
|
||||
|
@ -513,10 +593,47 @@ public class PlayMusicManager {
|
|||
}
|
||||
}
|
||||
|
||||
// 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 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");
|
||||
}
|
||||
|
|
|
@ -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 {
|
||||
/**
|
||||
|
|
Loading…
Reference in a new issue