Merge branch 'release/v0.9.6.0' into develop

This commit is contained in:
Jan Christian Grünhage 2017-03-29 00:31:32 +02:00
commit 1861adfd22
Signed by: jcgruenhage
GPG key ID: 321A67D9EE8BC3E1
16 changed files with 111 additions and 249 deletions

View file

@ -27,7 +27,7 @@ buildscript {
jcenter() jcenter()
} }
dependencies { dependencies {
classpath 'com.android.tools.build:gradle:2.4.0-alpha3' classpath 'com.android.tools.build:gradle:2.3.0'
} }
} }

View file

@ -29,6 +29,7 @@ import java.io.IOException;
import java.io.InputStream; import java.io.InputStream;
import java.io.OutputStream; import java.io.OutputStream;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collections; import java.util.Collections;
import java.util.List; import java.util.List;
@ -309,9 +310,7 @@ public class FileTools {
} }
// Remove all blacklisted paths // Remove all blacklisted paths
for (String blacklistPath : mountPointBlacklist) { storages.removeAll(Arrays.asList(mountPointBlacklist));
storages.remove(blacklistPath);
}
// Sort the list // Sort the list
Collections.sort(storages); Collections.sort(storages);

View file

@ -31,8 +31,8 @@ android {
minSdkVersion 21 minSdkVersion 21
targetSdkVersion 25 targetSdkVersion 25
// TODO Change Version with releases // TODO Change Version with releases
versionCode 109 versionCode 110
versionName '0.9.5.2' versionName '0.9.6.0'
vectorDrawables.useSupportLibrary = true vectorDrawables.useSupportLibrary = true
jackOptions { jackOptions {

View file

@ -4,7 +4,6 @@ import android.Manifest;
import android.content.Intent; import android.content.Intent;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.graphics.Color; import android.graphics.Color;
import android.os.AsyncTask;
import android.os.Build; import android.os.Build;
import android.os.Bundle; import android.os.Bundle;
import android.support.annotation.Nullable; import android.support.annotation.Nullable;

View file

@ -25,7 +25,6 @@ import re.jcg.playmusicexporter.settings.PlayMusicExporterPreferences;
import java.text.SimpleDateFormat; import java.text.SimpleDateFormat;
import java.util.List; import java.util.List;
import java.util.stream.Collectors;
/** /**
* A {@link PreferenceActivity} that presents a set of application settings. On * A {@link PreferenceActivity} that presents a set of application settings. On
@ -47,31 +46,28 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
* A preference value change listener that updates the preference's summary * A preference value change listener that updates the preference's summary
* to reflect its new value. * to reflect its new value.
*/ */
private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = new Preference.OnPreferenceChangeListener() { private static Preference.OnPreferenceChangeListener sBindPreferenceSummaryToValueListener = (preference, value) -> {
@Override String stringValue = value.toString();
public boolean onPreferenceChange(Preference preference, Object value) {
String stringValue = value.toString();
if (preference instanceof ListPreference) { if (preference instanceof ListPreference) {
// For list preferences, look up the correct display value in // For list preferences, look up the correct display value in
// the preference's 'entries' list. // the preference's 'entries' list.
ListPreference listPreference = (ListPreference) preference; ListPreference listPreference = (ListPreference) preference;
int index = listPreference.findIndexOfValue(stringValue); int index = listPreference.findIndexOfValue(stringValue);
// Set the summary to reflect the new value. // Set the summary to reflect the new value.
preference.setSummary( preference.setSummary(
index >= 0 index >= 0
? listPreference.getEntries()[index] ? listPreference.getEntries()[index]
: null); : null);
} else { } else {
// For all other preferences, set the summary to the value's // For all other preferences, set the summary to the value's
// simple string representation. // simple string representation.
preference.setSummary(stringValue); preference.setSummary(stringValue);
}
return true;
} }
return true;
}; };
/** /**
@ -154,19 +150,13 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
setHasOptionsMenu(true); setHasOptionsMenu(true);
findPreference("preference_alba_export_path").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { findPreference("preference_alba_export_path").setOnPreferenceClickListener(preference -> {
@Override startActivityForResult(new Intent("android.intent.action.OPEN_DOCUMENT_TREE"), REQUEST_CODE_OPEN_DOCUMENT_TREE_ALBA_PATH);
public boolean onPreferenceClick(Preference preference) { return true;
startActivityForResult(new Intent("android.intent.action.OPEN_DOCUMENT_TREE"), REQUEST_CODE_OPEN_DOCUMENT_TREE_ALBA_PATH);
return true;
}
}); });
findPreference("preference_groups_export_path").setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { findPreference("preference_groups_export_path").setOnPreferenceClickListener(preference -> {
@Override startActivityForResult(new Intent("android.intent.action.OPEN_DOCUMENT_TREE"), REQUEST_CODE_OPEN_DOCUMENT_TREE_GROUPS_PATH);
public boolean onPreferenceClick(Preference preference) { return true;
startActivityForResult(new Intent("android.intent.action.OPEN_DOCUMENT_TREE"), REQUEST_CODE_OPEN_DOCUMENT_TREE_GROUPS_PATH);
return true;
}
}); });
} }
@ -240,12 +230,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
} }
private void setupOnClickListeners() { private void setupOnClickListeners() {
findPreference(PlayMusicExporterPreferences.AUTO_EXPORT_PATH).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { findPreference(PlayMusicExporterPreferences.AUTO_EXPORT_PATH).setOnPreferenceClickListener(preference -> {
@Override startActivityForResult(new Intent("android.intent.action.OPEN_DOCUMENT_TREE"), REQUEST_CODE_OPEN_DOCUMENT_TREE_AUTO_PATH);
public boolean onPreferenceClick(Preference preference) { return true;
startActivityForResult(new Intent("android.intent.action.OPEN_DOCUMENT_TREE"), REQUEST_CODE_OPEN_DOCUMENT_TREE_AUTO_PATH);
return true;
}
}); });
//For every setting that is used to define the export job, setup a listener that //For every setting that is used to define the export job, setup a listener that
@ -256,12 +243,9 @@ public class SettingsActivity extends AppCompatPreferenceActivity {
} }
private void setupRescheduler(String preference) { private void setupRescheduler(String preference) {
findPreference(preference).setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { findPreference(preference).setOnPreferenceClickListener(preference1 -> {
@Override ExportAllJob.scheduleExport(getContext());
public boolean onPreferenceClick(Preference preference) { return false;
ExportAllJob.scheduleExport(getContext());
return false;
}
}); });
} }

View file

@ -79,10 +79,7 @@ public class MusicContainerListFragment extends ListFragment {
* A dummy implementation of the {@link Callbacks} interface that does * A dummy implementation of the {@link Callbacks} interface that does
* nothing. Used only when this fragment is not attached to an activity. * nothing. Used only when this fragment is not attached to an activity.
*/ */
private static Callbacks sDummyCallbacks = new Callbacks() { private static Callbacks sDummyCallbacks = musicTrackList -> {
@Override
public void onItemSelected(MusicTrackList musicTrackList) {
}
}; };
private MusicContainerListAdapter mMusicTrackListAdapter; private MusicContainerListAdapter mMusicTrackListAdapter;
@ -112,9 +109,7 @@ public class MusicContainerListFragment extends ListFragment {
// Null check // Null check
if (list != null) { if (list != null) {
// Copy the list // Copy the list
for (MusicTrackList musicTrackList : list) { newList.addAll(list);
newList.add(musicTrackList);
}
} }
// Set the list in the adapter // Set the list in the adapter
@ -145,7 +140,8 @@ public class MusicContainerListFragment extends ListFragment {
setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION)); setActivatedPosition(savedInstanceState.getInt(STATE_ACTIVATED_POSITION));
} }
} }
// DEPRECATED
// DEPRECATED
@Override @Override
public void onAttach(Context context) { public void onAttach(Context context) {
super.onAttach(context); super.onAttach(context);

View file

@ -32,7 +32,6 @@ import android.text.TextUtils;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ImageView; import android.widget.ImageView;
import android.widget.ListView; import android.widget.ListView;
import android.widget.TextView; import android.widget.TextView;
@ -197,43 +196,36 @@ public class MusicTrackListFragment extends Fragment {
mListView.setAdapter(mMusicTrackAdapter); mListView.setAdapter(mMusicTrackAdapter);
// Click on one list item // Click on one list item
mListView.setOnItemClickListener(new AdapterView.OnItemClickListener() { mListView.setOnItemClickListener((parent, view, position, id) -> {
@Override // The header is not clicked
public void onItemClick(AdapterView<?> parent, View view, int position, long id) { if (position > 0) {
// The header is not clicked // We need to subtract the header view
if (position > 0) { position -= 1;
// We need to subtract the header view
position -= 1;
// Gets the selected track // Gets the selected track
MusicTrack musicTrack = mMusicTrackAdapter.getItem(position); MusicTrack musicTrack = mMusicTrackAdapter.getItem(position);
// Toggle the track // Toggle the track
selectTrack(musicTrack, view, TrackSelectionState.Toggle); selectTrack(musicTrack, view, TrackSelectionState.Toggle);
}
} }
}); });
// The floating action button // The floating action button
mFloatingButtonExport = (FloatingActionButton) rootView.findViewById(R.id.floating_button_export); mFloatingButtonExport = (FloatingActionButton) rootView.findViewById(R.id.floating_button_export);
mFloatingButtonExport.setOnClickListener(new View.OnClickListener() { mFloatingButtonExport.setOnClickListener(v -> {
@Override m_CPULock.acquire();
public void onClick(View v) // Export all selected tracks
{ for (SelectedTrack selectedTrack : SelectedTrackList.getInstance().getSelectedItems()) {
m_CPULock.acquire(); selectedTrack.export(getActivity());
// Export all selected tracks
for (SelectedTrack selectedTrack : SelectedTrackList.getInstance().getSelectedItems()) {
selectedTrack.export(getActivity());
}
if ( m_CPULock.isHeld())
{
m_CPULock.release();
}
// Clear the selection
SelectedTrackList.getInstance().clear(true);
} }
if ( m_CPULock.isHeld())
{
m_CPULock.release();
}
// Clear the selection
SelectedTrackList.getInstance().clear(true);
}); });
updateFloatingButton(); updateFloatingButton();
} }

View file

@ -22,7 +22,6 @@
package re.jcg.playmusicexporter.fragments; package re.jcg.playmusicexporter.fragments;
import android.app.Activity;
import android.content.Context; import android.content.Context;
import android.content.Intent; import android.content.Intent;
import android.content.res.Configuration; import android.content.res.Configuration;
@ -160,47 +159,24 @@ public class NavigationDrawerFragment extends Fragment {
setViewType(mViewType); setViewType(mViewType);
// Click on album // Click on album
mButtonTypeAlbum.setOnClickListener(new View.OnClickListener() { mButtonTypeAlbum.setOnClickListener(v -> setViewType(ViewType.Album));
@Override
public void onClick(View v) {
setViewType(ViewType.Album);
}
});
// Click on artist // Click on artist
mButtonTypeArtist.setOnClickListener(new View.OnClickListener() { mButtonTypeArtist.setOnClickListener(v -> setViewType(ViewType.Artist));
@Override
public void onClick(View v) {
setViewType(ViewType.Artist);
}
});
// Click on playlist // Click on playlist
mButtonTypePlaylist.setOnClickListener(new View.OnClickListener() { mButtonTypePlaylist.setOnClickListener(v -> setViewType(ViewType.Playlist));
@Override
public void onClick(View v) {
setViewType(ViewType.Playlist);
}
});
// Click on rated // Click on rated
mButtonTypeRated.setOnClickListener(new View.OnClickListener() { mButtonTypeRated.setOnClickListener(v -> setViewType(ViewType.Rated));
@Override
public void onClick(View v) {
setViewType(ViewType.Rated);
}
});
// Click on settings // Click on settings
mButtonSettings.setOnClickListener(new View.OnClickListener() { mButtonSettings.setOnClickListener(v -> {
@Override Intent intentSettings = new Intent(getActivity(), SettingsActivity.class);
public void onClick(View v) { startActivity(intentSettings);
Intent intentSettings = new Intent(getActivity(), SettingsActivity.class);
startActivity(intentSettings);
// Close the drawer // Close the drawer
mDrawerLayout.closeDrawers(); mDrawerLayout.closeDrawers();
}
}); });
// Color the settings button // Color the settings button
@ -307,12 +283,7 @@ public class NavigationDrawerFragment extends Fragment {
} }
// Defer code dependent on restoration of previous instance state. // Defer code dependent on restoration of previous instance state.
mDrawerLayout.post(new Runnable() { mDrawerLayout.post(mDrawerToggle::syncState);
@Override
public void run() {
mDrawerToggle.syncState();
}
});
mDrawerLayout.setDrawerListener(mDrawerToggle); mDrawerLayout.setDrawerListener(mDrawerToggle);
} }

