diff --git a/app/src/main/java/com/einmalfel/podlisten/MainActivity.java b/app/src/main/java/com/einmalfel/podlisten/MainActivity.java index c46d975..ee3f5d7 100644 --- a/app/src/main/java/com/einmalfel/podlisten/MainActivity.java +++ b/app/src/main/java/com/einmalfel/podlisten/MainActivity.java @@ -412,15 +412,7 @@ public synchronized void onClick(View v) { PodlistenAccount.getInstance().refresh(0); break; case SORT: - Preferences preferences = Preferences.getInstance(); - Preferences.SortingMode newMode = preferences.getSortingMode().nextCyclic(); - preferences.setSortingMode(newMode); - if (playlistFragment != null) { - playlistFragment.reloadList(); - } else { - Log.w(TAG, "Playlist fragment doesn't exist yet, skipping reload"); - } - snackbarController.showSnackbar(newMode.toString(), Snackbar.LENGTH_SHORT, null, null); + currentFabActionSortCase(); break; default: Log.e(TAG, "Unexpected currentFabAction received: " + currentFabAction); @@ -445,6 +437,18 @@ public synchronized void onClick(View v) { } } + private void currentFabActionSortCase() { + Preferences preferences = Preferences.getInstance(); + Preferences.SortingMode newMode = preferences.getSortingMode().nextCyclic(); + preferences.setSortingMode(newMode); + if (playlistFragment != null) { + playlistFragment.reloadList(); + } else { + Log.w(TAG, "Playlist fragment doesn't exist yet, skipping reload"); + } + snackbarController.showSnackbar(newMode.toString(), Snackbar.LENGTH_SHORT, null, null); + } + @Override protected void onNewIntent(Intent intent) { super.onNewIntent(intent); diff --git a/app/src/main/java/com/einmalfel/podlisten/PlayerService.java b/app/src/main/java/com/einmalfel/podlisten/PlayerService.java index d5e23dc..7767ee8 100644 --- a/app/src/main/java/com/einmalfel/podlisten/PlayerService.java +++ b/app/src/main/java/com/einmalfel/podlisten/PlayerService.java @@ -117,22 +117,10 @@ public void run() { synchronized (service) { switch (ct) { case STATE: - if (lastState != service.getState() || lastEpisode != currentId) { - sendStateUpdate(); - lastState = service.state; - lastEpisode = currentId; - } + ctStateCase(); break; case PROGRESS: - if (lastLength != service.length || lastProgress != service.getProgress()) { - sendProgressUpdate(); - lastLength = service.length; - lastProgress = service.progress; - } - if (fixingEndingSkip && service.length - service.progress < TRACK_ENDING_THRESHOLD_MS) { - Log.i(TAG, "Fixing ending skip: calling onCompletion, pos: " + service.progress); - onCompletion(player); - } + ctProgressCase(); break; default: Log.e(TAG, "Unexpected ct received: " + ct); @@ -143,6 +131,26 @@ public void run() { Log.d(TAG, "Finishing callback thread"); } + private void ctProgressCase() { + if (lastLength != service.length || lastProgress != service.getProgress()) { + sendProgressUpdate(); + lastLength = service.length; + lastProgress = service.progress; + } + if (fixingEndingSkip && service.length - service.progress < TRACK_ENDING_THRESHOLD_MS) { + Log.i(TAG, "Fixing ending skip: calling onCompletion, pos: " + service.progress); + onCompletion(player); + } + } + + private void ctStateCase() { + if (lastState != service.getState() || lastEpisode != currentId) { + sendStateUpdate(); + lastState = service.state; + lastEpisode = currentId; + } + } + private void sendStateUpdate() { Log.d(TAG, "Sending new playback state " + service.getState() + " id " + currentId); for (PlayerStateListener listener : listeners) { @@ -367,11 +375,7 @@ public synchronized void onAudioFocusChange(int focusChange) { Log.i(TAG, "Audio focus chagned from " + focusMode + " to " + focusChange); switch (focusChange) { case AudioManager.AUDIOFOCUS_GAIN: - if (focusMode == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { - setVolume(1f); - } else if (focusMode == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT && state == State.PLAYING) { - resume(); - } + focusChangeAudioFocusGainCase(); break; case AudioManager.AUDIOFOCUS_LOSS: stop(); @@ -388,6 +392,14 @@ public synchronized void onAudioFocusChange(int focusChange) { focusMode = focusChange; } + private void focusChangeAudioFocusGainCase() { + if (focusMode == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT_CAN_DUCK) { + setVolume(1f); + } else if (focusMode == AudioManager.AUDIOFOCUS_LOSS_TRANSIENT && state == State.PLAYING) { + resume(); + } + } + public synchronized void addListener(PlayerStateListener listener) { callbackThread.addListener(listener); } @@ -676,11 +688,7 @@ public synchronized void playPauseResume() { case STOPPED: case STOPPED_ERROR: case STOPPED_EMPTY: - if (currentId != 0) { - playEpisode(currentId); - } else { - playNext(); - } + stateStoppedEmptyCase(); break; case PLAYING: pause(); @@ -694,6 +702,14 @@ public synchronized void playPauseResume() { } } + private void stateStoppedEmptyCase() { + if (currentId != 0) { + playEpisode(currentId); + } else { + playNext(); + } + } + private void initPlayer() { if (player == null) { player = new MediaPlayer(); diff --git a/app/src/main/java/com/einmalfel/podlisten/Preferences.java b/app/src/main/java/com/einmalfel/podlisten/Preferences.java index 7993d18..75f8b97 100644 --- a/app/src/main/java/com/einmalfel/podlisten/Preferences.java +++ b/app/src/main/java/com/einmalfel/podlisten/Preferences.java @@ -322,12 +322,7 @@ private synchronized void readPreference(Key key) { completeAction = readEnum(Key.COMPLETE_ACTION, DEFAULT_COMPLETE_ACTION); break; case DOWNLOAD_NETWORK: - DownloadNetwork newDLNetwork = readEnum(Key.DOWNLOAD_NETWORK, DEFAULT_DOWNLOAD_NETWORK); - if (downloadNetwork != newDLNetwork) { - downloadNetwork = newDLNetwork; - DownloadReceiver.stopDownloads(null); - context.sendBroadcast(new Intent(DownloadReceiver.UPDATE_QUEUE_ACTION)); - } + keyDownloadNetworkCase(); break; case PAUSE_ON_DISCONNECT: pauseOnDisconnect = sPrefs.getBoolean(Key.PAUSE_ON_DISCONNECT.toString(), true); @@ -336,15 +331,7 @@ private synchronized void readPreference(Key key) { fixSkipEnding = sPrefs.getBoolean(Key.FIX_SKIP_ENDING.toString(), false); break; case AUTO_DOWNLOAD_AC: - boolean newAutoDownloadAC = sPrefs.getBoolean(Key.AUTO_DOWNLOAD_AC.toString(), false); - if (newAutoDownloadAC != autoDownloadACOnly) { - autoDownloadACOnly = newAutoDownloadAC; - if (!autoDownloadACOnly) { - context.sendBroadcast(new Intent(DownloadReceiver.UPDATE_QUEUE_ACTION)); - } else if (!DownloadReceiver.isDeviceCharging()) { - DownloadReceiver.stopDownloads(null); - } - } + keyAutoDownloadAcCase(); break; case PLAYER_FOREGROUND: playerForeground = sPrefs.getBoolean(Key.PLAYER_FOREGROUND.toString(), false); @@ -354,68 +341,19 @@ private synchronized void readPreference(Key key) { Log.e(TAG, "read " + currentActivity); break; case AUTO_DOWNLOAD: - AutoDownloadMode newM = readEnum(Key.AUTO_DOWNLOAD, DEFAULT_DOWNLOAD_MODE); - if (newM != autoDownloadMode) { - if (newM == AutoDownloadMode.PLAYLIST && autoDownloadMode == AutoDownloadMode.ALL_NEW) { - DownloadReceiver.stopDownloads( - Provider.K_ESTATE + " != " + Provider.ESTATE_IN_PLAYLIST); - } else if (newM == AutoDownloadMode.NEVER) { - DownloadReceiver.stopDownloads(null); - } - autoDownloadMode = newM; - context.sendBroadcast(new Intent(DownloadReceiver.UPDATE_QUEUE_ACTION)); - } + keyAutoDownloadCase(); break; case SORTING_MODE: sortingMode = readEnum(Key.SORTING_MODE, DEFAULT_SORTING_MODE); break; case MAX_DOWNLOADS: - MaxDownloadsOption newMaxDL = readEnum(Key.MAX_DOWNLOADS, DEFAULT_MAX_DOWNLOADS); - if (newMaxDL != maxDownloads) { - maxDownloads = newMaxDL; - context.sendBroadcast(new Intent(DownloadReceiver.UPDATE_QUEUE_ACTION)); - } + keyMaxDownloadsCase(); break; case REFRESH_INTERVAL: - RefreshIntervalOption newRI = readEnum(Key.REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL); - if (newRI != refreshInterval) { - refreshInterval = newRI; - PodlistenAccount.getInstance().setupSync(refreshInterval.periodSeconds); - } + keyRefreshIntervalCase(); break; case STORAGE_PATH: - String storagePreferenceString = sPrefs.getString(Key.STORAGE_PATH.toString(), ""); - if (storagePreferenceString.isEmpty()) { - // by default, if there are removable storages use first removable, otherwise use last one - List storages = Storage.getWritableStorages(); - storage = Storage.getPrimaryStorage(); - for (Storage storageOption : storages) { - storage = storageOption; - if (storageOption.isRemovable()) { - break; - } - } - try { - storage.createSubdirs(); - sPrefs.edit().putString(Key.STORAGE_PATH.toString(), storage.toString()).commit(); - } catch (IOException exception) { - Log.wtf(TAG, "Failed to init storage known to be writable " + storage, exception); - } - } else { - try { - Storage newStorage = new Storage(new File(storagePreferenceString)); - newStorage.createSubdirs(); - if (storage != null && !storage.equals(newStorage)) { - clearStorage(); - } - storage = newStorage; - } catch (IOException e) { - Log.wtf( - TAG, "Failed to set storage " + storagePreferenceString + ". Reverting to prev", e); - sPrefs.edit().putString( - Key.STORAGE_PATH.toString(), storage == null ? "" : storage.toString()).commit(); - } - } + keyStoragePathCase(); break; default: Log.e(TAG, "Unexpected key received: " + key); @@ -423,6 +361,92 @@ private synchronized void readPreference(Key key) { } } + private void keyStoragePathCase() { + String storagePreferenceString = sPrefs.getString(Key.STORAGE_PATH.toString(), ""); + if (storagePreferenceString.isEmpty()) { + // by default, if there are removable storages use first removable, otherwise use last one + List storages = Storage.getWritableStorages(); + storage = Storage.getPrimaryStorage(); + for (Storage storageOption : storages) { + storage = storageOption; + if (storageOption.isRemovable()) { + break; + } + } + try { + storage.createSubdirs(); + sPrefs.edit().putString(Key.STORAGE_PATH.toString(), storage.toString()).commit(); + } catch (IOException exception) { + Log.wtf(TAG, "Failed to init storage known to be writable " + storage, exception); + } + } else { + try { + Storage newStorage = new Storage(new File(storagePreferenceString)); + newStorage.createSubdirs(); + if (storage != null && !storage.equals(newStorage)) { + clearStorage(); + } + storage = newStorage; + } catch (IOException e) { + Log.wtf( + TAG, "Failed to set storage " + storagePreferenceString + ". Reverting to prev", e); + sPrefs.edit().putString( + Key.STORAGE_PATH.toString(), storage == null ? "" : storage.toString()).commit(); + } + } + } + + private void keyRefreshIntervalCase() { + RefreshIntervalOption newRI = readEnum(Key.REFRESH_INTERVAL, DEFAULT_REFRESH_INTERVAL); + if (newRI != refreshInterval) { + refreshInterval = newRI; + PodlistenAccount.getInstance().setupSync(refreshInterval.periodSeconds); + } + } + + private void keyMaxDownloadsCase() { + MaxDownloadsOption newMaxDL = readEnum(Key.MAX_DOWNLOADS, DEFAULT_MAX_DOWNLOADS); + if (newMaxDL != maxDownloads) { + maxDownloads = newMaxDL; + context.sendBroadcast(new Intent(DownloadReceiver.UPDATE_QUEUE_ACTION)); + } + } + + private void keyAutoDownloadCase() { + AutoDownloadMode newM = readEnum(Key.AUTO_DOWNLOAD, DEFAULT_DOWNLOAD_MODE); + if (newM != autoDownloadMode) { + if (newM == AutoDownloadMode.PLAYLIST && autoDownloadMode == AutoDownloadMode.ALL_NEW) { + DownloadReceiver.stopDownloads( + Provider.K_ESTATE + " != " + Provider.ESTATE_IN_PLAYLIST); + } else if (newM == AutoDownloadMode.NEVER) { + DownloadReceiver.stopDownloads(null); + } + autoDownloadMode = newM; + context.sendBroadcast(new Intent(DownloadReceiver.UPDATE_QUEUE_ACTION)); + } + } + + private void keyAutoDownloadAcCase() { + boolean newAutoDownloadAC = sPrefs.getBoolean(Key.AUTO_DOWNLOAD_AC.toString(), false); + if (newAutoDownloadAC != autoDownloadACOnly) { + autoDownloadACOnly = newAutoDownloadAC; + if (!autoDownloadACOnly) { + context.sendBroadcast(new Intent(DownloadReceiver.UPDATE_QUEUE_ACTION)); + } else if (!DownloadReceiver.isDeviceCharging()) { + DownloadReceiver.stopDownloads(null); + } + } + } + + private void keyDownloadNetworkCase() { + DownloadNetwork newDLNetwork = readEnum(Key.DOWNLOAD_NETWORK, DEFAULT_DOWNLOAD_NETWORK); + if (downloadNetwork != newDLNetwork) { + downloadNetwork = newDLNetwork; + DownloadReceiver.stopDownloads(null); + context.sendBroadcast(new Intent(DownloadReceiver.UPDATE_QUEUE_ACTION)); + } + } + @NonNull public RefreshIntervalOption getRefreshInterval() { return refreshInterval; diff --git a/app/src/main/java/com/einmalfel/podlisten/PreferencesActivity.java b/app/src/main/java/com/einmalfel/podlisten/PreferencesActivity.java index ca590a5..1a6357b 100644 --- a/app/src/main/java/com/einmalfel/podlisten/PreferencesActivity.java +++ b/app/src/main/java/com/einmalfel/podlisten/PreferencesActivity.java @@ -66,52 +66,7 @@ protected void onNewIntent(Intent intent) { PodListenApp.sendLogs(); break; case "com.einmalfel.podlisten.OPML_EXPORT": - String state = Environment.getExternalStorageState(); - if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_UNKNOWN.equals(state)) { - final File dir; - if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { - dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS); - } else { - dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS); - } - if (!dir.exists() && !dir.mkdirs()) { - Log.e(TAG, "Directory for OPML export doesn't exist " + dir); - } - final File target = new File(dir, getString(R.string.opml_export_file_name)); - if (exportToOPML(target)) { - AlertDialog.Builder b = new AlertDialog.Builder(this); - b.setTitle(getString(R.string.opml_dialog_title)) - .setMessage(String.format(getString(R.string.opml_dialog_message), target)) - .setNegativeButton(R.string.opml_dialog_done, null); - - final Intent sendIntent = new Intent(Intent.ACTION_SEND); - sendIntent.setType("file/*"); - sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(target)); - if (sendIntent.resolveActivity(getPackageManager()) != null) { - b.setPositiveButton(R.string.opml_dialog_send, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - startActivity(sendIntent); - } - }); - } - - if (showDirectory(dir, true)) { - b.setNeutralButton(R.string.opml_dialog_FMapp, new DialogInterface.OnClickListener() { - @Override - public void onClick(DialogInterface dialog, int which) { - showDirectory(dir, false); - } - }); - } - - b.show(); - } else { - Snackbar.make(findViewById(android.R.id.content), - R.string.preferences_opml_export_failed, - Snackbar.LENGTH_LONG).show(); - } - } + intentOPMLExportCase(); break; default: Log.e(TAG, "Unexpected intent received: " + intent); @@ -119,6 +74,55 @@ public void onClick(DialogInterface dialog, int which) { } } + private void intentOPMLExportCase() { + String state = Environment.getExternalStorageState(); + if (Environment.MEDIA_MOUNTED.equals(state) || Environment.MEDIA_UNKNOWN.equals(state)) { + final File dir; + if (android.os.Build.VERSION.SDK_INT >= android.os.Build.VERSION_CODES.KITKAT) { + dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_DOCUMENTS); + } else { + dir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PODCASTS); + } + if (!dir.exists() && !dir.mkdirs()) { + Log.e(TAG, "Directory for OPML export doesn't exist " + dir); + } + final File target = new File(dir, getString(R.string.opml_export_file_name)); + if (exportToOPML(target)) { + AlertDialog.Builder b = new AlertDialog.Builder(this); + b.setTitle(getString(R.string.opml_dialog_title)) + .setMessage(String.format(getString(R.string.opml_dialog_message), target)) + .setNegativeButton(R.string.opml_dialog_done, null); + + final Intent sendIntent = new Intent(Intent.ACTION_SEND); + sendIntent.setType("file/*"); + sendIntent.putExtra(Intent.EXTRA_STREAM, Uri.fromFile(target)); + if (sendIntent.resolveActivity(getPackageManager()) != null) { + b.setPositiveButton(R.string.opml_dialog_send, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + startActivity(sendIntent); + } + }); + } + + if (showDirectory(dir, true)) { + b.setNeutralButton(R.string.opml_dialog_FMapp, new DialogInterface.OnClickListener() { + @Override + public void onClick(DialogInterface dialog, int which) { + showDirectory(dir, false); + } + }); + } + + b.show(); + } else { + Snackbar.make(findViewById(android.R.id.content), + R.string.preferences_opml_export_failed, + Snackbar.LENGTH_LONG).show(); + } + } + } + private boolean exportToOPML(File file) { XmlSerializer serializer = Xml.newSerializer(); try {