diff --git a/app/src/main/java/com/kabouzeid/gramophone/App.java b/app/src/main/java/com/kabouzeid/gramophone/App.java index df9efc08..6e241d17 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/App.java +++ b/app/src/main/java/com/kabouzeid/gramophone/App.java @@ -2,7 +2,6 @@ package com.kabouzeid.gramophone; import android.app.Application; import android.os.Build; -import android.widget.Toast; import com.anjlab.android.iab.v3.BillingProcessor; import com.anjlab.android.iab.v3.TransactionDetails; @@ -21,7 +20,7 @@ public class App extends Application { public static final String GOOGLE_PLAY_LICENSE_KEY = "MIIBIjANBgkqhkiG9w0BAQEFAAOCAQ8AMIIBCgKCAQEAjMeADN5Ffnt/ml5SYxNPCn8kGcOYGpHEfNSCts99vVxqmCn6C01E94c17j7rUK2aeHur5uxphZylzopPlQ8P8l1fqty0GPUNRSo18FCJzfGH8HZAwZYOcnRFPaXdaq3InyFJhBiODh2oeAcVK/idH6QraQ4r9HIlzigAg6lgwzxl2wJKDh7X/GMdDntCyzDh8xDQ0wIawFgvgojHwqh2Ci8Gnq6EYRwPA9yHiIIksT8Q30QyM5ewl5QcnWepsls7enNqeHarhpmSibRUDgCsxHoOpny7SyuvZvUI3wuLckDR0ds9hrt614scHHqDOBp/qWCZiAgOPVAEQcURbV09qQIDAQAB"; public static final String PRO_VERSION_PRODUCT_ID = "pro_version"; - public static App app; + private static App app; private BillingProcessor billingProcessor; @@ -49,7 +48,7 @@ public class App extends Application { @Override public void onPurchaseHistoryRestored() { - Toast.makeText(App.this, R.string.restored_previous_purchase_please_restart, Toast.LENGTH_LONG).show(); +// Toast.makeText(App.this, R.string.restored_previous_purchase_please_restart, Toast.LENGTH_LONG).show(); } @Override diff --git a/app/src/main/java/com/kabouzeid/gramophone/dialogs/BlacklistFolderChooserDialog.java b/app/src/main/java/com/kabouzeid/gramophone/dialogs/BlacklistFolderChooserDialog.java new file mode 100644 index 00000000..c32b236c --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/dialogs/BlacklistFolderChooserDialog.java @@ -0,0 +1,176 @@ +package com.kabouzeid.gramophone.dialogs; + +import android.Manifest; +import android.app.Dialog; +import android.content.pm.PackageManager; +import android.os.Build; +import android.os.Bundle; +import android.os.Environment; +import android.support.annotation.NonNull; +import android.support.v4.app.ActivityCompat; +import android.support.v4.app.DialogFragment; +import android.view.View; + +import com.afollestad.materialdialogs.DialogAction; +import com.afollestad.materialdialogs.MaterialDialog; +import com.kabouzeid.gramophone.R; + +import java.io.File; +import java.util.ArrayList; +import java.util.Collections; +import java.util.Comparator; +import java.util.List; + +/** + * @author Aidan Follestad (afollestad), modified by Karim Abou Zeid + */ +public class BlacklistFolderChooserDialog extends DialogFragment implements MaterialDialog.ListCallback { + + private File parentFolder; + private File[] parentContents; + private boolean canGoUp = false; + + private FolderCallback callback; + + String initialPath = Environment.getExternalStorageDirectory().getAbsolutePath(); + + private String[] getContentsArray() { + if (parentContents == null) { + if (canGoUp) { + return new String[]{".."}; + } + return new String[]{}; + } + String[] results = new String[parentContents.length + (canGoUp ? 1 : 0)]; + if (canGoUp) { + results[0] = ".."; + } + for (int i = 0; i < parentContents.length; i++) { + results[canGoUp ? i + 1 : i] = parentContents[i].getName(); + } + return results; + } + + private File[] listFiles() { + File[] contents = parentFolder.listFiles(); + List results = new ArrayList<>(); + if (contents != null) { + for (File fi : contents) { + if (fi.isDirectory()) { + results.add(fi); + } + } + Collections.sort(results, new FolderSorter()); + return results.toArray(new File[results.size()]); + } + return null; + } + + public static BlacklistFolderChooserDialog create() { + return new BlacklistFolderChooserDialog(); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M + && ActivityCompat.checkSelfPermission( + getActivity(), Manifest.permission.READ_EXTERNAL_STORAGE) + != PackageManager.PERMISSION_GRANTED) { + return new MaterialDialog.Builder(getActivity()) + .title(R.string.md_error_label) + .content(R.string.md_storage_perm_error) + .positiveText(android.R.string.ok) + .build(); + } + if (savedInstanceState == null) { + savedInstanceState = new Bundle(); + } + if (!savedInstanceState.containsKey("current_path")) { + savedInstanceState.putString("current_path", initialPath); + } + parentFolder = new File(savedInstanceState.getString("current_path", File.pathSeparator)); + checkIfCanGoUp(); + parentContents = listFiles(); + MaterialDialog.Builder builder = + new MaterialDialog.Builder(getActivity()) + .title(parentFolder.getAbsolutePath()) + .items((CharSequence[]) getContentsArray()) + .itemsCallback(this) + .autoDismiss(false) + .onPositive(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog dialog, @NonNull DialogAction which) { + dismiss(); + callback.onFolderSelection(BlacklistFolderChooserDialog.this, parentFolder); + } + }) + .onNegative(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) { + dismiss(); + } + }) + .positiveText(R.string.add_action) + .negativeText(android.R.string.cancel); + if (File.pathSeparator.equals(initialPath)) { + canGoUp = false; + } + return builder.build(); + } + + @Override + public void onSelection(MaterialDialog materialDialog, View view, int i, CharSequence s) { + if (canGoUp && i == 0) { + parentFolder = parentFolder.getParentFile(); + if (parentFolder.getAbsolutePath().equals("/storage/emulated")) { + parentFolder = parentFolder.getParentFile(); + } + canGoUp = parentFolder.getParent() != null; + } else { + parentFolder = parentContents[canGoUp ? i - 1 : i]; + canGoUp = true; + if (parentFolder.getAbsolutePath().equals("/storage/emulated")) { + parentFolder = Environment.getExternalStorageDirectory(); + } + } + reload(); + } + + private void checkIfCanGoUp() { + try { + canGoUp = parentFolder.getPath().split(File.pathSeparator).length > 1; + } catch (IndexOutOfBoundsException e) { + canGoUp = false; + } + } + + private void reload() { + parentContents = listFiles(); + MaterialDialog dialog = (MaterialDialog) getDialog(); + dialog.setTitle(parentFolder.getAbsolutePath()); + dialog.setItems((CharSequence[]) getContentsArray()); + } + + @Override + public void onSaveInstanceState(Bundle outState) { + super.onSaveInstanceState(outState); + outState.putString("current_path", parentFolder.getAbsolutePath()); + } + + public void setCallback(FolderCallback callback) { + this.callback = callback; + } + + public interface FolderCallback { + void onFolderSelection(@NonNull BlacklistFolderChooserDialog dialog, @NonNull File folder); + } + + private static class FolderSorter implements Comparator { + + @Override + public int compare(File lhs, File rhs) { + return lhs.getName().compareTo(rhs.getName()); + } + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/loader/SongLoader.java b/app/src/main/java/com/kabouzeid/gramophone/loader/SongLoader.java index 4c3c65bc..fdce1b22 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/loader/SongLoader.java +++ b/app/src/main/java/com/kabouzeid/gramophone/loader/SongLoader.java @@ -9,10 +9,13 @@ import android.support.annotation.NonNull; import android.support.annotation.Nullable; import com.kabouzeid.gramophone.model.Song; +import com.kabouzeid.gramophone.provider.BlacklistStore; import com.kabouzeid.gramophone.util.PreferenceUtil; import java.util.ArrayList; +import hugo.weaving.DebugLog; + /** * @author Karim Abou Zeid (kabouzeid) */ @@ -87,11 +90,20 @@ public class SongLoader { return makeSongCursor(context, selection, selectionValues, PreferenceUtil.getInstance(context).getSongSortOrder()); } + @DebugLog @Nullable - public static Cursor makeSongCursor(@NonNull final Context context, @Nullable final String selection, final String[] selectionValues, final String sortOrder) { - String baseSelection = BASE_SELECTION; + public static Cursor makeSongCursor(@NonNull final Context context, @Nullable String selection, String[] selectionValues, final String sortOrder) { if (selection != null && !selection.trim().equals("")) { - baseSelection += " AND " + selection; + selection = BASE_SELECTION + " AND " + selection; + } else { + selection = BASE_SELECTION; + } + + // Blacklist + ArrayList paths = BlacklistStore.getInstance(context).getPaths(); + if (!paths.isEmpty()) { + selection = generateBlacklistSelection(selection, paths.size()); + selectionValues = addBlacklistSelectionValues(selectionValues, paths); } try { @@ -109,9 +121,30 @@ public class SongLoader { AudioColumns.ARTIST_ID,// 9 AudioColumns.ARTIST,// 10 - }, baseSelection, selectionValues, sortOrder); + }, selection, selectionValues, sortOrder); } catch (SecurityException e) { return null; } } + + @DebugLog + private static String generateBlacklistSelection(String selection, int pathCount) { + String newSelection = selection != null && !selection.trim().equals("") ? selection + " AND " : ""; + newSelection += AudioColumns.DATA + " NOT LIKE ?"; + for (int i = 0; i < pathCount - 1; i++) { + newSelection += " AND " + AudioColumns.DATA + " NOT LIKE ?"; + } + return newSelection; + } + + @DebugLog + private static String[] addBlacklistSelectionValues(String[] selectionValues, ArrayList paths) { + if (selectionValues == null) selectionValues = new String[0]; + String[] newSelectionValues = new String[selectionValues.length + paths.size()]; + System.arraycopy(selectionValues, 0, newSelectionValues, 0, selectionValues.length); + for (int i = selectionValues.length; i < newSelectionValues.length; i++) { + newSelectionValues[i] = paths.get(i - selectionValues.length) + "%"; + } + return newSelectionValues; + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/preferences/BlacklistPreference.java b/app/src/main/java/com/kabouzeid/gramophone/preferences/BlacklistPreference.java new file mode 100644 index 00000000..777d85ba --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/preferences/BlacklistPreference.java @@ -0,0 +1,27 @@ +package com.kabouzeid.gramophone.preferences; + +import android.content.Context; +import android.util.AttributeSet; + +import com.kabouzeid.appthemehelper.common.prefs.supportv7.ATEDialogPreference; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ +public class BlacklistPreference extends ATEDialogPreference { + public BlacklistPreference(Context context) { + super(context); + } + + public BlacklistPreference(Context context, AttributeSet attrs) { + super(context, attrs); + } + + public BlacklistPreference(Context context, AttributeSet attrs, int defStyleAttr) { + super(context, attrs, defStyleAttr); + } + + public BlacklistPreference(Context context, AttributeSet attrs, int defStyleAttr, int defStyleRes) { + super(context, attrs, defStyleAttr, defStyleRes); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/preferences/BlacklistPreferenceDialog.java b/app/src/main/java/com/kabouzeid/gramophone/preferences/BlacklistPreferenceDialog.java new file mode 100644 index 00000000..ffa2d287 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/preferences/BlacklistPreferenceDialog.java @@ -0,0 +1,116 @@ +package com.kabouzeid.gramophone.preferences; + +import android.app.Dialog; +import android.os.Bundle; +import android.support.annotation.NonNull; +import android.support.v4.app.DialogFragment; +import android.text.Html; +import android.view.View; + +import com.afollestad.materialdialogs.DialogAction; +import com.afollestad.materialdialogs.MaterialDialog; +import com.kabouzeid.gramophone.R; +import com.kabouzeid.gramophone.dialogs.BlacklistFolderChooserDialog; +import com.kabouzeid.gramophone.provider.BlacklistStore; + +import java.io.File; +import java.util.ArrayList; + +/** + * @author Karim Abou Zeid (kabouzeid) + */ +public class BlacklistPreferenceDialog extends DialogFragment implements BlacklistFolderChooserDialog.FolderCallback { + public static final String TAG = BlacklistPreferenceDialog.class.getSimpleName(); + + private ArrayList paths; + + public static BlacklistPreferenceDialog newInstance() { + return new BlacklistPreferenceDialog(); + } + + @NonNull + @Override + public Dialog onCreateDialog(Bundle savedInstanceState) { + BlacklistFolderChooserDialog blacklistFolderChooserDialog = (BlacklistFolderChooserDialog) getChildFragmentManager().findFragmentByTag("FOLDER_CHOOSER"); + if (blacklistFolderChooserDialog != null) { + blacklistFolderChooserDialog.setCallback(this); + } + + refreshBlacklistData(); + return new MaterialDialog.Builder(getContext()) + .title(R.string.blacklist) + .positiveText(android.R.string.ok) + .neutralText(R.string.clear_action) + .negativeText(R.string.add_action) + .items(paths) + .autoDismiss(false) + .itemsCallback(new MaterialDialog.ListCallback() { + @Override + public void onSelection(MaterialDialog materialDialog, View view, int i, final CharSequence charSequence) { + new MaterialDialog.Builder(getContext()) + .title(R.string.remove_from_blacklist) + .content(Html.fromHtml(getString(R.string.do_you_want_to_remove_from_the_blacklist, charSequence))) + .positiveText(R.string.remove_action) + .negativeText(android.R.string.cancel) + .onPositive(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) { + BlacklistStore.getInstance(getContext()).removePath(new File(charSequence.toString())); + refreshBlacklistData(); + } + }).show(); + } + }) + // clear + .onNeutral(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) { + new MaterialDialog.Builder(getContext()) + .title(R.string.clear_blacklist) + .content(R.string.do_you_want_to_clear_the_blacklist) + .positiveText(R.string.clear_action) + .negativeText(android.R.string.cancel) + .onPositive(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) { + BlacklistStore.getInstance(getContext()).clear(); + refreshBlacklistData(); + } + }).show(); + } + }) + // add + .onNegative(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) { + BlacklistFolderChooserDialog dialog = BlacklistFolderChooserDialog.create(); + dialog.setCallback(BlacklistPreferenceDialog.this); + dialog.show(getChildFragmentManager(), "FOLDER_CHOOSER"); + } + }) + .onPositive(new MaterialDialog.SingleButtonCallback() { + @Override + public void onClick(@NonNull MaterialDialog materialDialog, @NonNull DialogAction dialogAction) { + dismiss(); + } + }) + .build(); + } + + private void refreshBlacklistData() { + paths = BlacklistStore.getInstance(getContext()).getPaths(); + + MaterialDialog dialog = (MaterialDialog) getDialog(); + if (dialog != null) { + String[] pathArray = new String[paths.size()]; + pathArray = paths.toArray(pathArray); + dialog.setItems((CharSequence[]) pathArray); + } + } + + @Override + public void onFolderSelection(@NonNull BlacklistFolderChooserDialog folderChooserDialog, @NonNull File file) { + BlacklistStore.getInstance(getContext()).addPath(file); + refreshBlacklistData(); + } +} \ No newline at end of file diff --git a/app/src/main/java/com/kabouzeid/gramophone/provider/BlacklistStore.java b/app/src/main/java/com/kabouzeid/gramophone/provider/BlacklistStore.java new file mode 100644 index 00000000..7deaee67 --- /dev/null +++ b/app/src/main/java/com/kabouzeid/gramophone/provider/BlacklistStore.java @@ -0,0 +1,158 @@ +package com.kabouzeid.gramophone.provider; + +import android.content.ContentValues; +import android.content.Context; +import android.content.Intent; +import android.database.Cursor; +import android.database.sqlite.SQLiteDatabase; +import android.database.sqlite.SQLiteOpenHelper; +import android.os.Environment; +import android.support.annotation.NonNull; + +import com.kabouzeid.gramophone.service.MusicService; +import com.kabouzeid.gramophone.util.FileUtil; +import com.kabouzeid.gramophone.util.PreferenceUtil; + +import java.io.File; +import java.util.ArrayList; + +import hugo.weaving.DebugLog; + +public class BlacklistStore extends SQLiteOpenHelper { + private static BlacklistStore sInstance = null; + public static final String DATABASE_NAME = "blacklist.db"; + private static final int VERSION = 1; + private Context context; + + public BlacklistStore(final Context context) { + super(context, DATABASE_NAME, null, VERSION); + this.context = context; + } + + @Override + public void onCreate(@NonNull final SQLiteDatabase db) { + db.execSQL("CREATE TABLE IF NOT EXISTS " + BlacklistStoreColumns.NAME + " (" + + BlacklistStoreColumns.PATH + " STRING NOT NULL);"); + } + + @Override + public void onUpgrade(@NonNull final SQLiteDatabase db, final int oldVersion, final int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + BlacklistStoreColumns.NAME); + onCreate(db); + } + + @Override + public void onDowngrade(@NonNull SQLiteDatabase db, int oldVersion, int newVersion) { + db.execSQL("DROP TABLE IF EXISTS " + BlacklistStoreColumns.NAME); + onCreate(db); + } + + @NonNull + public static synchronized BlacklistStore getInstance(@NonNull final Context context) { + if (sInstance == null) { + sInstance = new BlacklistStore(context.getApplicationContext()); + if (!PreferenceUtil.getInstance(context).initializedBlacklist()) { + // blacklisted by default + sInstance.addPathImpl(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_ALARMS)); + sInstance.addPathImpl(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_NOTIFICATIONS)); + sInstance.addPathImpl(Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_RINGTONES)); + + PreferenceUtil.getInstance(context).setInitializedBlacklist(); + } + } + return sInstance; + } + + public void addPath(File file) { + addPathImpl(file); + notifyMediaStoreChanged(); + } + + private void addPathImpl(File file) { + if (file == null || contains(file)) { + return; + } + String path = FileUtil.safeGetCanonicalPath(file); + + final SQLiteDatabase database = getWritableDatabase(); + database.beginTransaction(); + + try { + // add the entry + final ContentValues values = new ContentValues(1); + values.put(BlacklistStoreColumns.PATH, path); + database.insert(BlacklistStoreColumns.NAME, null, values); + + database.setTransactionSuccessful(); + } finally { + database.endTransaction(); + } + } + + public boolean contains(File file) { + if (file == null) { + return false; + } + String path = FileUtil.safeGetCanonicalPath(file); + + final SQLiteDatabase database = getReadableDatabase(); + Cursor cursor = database.query(BlacklistStoreColumns.NAME, + new String[]{BlacklistStoreColumns.PATH}, + BlacklistStoreColumns.PATH + "=?", + new String[]{path}, + null, null, null, null); + + boolean containsPath = cursor != null && cursor.moveToFirst(); + if (cursor != null) { + cursor.close(); + } + return containsPath; + } + + public void removePath(File file) { + final SQLiteDatabase database = getWritableDatabase(); + String path = FileUtil.safeGetCanonicalPath(file); + + database.delete(BlacklistStoreColumns.NAME, + BlacklistStoreColumns.PATH + "=?", + new String[]{path}); + + notifyMediaStoreChanged(); + } + + public void clear() { + final SQLiteDatabase database = getWritableDatabase(); + database.delete(BlacklistStoreColumns.NAME, null, null); + + notifyMediaStoreChanged(); + } + + private void notifyMediaStoreChanged() { + context.sendBroadcast(new Intent(MusicService.MEDIA_STORE_CHANGED)); + } + + @NonNull + @DebugLog + public ArrayList getPaths() { + Cursor cursor = getReadableDatabase().query(BlacklistStoreColumns.NAME, + new String[]{BlacklistStoreColumns.PATH}, + null, null, null, null, null); + + ArrayList paths = new ArrayList<>(); + if (cursor != null && cursor.moveToFirst()) { + do { + paths.add(cursor.getString(0)); + } while (cursor.moveToNext()); + } + + if (cursor != null) + cursor.close(); + return paths; + } + + public interface BlacklistStoreColumns { + String NAME = "blacklist"; + + String PATH = "path"; + } +} diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java index 0c1e4f43..5b4d7742 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/activities/MainActivity.java @@ -146,11 +146,10 @@ public class MainActivity extends AbsSlidingMusicPanelActivity { if (!hasPermissions()) { requestPermissions(); } + checkSetUpPro(); // good chance that pro version check was delayed on first start } else if (requestCode == PURCHASE_REQUEST) { if (resultCode == RESULT_OK) { - if (App.isProVersion()) { - setUpPro(); - } + checkSetUpPro(); } } } @@ -174,9 +173,7 @@ public class MainActivity extends AbsSlidingMusicPanelActivity { NavigationViewUtil.setItemIconColors(navigationView, ATHUtil.resolveColor(this, R.attr.iconColor, ThemeStore.textColorSecondary(this)), accentColor); NavigationViewUtil.setItemTextColors(navigationView, ThemeStore.textColorPrimary(this), accentColor); - if (App.isProVersion()) { - setUpPro(); - } + checkSetUpPro(); navigationView.setNavigationItemSelectedListener(new NavigationView.OnNavigationItemSelectedListener() { @Override public boolean onNavigationItemSelected(@NonNull MenuItem menuItem) { @@ -228,6 +225,12 @@ public class MainActivity extends AbsSlidingMusicPanelActivity { }); } + private void checkSetUpPro() { + if (App.isProVersion()) { + setUpPro(); + } + } + private void setUpPro() { navigationView.getMenu().removeGroup(R.id.navigation_drawer_menu_category_buy_pro); } 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 95781a17..843140f3 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 @@ -29,6 +29,8 @@ import com.kabouzeid.gramophone.App; import com.kabouzeid.gramophone.R; import com.kabouzeid.gramophone.appshortcuts.DynamicShortcutManager; import com.kabouzeid.gramophone.misc.NonProAllowedColors; +import com.kabouzeid.gramophone.preferences.BlacklistPreference; +import com.kabouzeid.gramophone.preferences.BlacklistPreferenceDialog; import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreference; import com.kabouzeid.gramophone.preferences.NowPlayingScreenPreferenceDialog; import com.kabouzeid.gramophone.ui.activities.base.AbsBaseActivity; @@ -155,6 +157,7 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia addPreferencesFromResource(R.xml.pref_lockscreen); addPreferencesFromResource(R.xml.pref_audio); addPreferencesFromResource(R.xml.pref_playlists); + addPreferencesFromResource(R.xml.pref_blacklist); } @Nullable @@ -162,6 +165,8 @@ public class SettingsActivity extends AbsBaseActivity implements ColorChooserDia public DialogFragment onCreatePreferenceDialog(Preference preference) { if (preference instanceof NowPlayingScreenPreference) { return NowPlayingScreenPreferenceDialog.newInstance(); + } else if (preference instanceof BlacklistPreference) { + return BlacklistPreferenceDialog.newInstance(); } return super.onCreatePreferenceDialog(preference); } diff --git a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/folders/FoldersFragment.java b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/folders/FoldersFragment.java index e516dbc6..ca55831d 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/folders/FoldersFragment.java +++ b/app/src/main/java/com/kabouzeid/gramophone/ui/fragments/mainactivity/folders/FoldersFragment.java @@ -455,8 +455,8 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi @Override public boolean accept(File file) { return !file.isHidden() && (file.isDirectory() || - FileUtil.fileIsMimeType(file, "audio/*", MimeTypeMap.getSingleton()) || - FileUtil.fileIsMimeType(file, "application/ogg", MimeTypeMap.getSingleton())); + FileUtil.fileIsMimeType(file, "audio/*", MimeTypeMap.getSingleton()) || + FileUtil.fileIsMimeType(file, "application/ogg", MimeTypeMap.getSingleton())); } }; @@ -658,12 +658,7 @@ public class FoldersFragment extends AbsMainActivityFragment implements MainActi paths = new String[files.size()]; for (int i = 0; i < files.size(); i++) { File f = files.get(i); - try { - paths[i] = f.getCanonicalPath(); // canonical path is important here because we want to compare the path with the media store entry later - } catch (IOException e) { - e.printStackTrace(); - paths[i] = f.getPath(); - } + paths[i] = FileUtil.safeGetCanonicalPath(f); if (isCancelled() || checkCallbackReference() == null) return paths; } diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/FileUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/FileUtil.java index df54e766..0648b629 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/FileUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/FileUtil.java @@ -68,12 +68,7 @@ public final class FileUtil { if (files != null) { String[] paths = new String[files.size()]; for (int i = 0; i < files.size(); i++) { - try { - paths[i] = files.get(i).getCanonicalPath(); // canonical path is important here because we want to compare the path with the media store entry later - } catch (IOException e) { - e.printStackTrace(); - paths[i] = files.get(i).getPath(); - } + paths[i] = safeGetCanonicalPath(files.get(i)); } return paths; } @@ -190,4 +185,13 @@ public final class FileUtil { fin.close(); return ret; } + + public static String safeGetCanonicalPath(File file) { + try { + return file.getCanonicalPath(); + } catch (IOException e) { + e.printStackTrace(); + return file.getAbsolutePath(); + } + } } diff --git a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java index b16242f6..589c690c 100644 --- a/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java +++ b/app/src/main/java/com/kabouzeid/gramophone/util/PreferenceUtil.java @@ -71,6 +71,8 @@ public final class PreferenceUtil { public static final String SYNCHRONIZED_LYRICS_SHOW = "synchronized_lyrics_show"; + public static final String INITIALIZED_BLACKLIST = "initialized_blacklist"; + private static PreferenceUtil sInstance; private final SharedPreferences mPreferences; @@ -405,11 +407,21 @@ public final class PreferenceUtil { public void setStartDirectory(File file) { final SharedPreferences.Editor editor = mPreferences.edit(); - editor.putString(START_DIRECTORY, file.getPath()); + editor.putString(START_DIRECTORY, FileUtil.safeGetCanonicalPath(file)); editor.apply(); } public final boolean synchronizedLyricsShow() { return mPreferences.getBoolean(SYNCHRONIZED_LYRICS_SHOW, true); } + + public void setInitializedBlacklist() { + final SharedPreferences.Editor editor = mPreferences.edit(); + editor.putBoolean(INITIALIZED_BLACKLIST, true); + editor.apply(); + } + + public final boolean initializedBlacklist() { + return mPreferences.getBoolean(INITIALIZED_BLACKLIST, false); + } } diff --git a/app/src/main/res/values/strings.xml b/app/src/main/res/values/strings.xml index 5d65e0fe..3b30f72e 100644 --- a/app/src/main/res/values/strings.xml +++ b/app/src/main/res/values/strings.xml @@ -286,4 +286,10 @@ Restore No purchase found. For his contributions to the source code. + Add + Blacklist + Remove from blacklist + %1$s from the blacklist?]]> + Clear blacklist + Do you want to clear the blacklist? diff --git a/app/src/main/res/xml/pref_blacklist.xml b/app/src/main/res/xml/pref_blacklist.xml new file mode 100644 index 00000000..803d9e8d --- /dev/null +++ b/app/src/main/res/xml/pref_blacklist.xml @@ -0,0 +1,12 @@ + + + + + + + + +