View file

@ -7,11 +7,6 @@ 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;

View file

@ -30,12 +30,6 @@ 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;

View file

@ -22,14 +22,12 @@
package re.jcg.playmusicexporter.utils; package re.jcg.playmusicexporter.utils;
import android.graphics.Bitmap;
import android.widget.ImageView; import android.widget.ImageView;
import java.lang.ref.WeakReference; import java.lang.ref.WeakReference;
import re.jcg.playmusicexporter.R; import re.jcg.playmusicexporter.R;
import de.arcus.playmusiclib.ArtworkLoader; import de.arcus.playmusiclib.ArtworkLoader;
import de.arcus.playmusiclib.ArtworkLoaderCallback;
import de.arcus.playmusiclib.items.ArtworkEntry; import de.arcus.playmusiclib.items.ArtworkEntry;
/** /**
@ -121,13 +119,10 @@ public class ArtworkViewLoader {
maximalArtworkSize = imageViewDefault.getContext().getResources().getDimensionPixelSize(R.dimen.music_track_artwork_loading_size); maximalArtworkSize = imageViewDefault.getContext().getResources().getDimensionPixelSize(R.dimen.music_track_artwork_loading_size);
// Sets the bitmap in the UI thread // Sets the bitmap in the UI thread
Runnable runnable = new Runnable() { Runnable runnable = () -> {
@Override // Default icon
public void run() { imageViewDefault.setImageResource(mDefaultImage);
// Default icon
imageViewDefault.setImageResource(mDefaultImage);
}
}; };
imageViewDefault.post(runnable); imageViewDefault.post(runnable);
} }
@ -138,36 +133,30 @@ public class ArtworkViewLoader {
mIsLoading = true; mIsLoading = true;
// Load the artwork // Load the artwork
ArtworkLoader.loadArtworkAsync(mArtworkEntry, maximalArtworkSize, new ArtworkLoaderCallback() { ArtworkLoader.loadArtworkAsync(mArtworkEntry, maximalArtworkSize, bitmap -> {
@Override final ImageView imageView = mImageView.get();
public void onFinished(final Bitmap bitmap) {
final ImageView imageView = mImageView.get();
if (imageViewDefault != null) { if (imageViewDefault != null) {
// Sets the bitmap in the UI thread // Sets the bitmap in the UI thread
Runnable runnable = new Runnable() { Runnable runnable = () -> {
@Override // Bitmap is valid
public void run() { if (bitmap != null)
// Bitmap is valid imageView.setImageBitmap(bitmap);
if (bitmap != null) else
imageView.setImageBitmap(bitmap); imageView.setImageResource(mDefaultImage);
else };
imageView.setImageResource(mDefaultImage); imageView.post(runnable);
} }
};
imageView.post(runnable);
}
// Loading is done // Loading is done
mIsLoading = false; mIsLoading = false;
// Loads the next image // Loads the next image
if (mNewArtworkEntry != null) { if (mNewArtworkEntry != null) {
mArtworkEntry = mNewArtworkEntry; mArtworkEntry = mNewArtworkEntry;
mNewArtworkEntry = null; mNewArtworkEntry = null;
loadImage(); loadImage();
}
} }
}); });
} }

View file

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015 David Schulte
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in
~ all copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
~ THE SOFTWARE.
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/button_navigation_drawer_hover">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/button_navigation_drawer_normal"/>
</shape>
</item>
</ripple>

View file

@ -1,31 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<!--
~ Copyright (c) 2015 David Schulte
~
~ Permission is hereby granted, free of charge, to any person obtaining a copy
~ of this software and associated documentation files (the "Software"), to deal
~ in the Software without restriction, including without limitation the rights
~ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
~ copies of the Software, and to permit persons to whom the Software is
~ furnished to do so, subject to the following conditions:
~
~ The above copyright notice and this permission notice shall be included in
~ all copies or substantial portions of the Software.
~
~ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
~ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
~ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
~ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
~ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
~ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
~ THE SOFTWARE.
-->
<ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:color="@color/button_navigation_drawer_hover">
<item>
<shape android:shape="rectangle">
<solid android:color="@color/button_navigation_drawer_selected"/>
</shape>
</item>
</ripple>

View file

@ -21,7 +21,11 @@
~ THE SOFTWARE. ~ THE SOFTWARE.
--> -->
<shape xmlns:android="http://schemas.android.com/apk/res/android" <ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:color="@color/button_navigation_drawer_hover">
<solid android:color="@color/button_navigation_drawer_normal"/> <item>
</shape> <shape android:shape="rectangle">
<solid android:color="@color/button_navigation_drawer_normal"/>
</shape>
</item>
</ripple>

View file

@ -21,7 +21,11 @@
~ THE SOFTWARE. ~ THE SOFTWARE.
--> -->
<shape xmlns:android="http://schemas.android.com/apk/res/android" <ripple xmlns:android="http://schemas.android.com/apk/res/android"
android:shape="rectangle"> android:color="@color/button_navigation_drawer_hover">
<solid android:color="@color/button_navigation_drawer_selected"/> <item>
</shape> <shape android:shape="rectangle">
<solid android:color="@color/button_navigation_drawer_selected"/>
</shape>
</item>
</ripple>

View file

@ -25,7 +25,6 @@ package de.arcus.playmusiclib;
import android.content.Context; import android.content.Context;
import android.content.pm.ApplicationInfo; import android.content.pm.ApplicationInfo;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.database.Cursor;
import android.database.SQLException; import android.database.SQLException;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.graphics.Bitmap; import android.graphics.Bitmap;
@ -33,10 +32,8 @@ import android.net.Uri;
import android.os.Build; import android.os.Build;
import android.os.Environment; import android.os.Environment;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.support.v4.content.FileProvider;
import android.support.v4.provider.DocumentFile; import android.support.v4.provider.DocumentFile;
import android.text.TextUtils; import android.text.TextUtils;
import android.util.Log;
import com.mpatric.mp3agic.ID3v1Genres; import com.mpatric.mp3agic.ID3v1Genres;
import com.mpatric.mp3agic.ID3v1Tag; import com.mpatric.mp3agic.ID3v1Tag;
@ -557,7 +554,7 @@ public class PlayMusicManager {
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;