diff --git a/app/build.gradle b/app/build.gradle index 8d1c4719..28921a3c 100644 --- a/app/build.gradle +++ b/app/build.gradle @@ -94,8 +94,11 @@ dependencies { compile 'com.nostra13.universalimageloader:universal-image-loader:1.9.4' - compile 'com.afollestad:material-dialogs:0.7.7.0' + compile 'com.afollestad:material-dialogs:0.7.8.1' compile 'com.afollestad:material-cab:0.1.4' compile 'com.jakewharton:butterknife:7.0.1' + + debugCompile 'com.squareup.leakcanary:leakcanary-android:1.3.1' + releaseCompile 'com.squareup.leakcanary:leakcanary-android-no-op:1.3.1' } diff --git a/app/proguard-rules.pro b/app/proguard-rules.pro index 6739e10b..5c6e8779 100644 --- a/app/proguard-rules.pro +++ b/app/proguard-rules.pro @@ -22,19 +22,22 @@ -keepattributes Signature -keepattributes Exceptions --keep class !android.support.v7.internal.view.menu.**,** {*;} +# LeakCanary +-keep class org.eclipse.mat.** { *; } +-keep class com.squareup.leakcanary.** { *; } +# ButterKnife -keep class butterknife.** { *; } -dontwarn butterknife.internal.** -keep class **$$ViewBinder { *; } - -keepclasseswithmembernames class * { @butterknife.* ; } - -keepclasseswithmembernames class * { @butterknife.* ; } +-keep class !android.support.v7.internal.view.menu.**,** {*;} + -dontwarn -ignorewarnings \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/App.java b/app/src/main/java/com/kabouzeid/gramophone/App.java index b1f0cb29..057367ec 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/App.java +++ b/app/src/main/java/com/kabouzeid/gramophone/App.java @@ -1,12 +1,15 @@ package com.kabouzeid.gramophone; import android.app.Application; +import android.content.Context; import com.crashlytics.android.Crashlytics; import com.kabouzeid.gramophone.imageloader.PhonographImageDownloader; import com.nostra13.universalimageloader.core.ImageLoader; import com.nostra13.universalimageloader.core.ImageLoaderConfiguration; import com.nostra13.universalimageloader.utils.L; +import com.squareup.leakcanary.LeakCanary; +import com.squareup.leakcanary.RefWatcher; import io.fabric.sdk.android.Fabric; @@ -16,12 +19,21 @@ import io.fabric.sdk.android.Fabric; public class App extends Application { public static final String TAG = App.class.getSimpleName(); + private RefWatcher refWatcher; + + public static RefWatcher getRefWatcher(Context context) { + App application = (App) context.getApplicationContext(); + return application.refWatcher; + } + @Override public void onCreate() { super.onCreate(); if (!BuildConfig.DEBUG) Fabric.with(this, new Crashlytics()); + refWatcher = LeakCanary.install(this); + ImageLoaderConfiguration config = new ImageLoaderConfiguration.Builder(this) .imageDownloader(new PhonographImageDownloader(this)) .memoryCacheSizePercentage(30) diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/AboutDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/AboutDialog.java index 8890a0a9..67fb7b8c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/AboutDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/AboutDialog.java @@ -5,7 +5,6 @@ import android.content.Context; import android.content.pm.PackageManager; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.text.TextUtils; import com.afollestad.materialdialogs.MaterialDialog; @@ -14,7 +13,17 @@ import com.kabouzeid.gramophone.R; /** * @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad) */ -public class AboutDialog extends DialogFragment { +public class AboutDialog extends LeakDetectDialogFragment { + + private static String getCurrentVersionName(@NonNull final Context context) { + String versionName; + try { + versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; + } catch (PackageManager.NameNotFoundException e) { + return "Unknown"; + } + return versionName; + } @NonNull @Override @@ -30,14 +39,4 @@ public class AboutDialog extends DialogFragment { .positiveText(android.R.string.ok) .build(); } - - private static String getCurrentVersionName(@NonNull final Context context) { - String versionName; - try { - versionName = context.getPackageManager().getPackageInfo(context.getPackageName(), 0).versionName; - } catch (PackageManager.NameNotFoundException e) { - return "Unknown"; - } - return versionName; - } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/AddToPlaylistDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/AddToPlaylistDialog.java index bcd83260..9f72f74f 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/AddToPlaylistDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/AddToPlaylistDialog.java @@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Dialog; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.view.View; import com.afollestad.materialdialogs.MaterialDialog; @@ -19,7 +18,7 @@ import java.util.List; /** * @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad) */ -public class AddToPlaylistDialog extends DialogFragment { +public class AddToPlaylistDialog extends LeakDetectDialogFragment { @NonNull public static AddToPlaylistDialog create(Song song) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/ClearSmartPlaylistDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/ClearSmartPlaylistDialog.java index e65957b4..f7104664 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/ClearSmartPlaylistDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/ClearSmartPlaylistDialog.java @@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Dialog; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.text.Html; import com.afollestad.materialdialogs.MaterialDialog; @@ -13,7 +12,7 @@ import com.kabouzeid.gramophone.model.smartplaylist.AbsSmartPlaylist; /** * @author Karim Abou Zeid (kabouzeid) */ -public class ClearSmartPlaylistDialog extends DialogFragment { +public class ClearSmartPlaylistDialog extends LeakDetectDialogFragment { @NonNull public static ClearSmartPlaylistDialog create(AbsSmartPlaylist playlist) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/ColorChooserDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/ColorChooserDialog.java index 9696d9f9..c7ee089d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/ColorChooserDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/ColorChooserDialog.java @@ -2,7 +2,6 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Activity; import android.app.Dialog; -import android.app.DialogFragment; import android.content.res.ColorStateList; import android.content.res.TypedArray; import android.graphics.Color; @@ -16,6 +15,7 @@ import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; import android.support.v4.content.res.ResourcesCompat; +import android.support.v7.app.AppCompatActivity; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; @@ -30,12 +30,33 @@ import com.kabouzeid.gramophone.views.ColorView; /** * @author Aidan Follestad (afollestad) */ -public class ColorChooserDialog extends DialogFragment implements View.OnClickListener { +public class ColorChooserDialog extends LeakDetectDialogFragment implements View.OnClickListener { private ColorCallback mCallback; private int[] mColors; private GridView mGrid; + public ColorChooserDialog() { + } + + private static int translucentColor(int color) { + final float factor = 0.7f; + int alpha = Math.round(Color.alpha(color) * factor); + int red = Color.red(color); + int green = Color.green(color); + int blue = Color.blue(color); + return Color.argb(alpha, red, green, blue); + } + + @NonNull + private static Drawable createSelector(int color) { + ShapeDrawable darkerCircle = new ShapeDrawable(new OvalShape()); + darkerCircle.getPaint().setColor(translucentColor(ColorUtil.shiftColorDown(color))); + StateListDrawable stateListDrawable = new StateListDrawable(); + stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, darkerCircle); + return stateListDrawable; + } + @Override public void onAttach(Activity activity) { super.onAttach(activity); @@ -51,13 +72,6 @@ public class ColorChooserDialog extends DialogFragment implements View.OnClickLi } } - public interface ColorCallback { - void onColorSelection(int title, int color); - } - - public ColorChooserDialog() { - } - @Override public Dialog onCreateDialog(Bundle savedInstanceState) { MaterialDialog dialog = new MaterialDialog.Builder(getActivity()) @@ -111,6 +125,18 @@ public class ColorChooserDialog extends DialogFragment implements View.OnClickLi } else ((BaseAdapter) mGrid.getAdapter()).notifyDataSetChanged(); } + public void show(@NonNull AppCompatActivity activity, int title, int preselect) { + Bundle args = new Bundle(); + args.putInt("preselect", preselect); + args.putInt("title", title); + setArguments(args); + show(activity.getSupportFragmentManager(), "COLOR_SELECTOR"); + } + + public interface ColorCallback { + void onColorSelection(int title, int color); + } + private class ColorGridAdapter extends BaseAdapter implements View.OnClickListener { public ColorGridAdapter() { @@ -166,30 +192,4 @@ public class ColorChooserDialog extends DialogFragment implements View.OnClickLi invalidateGrid(); } } - - private static int translucentColor(int color) { - final float factor = 0.7f; - int alpha = Math.round(Color.alpha(color) * factor); - int red = Color.red(color); - int green = Color.green(color); - int blue = Color.blue(color); - return Color.argb(alpha, red, green, blue); - } - - @NonNull - private static Drawable createSelector(int color) { - ShapeDrawable darkerCircle = new ShapeDrawable(new OvalShape()); - darkerCircle.getPaint().setColor(translucentColor(ColorUtil.shiftColorDown(color))); - StateListDrawable stateListDrawable = new StateListDrawable(); - stateListDrawable.addState(new int[]{android.R.attr.state_pressed}, darkerCircle); - return stateListDrawable; - } - - public void show(@NonNull Activity context, int title, int preselect) { - Bundle args = new Bundle(); - args.putInt("preselect", preselect); - args.putInt("title", title); - setArguments(args); - show(context.getFragmentManager(), "COLOR_SELECTOR"); - } } \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/CreatePlaylistDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/CreatePlaylistDialog.java index ef08ba0e..05ff8755 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/CreatePlaylistDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/CreatePlaylistDialog.java @@ -4,7 +4,6 @@ import android.app.Dialog; import android.os.Bundle; import android.support.annotation.NonNull; import android.support.annotation.Nullable; -import android.support.v4.app.DialogFragment; import android.text.InputType; import com.afollestad.materialdialogs.MaterialDialog; @@ -17,7 +16,7 @@ import java.util.ArrayList; /** * @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad) */ -public class CreatePlaylistDialog extends DialogFragment { +public class CreatePlaylistDialog extends LeakDetectDialogFragment { @NonNull public static CreatePlaylistDialog create() { diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/DeletePlaylistDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/DeletePlaylistDialog.java index 2b92f779..18c6bbd8 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/DeletePlaylistDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/DeletePlaylistDialog.java @@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Dialog; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.text.Html; import com.afollestad.materialdialogs.MaterialDialog; @@ -16,7 +15,7 @@ import java.util.ArrayList; /** * @author Karim Abou Zeid (kabouzeid) */ -public class DeletePlaylistDialog extends DialogFragment { +public class DeletePlaylistDialog extends LeakDetectDialogFragment { @NonNull public static DeletePlaylistDialog create(Playlist playlist) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/DeleteSongsDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/DeleteSongsDialog.java index 883b9a31..4f0092af 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/DeleteSongsDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/DeleteSongsDialog.java @@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Dialog; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.text.Html; import com.afollestad.materialdialogs.MaterialDialog; @@ -16,7 +15,7 @@ import java.util.ArrayList; /** * @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad) */ -public class DeleteSongsDialog extends DialogFragment { +public class DeleteSongsDialog extends LeakDetectDialogFragment { @NonNull public static DeleteSongsDialog create(Song song) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/LeakDetectDialogFragment.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/LeakDetectDialogFragment.java new file mode 100644 index 00000000..6dd34b33 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/LeakDetectDialogFragment.java @@ -0,0 +1,21 @@ +package com.kabouzeid.gramophone.dialogs; + + +import android.support.v4.app.DialogFragment; + +import com.kabouzeid.gramophone.App; +import com.squareup.leakcanary.RefWatcher; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ +public class LeakDetectDialogFragment extends DialogFragment { + @Override + public void onDestroy() { + super.onDestroy(); + if (getActivity() != null) { + RefWatcher refWatcher = App.getRefWatcher(getActivity()); + refWatcher.watch(this); + } + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/PlayingQueueDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/PlayingQueueDialog.java index 36cef572..dcb7d173 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/PlayingQueueDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/PlayingQueueDialog.java @@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Dialog; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.support.v7.app.AppCompatActivity; import android.view.View; import android.widget.AdapterView; @@ -20,7 +19,7 @@ import java.util.ArrayList; /** * @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad) */ -public class PlayingQueueDialog extends DialogFragment { +public class PlayingQueueDialog extends LeakDetectDialogFragment { public static PlayingQueueDialog create() { final ArrayList playingQueue = MusicPlayerRemote.getPlayingQueue(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/RemoveFromPlaylistDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/RemoveFromPlaylistDialog.java index 3abb7705..b792ce7d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/RemoveFromPlaylistDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/RemoveFromPlaylistDialog.java @@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Dialog; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.text.Html; import com.afollestad.materialdialogs.MaterialDialog; @@ -16,7 +15,7 @@ import java.util.ArrayList; /** * @author Karim Abou Zeid (kabouzeid) */ -public class RemoveFromPlaylistDialog extends DialogFragment { +public class RemoveFromPlaylistDialog extends LeakDetectDialogFragment { @NonNull public static RemoveFromPlaylistDialog create(PlaylistSong song) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/RenamePlaylistDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/RenamePlaylistDialog.java index b3405a24..f1e2bb05 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/RenamePlaylistDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/RenamePlaylistDialog.java @@ -3,7 +3,6 @@ package com.kabouzeid.gramophone.dialogs; import android.app.Dialog; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.text.InputType; import com.afollestad.materialdialogs.MaterialDialog; @@ -13,7 +12,7 @@ import com.kabouzeid.gramophone.util.PlaylistsUtil; /** * @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad) */ -public class RenamePlaylistDialog extends DialogFragment { +public class RenamePlaylistDialog extends LeakDetectDialogFragment { @NonNull public static RenamePlaylistDialog create(long playlistId) { diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/SleepTimerDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/SleepTimerDialog.java index 47babec4..0f601605 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/SleepTimerDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/SleepTimerDialog.java @@ -13,7 +13,6 @@ import android.os.Bundle; import android.os.CountDownTimer; import android.os.SystemClock; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.widget.FrameLayout; import android.widget.TextView; import android.widget.Toast; @@ -35,7 +34,7 @@ import butterknife.ButterKnife; /** * @author Karim Abou Zeid (kabouzeid) */ -public class SleepTimerDialog extends DialogFragment { +public class SleepTimerDialog extends LeakDetectDialogFragment { @Bind(R.id.seek_arc) SeekArc seekArc; @Bind(R.id.timer_display) diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/SongDetailDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/SongDetailDialog.java index 85b95469..25720619 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/SongDetailDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/SongDetailDialog.java @@ -5,7 +5,6 @@ import android.app.Dialog; import android.content.Context; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.text.Html; import android.text.Spanned; import android.util.Log; @@ -31,7 +30,7 @@ import java.io.IOException; /** * @author Karim Abou Zeid (kabouzeid), Aidan Follestad (afollestad) */ -public class SongDetailDialog extends DialogFragment { +public class SongDetailDialog extends LeakDetectDialogFragment { public static final String TAG = SongDetailDialog.class.getSimpleName(); @@ -44,6 +43,16 @@ public class SongDetailDialog extends DialogFragment { return dialog; } + private static Spanned makeTextWithTitle(@NonNull Context context, int titleResId, String text) { + return Html.fromHtml("" + context.getResources().getString(titleResId) + ": " + "" + text); + } + + private static String getFileSizeString(long sizeInBytes) { + long fileSizeInKB = sizeInBytes / 1024; + long fileSizeInMB = fileSizeInKB / 1024; + return fileSizeInMB + " MB"; + } + @NonNull @Override public Dialog onCreateDialog(Bundle savedInstanceState) { @@ -94,14 +103,4 @@ public class SongDetailDialog extends DialogFragment { } return dialog; } - - private static Spanned makeTextWithTitle(@NonNull Context context, int titleResId, String text) { - return Html.fromHtml("" + context.getResources().getString(titleResId) + ": " + "" + text); - } - - private static String getFileSizeString(long sizeInBytes) { - long fileSizeInKB = sizeInBytes / 1024; - long fileSizeInMB = fileSizeInKB / 1024; - return fileSizeInMB + " MB"; - } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/SongShareDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/SongShareDialog.java index 1b193c74..8c084979 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/dialogs/SongShareDialog.java +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/SongShareDialog.java @@ -4,7 +4,6 @@ import android.app.Dialog; import android.content.Intent; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.DialogFragment; import android.view.View; import com.afollestad.materialdialogs.MaterialDialog; @@ -15,7 +14,7 @@ import com.kabouzeid.gramophone.util.MusicUtil; /** * @author Karim Abou Zeid (kabouzeid) */ -public class SongShareDialog extends DialogFragment { +public class SongShareDialog extends LeakDetectDialogFragment { @NonNull public static SongShareDialog create(final Song song) { final SongShareDialog dialog = new SongShareDialog(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/interfaces/MusicStateListener.java b/app/src/main/java/com/kabouzeid/gramophone/interfaces/MusicServiceEventListener.java similarity index 63% rename from app/src/main/java/com/kabouzeid/gramophone/interfaces/MusicStateListener.java rename to app/src/main/java/com/kabouzeid/gramophone/interfaces/MusicServiceEventListener.java index 68bb5f7d..1bf88662 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/interfaces/MusicStateListener.java +++ b/app/src/main/java/com/kabouzeid/gramophone/interfaces/MusicServiceEventListener.java @@ -3,10 +3,14 @@ package com.kabouzeid.gramophone.interfaces; /** * @author Karim Abou Zeid (kabouzeid) */ -public interface MusicStateListener { +public interface MusicServiceEventListener { void onPlayingMetaChanged(); void onPlayStateChanged(); + void onRepeatModeChanged(); + + void onShuffleModeChanged(); + void onMediaStoreChanged(); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SearchActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SearchActivity.java index 809b5765..0f9cbb93 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SearchActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SearchActivity.java @@ -21,13 +21,13 @@ import android.widget.TextView; import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.adapter.SearchAdapter; -import com.kabouzeid.gramophone.ui.activities.base.AbsMusicStateActivity; +import com.kabouzeid.gramophone.ui.activities.base.AbsMusicServiceActivity; import com.kabouzeid.gramophone.util.Util; import butterknife.Bind; import butterknife.ButterKnife; -public class SearchActivity extends AbsMusicStateActivity { +public class SearchActivity extends AbsMusicServiceActivity { public static final String TAG = SearchActivity.class.getSimpleName(); @Bind(R.id.recycler_view) diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java index b1ea846b..d48d1d6d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/SettingsActivity.java @@ -104,7 +104,7 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia @Override public boolean onPreferenceClick(@NonNull Preference preference) { new ColorChooserDialog().show( - getActivity(), + ((SettingsActivity) getActivity()), preference.getTitleRes(), ((SettingsActivity) getActivity()).getThemeColorPrimary()); return true; @@ -117,7 +117,7 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia @Override public boolean onPreferenceClick(@NonNull Preference preference) { new ColorChooserDialog().show( - getActivity(), + ((SettingsActivity) getActivity()), preference.getTitleRes(), ((SettingsActivity) getActivity()).getThemeColorAccent()); return true; @@ -168,6 +168,103 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia .getString(preference.getKey(), "")); } + @Override + public void onCreate(Bundle savedInstanceState) { + super.onCreate(savedInstanceState); + + addPreferencesFromResource(R.xml.pref_general); + addPreferencesFromResource(R.xml.pref_colors); + addPreferencesFromResource(R.xml.pref_now_playing_screen); + addPreferencesFromResource(R.xml.pref_images); + addPreferencesFromResource(R.xml.pref_lockscreen); + addPreferencesFromResource(R.xml.pref_audio); + + final Preference defaultStartPage = findPreference("default_start_page"); + setSummary(defaultStartPage); + defaultStartPage.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, @NonNull Object o) { + setSummary(defaultStartPage, o); + return true; + } + }); + + final Preference generalTheme = findPreference("general_theme"); + setSummary(generalTheme); + generalTheme.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, @NonNull Object o) { + setSummary(generalTheme, o); + PreferenceUtil.getInstance(getActivity()).setGeneralTheme(getActivity(), (String) o); + ((SettingsActivity) getActivity()).recreateIfThemeChanged(); + return true; + } + }); + + ColorChooserPreference primaryColor = (ColorChooserPreference) findPreference("primary_color"); + primaryColor.setColor(PreferenceUtil.getInstance(getActivity()).getThemeColorPrimary(getActivity())); + primaryColor.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(@NonNull Preference preference) { + new ColorChooserDialog().show( + ((SettingsActivity) getActivity()), + preference.getTitleRes(), + ((SettingsActivity) getActivity()).getThemeColorPrimary()); + return true; + } + }); + + ColorChooserPreference accentColor = (ColorChooserPreference) findPreference("accent_color"); + accentColor.setColor(PreferenceUtil.getInstance(getActivity()).getThemeColorAccent(getActivity())); + accentColor.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(@NonNull Preference preference) { + new ColorChooserDialog().show( + ((SettingsActivity) getActivity()), + preference.getTitleRes(), + ((SettingsActivity) getActivity()).getThemeColorAccent()); + return true; + } + }); + + Preference colorNavBar = findPreference("should_color_navigation_bar"); + if (Build.VERSION.SDK_INT < Build.VERSION_CODES.LOLLIPOP) { + colorNavBar.setEnabled(false); + colorNavBar.setSummary(R.string.pref_only_lollipop); + } else { + colorNavBar.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + PreferenceUtil.getInstance(getActivity()).setColoredNavigationBar((boolean) newValue); + ((SettingsActivity) getActivity()).recreateIfThemeChanged(); + return true; + } + }); + } + + Preference ignoreMediaStoreArtwork = findPreference("ignore_media_store_artwork"); + ignoreMediaStoreArtwork.setOnPreferenceChangeListener(new Preference.OnPreferenceChangeListener() { + @Override + public boolean onPreferenceChange(Preference preference, Object newValue) { + ImageLoader.getInstance().clearMemoryCache(); + return true; + } + }); + + Preference equalizer = findPreference("equalizer"); + if (!hasEqualizer()) { + equalizer.setEnabled(false); + equalizer.setSummary(getResources().getString(R.string.no_equalizer)); + } + equalizer.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() { + @Override + public boolean onPreferenceClick(Preference preference) { + NavigationUtil.openEqualizer(getActivity()); + return true; + } + }); + } + private static void setSummary(Preference preference, @NonNull Object value) { String stringValue = value.toString(); diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicStateActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicServiceActivity.java similarity index 72% rename from app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicStateActivity.java rename to app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicServiceActivity.java index c980d4da..92972e40 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicStateActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsMusicServiceActivity.java @@ -11,7 +11,7 @@ import android.os.IBinder; import android.support.annotation.NonNull; import com.kabouzeid.gramophone.helper.MusicPlayerRemote; -import com.kabouzeid.gramophone.interfaces.MusicStateListener; +import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener; import com.kabouzeid.gramophone.service.MusicService; import java.lang.ref.WeakReference; @@ -20,10 +20,10 @@ import java.util.ArrayList; /** * @author Karim Abou Zeid (kabouzeid) */ -public abstract class AbsMusicStateActivity extends AbsBaseActivity implements ServiceConnection, MusicStateListener { - public static final String TAG = AbsMusicStateActivity.class.getSimpleName(); +public abstract class AbsMusicServiceActivity extends AbsBaseActivity implements ServiceConnection, MusicServiceEventListener { + public static final String TAG = AbsMusicServiceActivity.class.getSimpleName(); - private final ArrayList mMusicStateListener = new ArrayList<>(); + private final ArrayList mMusicServiceEventListener = new ArrayList<>(); private MusicPlayerRemote.ServiceToken serviceToken; private MusicStateReceiver musicStateReceiver; @@ -71,21 +71,21 @@ public abstract class AbsMusicStateActivity extends AbsBaseActivity implements S } } - public void addMusicStateListenerListener(final MusicStateListener listener) { + public void addMusicStateListenerListener(final MusicServiceEventListener listener) { if (listener != null) { - mMusicStateListener.add(listener); + mMusicServiceEventListener.add(listener); } } - public void removeMusicStateListenerListener(final MusicStateListener listener) { + public void removeMusicStateListenerListener(final MusicServiceEventListener listener) { if (listener != null) { - mMusicStateListener.remove(listener); + mMusicServiceEventListener.remove(listener); } } @Override public void onPlayingMetaChanged() { - for (MusicStateListener listener : mMusicStateListener) { + for (MusicServiceEventListener listener : mMusicServiceEventListener) { if (listener != null) { listener.onPlayingMetaChanged(); } @@ -94,7 +94,7 @@ public abstract class AbsMusicStateActivity extends AbsBaseActivity implements S @Override public void onPlayStateChanged() { - for (MusicStateListener listener : mMusicStateListener) { + for (MusicServiceEventListener listener : mMusicServiceEventListener) { if (listener != null) { listener.onPlayStateChanged(); } @@ -103,33 +103,43 @@ public abstract class AbsMusicStateActivity extends AbsBaseActivity implements S @Override public void onMediaStoreChanged() { - for (MusicStateListener listener : mMusicStateListener) { + for (MusicServiceEventListener listener : mMusicServiceEventListener) { if (listener != null) { listener.onMediaStoreChanged(); } } } + @Override public void onRepeatModeChanged() { - + for (MusicServiceEventListener listener : mMusicServiceEventListener) { + if (listener != null) { + listener.onRepeatModeChanged(); + } + } } + @Override public void onShuffleModeChanged() { - + for (MusicServiceEventListener listener : mMusicServiceEventListener) { + if (listener != null) { + listener.onShuffleModeChanged(); + } + } } private static final class MusicStateReceiver extends BroadcastReceiver { - private final WeakReference reference; + private final WeakReference reference; - public MusicStateReceiver(final AbsMusicStateActivity activity) { + public MusicStateReceiver(final AbsMusicServiceActivity activity) { reference = new WeakReference<>(activity); } @Override public void onReceive(final Context context, @NonNull final Intent intent) { final String action = intent.getAction(); - AbsMusicStateActivity activity = reference.get(); + AbsMusicServiceActivity activity = reference.get(); if (activity != null) { switch (action) { case MusicService.META_CHANGED: diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java index 419bbee1..c4118e46 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/base/AbsSlidingMusicPanelActivity.java @@ -62,17 +62,16 @@ import butterknife.ButterKnife; /** * @author Karim Abou Zeid (kabouzeid) - *

+ *

* Do not use {@link #setContentView(int)} but wrap your layout with * {@link #wrapSlidingMusicPanelAndFab(int)} first and then return it in {@link #createContentView()} */ -public abstract class AbsSlidingMusicPanelActivity extends AbsMusicStateActivity implements SlidingUpPanelLayout.PanelSlideListener { +public abstract class AbsSlidingMusicPanelActivity extends AbsMusicServiceActivity implements SlidingUpPanelLayout.PanelSlideListener { public static final String TAG = AbsSlidingMusicPanelActivity.class.getSimpleName(); private static final int FAB_CIRCULAR_REVEAL_ANIMATION_TIME = 1000; private static final long DEFAULT_PROGRESS_VIEW_REFRESH_INTERVAL = 500; private static final int CMD_REFRESH_PROGRESS_VIEWS = 1; - private static final String PANEL_EXPANDED_KEY = "panel_state"; @Bind(R.id.play_pause_fab) FloatingActionButton playPauseFab; diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java index 4c5b4329..f0adf4af 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/tageditor/AbsTagEditorActivity.java @@ -26,6 +26,7 @@ import com.afollestad.materialdialogs.ThemeSingleton; import com.afollestad.materialdialogs.util.DialogUtils; import com.github.ksoichiro.android.observablescrollview.ObservableScrollView; import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.misc.LagTracker; import com.kabouzeid.gramophone.misc.SimpleObservableScrollViewCallbacks; import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity; import com.kabouzeid.gramophone.util.MusicUtil; @@ -57,18 +58,10 @@ import butterknife.ButterKnife; */ public abstract class AbsTagEditorActivity extends AbsBaseActivity { - private static final String TAG = AbsTagEditorActivity.class.getSimpleName(); - - private static final int REQUEST_CODE_SELECT_IMAGE = 1337; - public static final String EXTRA_ID = "extra_id"; public static final String EXTRA_PALETTE = "extra_palette"; - - private int id; - private int headerVariableSpace; - private int paletteColorPrimary; - private boolean isInNoImageMode; - + private static final String TAG = AbsTagEditorActivity.class.getSimpleName(); + private static final int REQUEST_CODE_SELECT_IMAGE = 1337; @Bind(R.id.play_pause_fab) FloatingActionButton fab; @Bind(R.id.observableScrollView) @@ -79,13 +72,32 @@ public abstract class AbsTagEditorActivity extends AbsBaseActivity { ImageView image; @Bind(R.id.header) LinearLayout header; - + private int id; + private int headerVariableSpace; + private int paletteColorPrimary; + private boolean isInNoImageMode; + private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() { + @Override + public void onScrollChanged(int scrollY, boolean b, boolean b2) { + float alpha; + if (!isInNoImageMode) { + alpha = 1 - (float) Math.max(0, headerVariableSpace - scrollY) / headerVariableSpace; + } else { + header.setTranslationY(scrollY); + alpha = 1; + } + ViewUtil.setBackgroundAlpha(toolbar, alpha, paletteColorPrimary); + image.setTranslationY(scrollY / 2); + } + }; private List songPaths; @Override protected void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); + LagTracker.get().start("setContentView"); setContentView(getContentViewLayout()); + LagTracker.get().end("setContentView"); ButterKnife.bind(this); getIntentExtras(); @@ -116,21 +128,6 @@ public abstract class AbsTagEditorActivity extends AbsBaseActivity { observableScrollView.setScrollViewCallbacks(observableScrollViewCallbacks); } - private final SimpleObservableScrollViewCallbacks observableScrollViewCallbacks = new SimpleObservableScrollViewCallbacks() { - @Override - public void onScrollChanged(int scrollY, boolean b, boolean b2) { - float alpha; - if (!isInNoImageMode) { - alpha = 1 - (float) Math.max(0, headerVariableSpace - scrollY) / headerVariableSpace; - } else { - header.setTranslationY(scrollY); - alpha = 1; - } - ViewUtil.setBackgroundAlpha(toolbar, alpha, paletteColorPrimary); - image.setTranslationY(scrollY / 2); - } - }; - private void setUpImageView() { loadCurrentImage(); final CharSequence[] items = new CharSequence[]{ diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/LeakDetectFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/LeakDetectFragment.java new file mode 100644 index 00000000..f010fe98 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/LeakDetectFragment.java @@ -0,0 +1,20 @@ +package com.kabouzeid.gramophone.ui.fragments; + +import android.support.v4.app.Fragment; + +import com.kabouzeid.gramophone.App; +import com.squareup.leakcanary.RefWatcher; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ +public class LeakDetectFragment extends Fragment { + @Override + public void onDestroy() { + super.onDestroy(); + if (getActivity() != null) { + RefWatcher refWatcher = App.getRefWatcher(getActivity()); + refWatcher.watch(this); + } + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivityfragments/AbsMainActivityFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivityfragments/AbsMainActivityFragment.java index e046ad27..a7f81aae 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivityfragments/AbsMainActivityFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivityfragments/AbsMainActivityFragment.java @@ -2,15 +2,15 @@ package com.kabouzeid.gramophone.ui.fragments.mainactivityfragments; import android.os.Bundle; import android.support.annotation.NonNull; -import android.support.v4.app.Fragment; import com.kabouzeid.gramophone.interfaces.KabViewsDisableAble; import com.kabouzeid.gramophone.ui.activities.MainActivity; +import com.kabouzeid.gramophone.ui.fragments.LeakDetectFragment; /** * @author Karim Abou Zeid (kabouzeid) */ -public abstract class AbsMainActivityFragment extends Fragment implements KabViewsDisableAble { +public abstract class AbsMainActivityFragment extends LeakDetectFragment implements KabViewsDisableAble { private boolean areViewsEnabled; @NonNull diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivityfragments/AbsMainActivityRecyclerViewFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivityfragments/AbsMainActivityRecyclerViewFragment.java index d7e79082..2828b014 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivityfragments/AbsMainActivityRecyclerViewFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivityfragments/AbsMainActivityRecyclerViewFragment.java @@ -14,7 +14,7 @@ import android.view.ViewGroup; import android.widget.TextView; import com.kabouzeid.gramophone.R; -import com.kabouzeid.gramophone.interfaces.MusicStateListener; +import com.kabouzeid.gramophone.interfaces.MusicServiceEventListener; import com.kabouzeid.gramophone.views.FastScroller; import butterknife.Bind; @@ -23,7 +23,7 @@ import butterknife.ButterKnife; /** * @author Karim Abou Zeid (kabouzeid) */ -public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivityFragment implements OnOffsetChangedListener, MusicStateListener { +public abstract class AbsMainActivityRecyclerViewFragment extends AbsMainActivityFragment implements OnOffsetChangedListener, MusicServiceEventListener { public static final String TAG = AbsMainActivityRecyclerViewFragment.class.getSimpleName(); @@ -119,6 +119,16 @@ public abstract class AbsMainActivityRecyclerViewFragment