feat: added external memory cache option

This commit is contained in:
CappielloAntonio 2024-05-26 14:49:57 +02:00
parent c4e8fe5261
commit 477331da6f
7 changed files with 188 additions and 4 deletions

View file

@ -0,0 +1,76 @@
package com.cappielloantonio.tempo.ui.dialog;
import android.app.Dialog;
import android.os.Bundle;
import android.widget.Button;
import androidx.annotation.NonNull;
import androidx.annotation.OptIn;
import androidx.fragment.app.DialogFragment;
import androidx.media3.common.util.UnstableApi;
import com.cappielloantonio.tempo.R;
import com.cappielloantonio.tempo.databinding.DialogStreamingCacheStorageBinding;
import com.cappielloantonio.tempo.interfaces.DialogClickCallback;
import com.cappielloantonio.tempo.util.Preferences;
import com.google.android.material.dialog.MaterialAlertDialogBuilder;
@OptIn(markerClass = UnstableApi.class)
public class StreamingCacheStorageDialog extends DialogFragment {
private final DialogClickCallback dialogClickCallback;
public StreamingCacheStorageDialog(DialogClickCallback dialogClickCallback) {
this.dialogClickCallback = dialogClickCallback;
}
@NonNull
@Override
public Dialog onCreateDialog(Bundle savedInstanceState) {
DialogStreamingCacheStorageBinding bind = DialogStreamingCacheStorageBinding.inflate(getLayoutInflater());
return new MaterialAlertDialogBuilder(getActivity())
.setView(bind.getRoot())
.setTitle(R.string.streaming_cache_storage_dialog_title)
.setPositiveButton(R.string.streaming_cache_storage_external_dialog_positive_button, null)
.setNegativeButton(R.string.streaming_cache_storage_internal_dialog_negative_button, null)
.create();
}
@Override
public void onResume() {
super.onResume();
setButtonAction();
}
private void setButtonAction() {
androidx.appcompat.app.AlertDialog dialog = (androidx.appcompat.app.AlertDialog) getDialog();
if (dialog != null) {
Button positiveButton = dialog.getButton(Dialog.BUTTON_POSITIVE);
positiveButton.setOnClickListener(v -> {
int currentPreference = Preferences.getStreamingCacheStoragePreference();
int newPreference = 1;
if (currentPreference != newPreference) {
Preferences.setStreamingCacheStoragePreference(newPreference);
dialogClickCallback.onPositiveClick();
}
dialog.dismiss();
});
Button negativeButton = dialog.getButton(Dialog.BUTTON_NEGATIVE);
negativeButton.setOnClickListener(v -> {
int currentPreference = Preferences.getStreamingCacheStoragePreference();
int newPreference = 0;
if (currentPreference != newPreference) {
Preferences.setStreamingCacheStoragePreference(newPreference);
dialogClickCallback.onNegativeClick();
}
dialog.dismiss();
});
}
}
}

View file

@ -3,6 +3,7 @@ package com.cappielloantonio.tempo.ui.fragment;
import android.content.Intent; import android.content.Intent;
import android.media.audiofx.AudioEffect; import android.media.audiofx.AudioEffect;
import android.os.Bundle; import android.os.Bundle;
import android.os.Handler;
import android.view.LayoutInflater; import android.view.LayoutInflater;
import android.view.View; import android.view.View;
import android.view.ViewGroup; import android.view.ViewGroup;
@ -30,8 +31,8 @@ import com.cappielloantonio.tempo.ui.activity.MainActivity;
import com.cappielloantonio.tempo.ui.dialog.DeleteDownloadStorageDialog; import com.cappielloantonio.tempo.ui.dialog.DeleteDownloadStorageDialog;
import com.cappielloantonio.tempo.ui.dialog.DownloadStorageDialog; import com.cappielloantonio.tempo.ui.dialog.DownloadStorageDialog;
import com.cappielloantonio.tempo.ui.dialog.StarredSyncDialog; import com.cappielloantonio.tempo.ui.dialog.StarredSyncDialog;
import com.cappielloantonio.tempo.ui.dialog.StreamingCacheStorageDialog;
import com.cappielloantonio.tempo.util.DownloadUtil; import com.cappielloantonio.tempo.util.DownloadUtil;
import com.cappielloantonio.tempo.util.MusicUtil;
import com.cappielloantonio.tempo.util.Preferences; import com.cappielloantonio.tempo.util.Preferences;
import com.cappielloantonio.tempo.util.UIUtil; import com.cappielloantonio.tempo.util.UIUtil;
import com.cappielloantonio.tempo.viewmodel.SettingViewModel; import com.cappielloantonio.tempo.viewmodel.SettingViewModel;
@ -84,6 +85,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
super.onResume(); super.onResume();
checkEqualizer(); checkEqualizer();
checkCacheStorage();
checkStorage(); checkStorage();
setStreamingCacheSize(); setStreamingCacheSize();
@ -93,6 +95,7 @@ public class SettingsFragment extends PreferenceFragmentCompat {
actionLogout(); actionLogout();
actionScan(); actionScan();
actionSyncStarredTracks(); actionSyncStarredTracks();
actionChangeStreamingCacheStorage();
actionChangeDownloadStorage(); actionChangeDownloadStorage();
actionDeleteDownloadStorage(); actionDeleteDownloadStorage();
actionKeepScreenOn(); actionKeepScreenOn();
@ -135,6 +138,22 @@ public class SettingsFragment extends PreferenceFragmentCompat {
} }
} }
private void checkCacheStorage() {
Preference storage = findPreference("streaming_cache_storage");
if (storage == null) return;
try {
if (requireContext().getExternalFilesDirs(null)[1] == null) {
storage.setVisible(false);
} else {
storage.setSummary(Preferences.getDownloadStoragePreference() == 0 ? R.string.download_storage_internal_dialog_negative_button : R.string.download_storage_external_dialog_positive_button);
}
} catch (Exception exception) {
storage.setVisible(false);
}
}
private void checkStorage() { private void checkStorage() {
Preference storage = findPreference("download_storage"); Preference storage = findPreference("download_storage");
@ -213,7 +232,8 @@ public class SettingsFragment extends PreferenceFragmentCompat {
@Override @Override
public void onSuccess(boolean isScanning, long count) { public void onSuccess(boolean isScanning, long count) {
getScanStatus(); findPreference("scan_library").setSummary("Scanning: counting " + count + " tracks");
if (isScanning) getScanStatus();
} }
}); });
@ -233,6 +253,24 @@ public class SettingsFragment extends PreferenceFragmentCompat {
}); });
} }
private void actionChangeStreamingCacheStorage() {
findPreference("streaming_cache_storage").setOnPreferenceClickListener(preference -> {
StreamingCacheStorageDialog dialog = new StreamingCacheStorageDialog(new DialogClickCallback() {
@Override
public void onPositiveClick() {
findPreference("streaming_cache_storage").setSummary(R.string.streaming_cache_storage_external_dialog_positive_button);
}
@Override
public void onNegativeClick() {
findPreference("streaming_cache_storage").setSummary(R.string.streaming_cache_storage_internal_dialog_negative_button);
}
});
dialog.show(activity.getSupportFragmentManager(), null);
return true;
});
}
private void actionChangeDownloadStorage() { private void actionChangeDownloadStorage() {
findPreference("download_storage").setOnPreferenceClickListener(preference -> { findPreference("download_storage").setOnPreferenceClickListener(preference -> {
DownloadStorageDialog dialog = new DownloadStorageDialog(new DialogClickCallback() { DownloadStorageDialog dialog = new DownloadStorageDialog(new DialogClickCallback() {

View file

@ -38,11 +38,13 @@ public final class DownloadUtil {
public static final String DOWNLOAD_NOTIFICATION_SUCCESSFUL_GROUP = "com.cappielloantonio.tempo.SuccessfulDownload"; public static final String DOWNLOAD_NOTIFICATION_SUCCESSFUL_GROUP = "com.cappielloantonio.tempo.SuccessfulDownload";
public static final String DOWNLOAD_NOTIFICATION_FAILED_GROUP = "com.cappielloantonio.tempo.FailedDownload"; public static final String DOWNLOAD_NOTIFICATION_FAILED_GROUP = "com.cappielloantonio.tempo.FailedDownload";
private static final String STREAMING_CACHE_CONTENT_DIRECTORY = "streaming_cache";
private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads"; private static final String DOWNLOAD_CONTENT_DIRECTORY = "downloads";
private static DataSource.Factory dataSourceFactory; private static DataSource.Factory dataSourceFactory;
private static DataSource.Factory httpDataSourceFactory; private static DataSource.Factory httpDataSourceFactory;
private static DatabaseProvider databaseProvider; private static DatabaseProvider databaseProvider;
private static File streamingCacheDirectory;
private static File downloadDirectory; private static File downloadDirectory;
private static Cache downloadCache; private static Cache downloadCache;
private static SimpleCache streamingCache; private static SimpleCache streamingCache;
@ -135,7 +137,7 @@ public final class DownloadUtil {
private static synchronized SimpleCache getStreamingCache(Context context) { private static synchronized SimpleCache getStreamingCache(Context context) {
if (streamingCache == null) { if (streamingCache == null) {
File streamingCacheDirectory = new File(context.getCacheDir(), "streamingCache"); File streamingCacheDirectory = new File(getStreamingCacheDirectory(context), STREAMING_CACHE_CONTENT_DIRECTORY);
streamingCache = new SimpleCache( streamingCache = new SimpleCache(
streamingCacheDirectory, streamingCacheDirectory,
@ -169,6 +171,27 @@ public final class DownloadUtil {
return databaseProvider; return databaseProvider;
} }
private static synchronized File getStreamingCacheDirectory(Context context) {
if (streamingCacheDirectory == null) {
if (Preferences.getStreamingCacheStoragePreference() == 0) {
streamingCacheDirectory = context.getExternalFilesDirs(null)[0];
if (streamingCacheDirectory == null) {
streamingCacheDirectory = context.getFilesDir();
}
} else {
try {
streamingCacheDirectory = context.getExternalFilesDirs(null)[1];
} catch (Exception exception) {
streamingCacheDirectory = context.getExternalFilesDirs(null)[0];
Preferences.setStreamingCacheStoragePreference(0);
}
}
}
return streamingCacheDirectory;
}
private static synchronized File getDownloadDirectory(Context context) { private static synchronized File getDownloadDirectory(Context context) {
if (downloadDirectory == null) { if (downloadDirectory == null) {
if (Preferences.getDownloadStoragePreference() == 0) { if (Preferences.getDownloadStoragePreference() == 0) {

View file

@ -42,6 +42,7 @@ object Preferences {
private const val MUSIC_DIRECTORY_SECTION_VISIBILITY = "music_directory_section_visibility" private const val MUSIC_DIRECTORY_SECTION_VISIBILITY = "music_directory_section_visibility"
private const val REPLAY_GAIN_MODE = "replay_gain_mode" private const val REPLAY_GAIN_MODE = "replay_gain_mode"
private const val AUDIO_TRANSCODE_PRIORITY = "audio_transcode_priority" private const val AUDIO_TRANSCODE_PRIORITY = "audio_transcode_priority"
private const val STREAMING_CACHE_STORAGE = "streaming_cache_storage"
private const val DOWNLOAD_STORAGE = "download_storage" private const val DOWNLOAD_STORAGE = "download_storage"
private const val DEFAULT_DOWNLOAD_VIEW_TYPE = "default_download_view_type" private const val DEFAULT_DOWNLOAD_VIEW_TYPE = "default_download_view_type"
private const val AUDIO_TRANSCODE_DOWNLOAD = "audio_transcode_download" private const val AUDIO_TRANSCODE_DOWNLOAD = "audio_transcode_download"
@ -310,6 +311,19 @@ object Preferences {
return App.getInstance().preferences.getBoolean(AUDIO_TRANSCODE_PRIORITY, false) return App.getInstance().preferences.getBoolean(AUDIO_TRANSCODE_PRIORITY, false)
} }
@JvmStatic
fun getStreamingCacheStoragePreference(): Int {
return App.getInstance().preferences.getString(STREAMING_CACHE_STORAGE, "0")!!.toInt()
}
@JvmStatic
fun setStreamingCacheStoragePreference(streamingCachePreference: Int) {
return App.getInstance().preferences.edit().putString(
STREAMING_CACHE_STORAGE,
streamingCachePreference.toString()
).apply()
}
@JvmStatic @JvmStatic
fun getDownloadStoragePreference(): Int { fun getDownloadStoragePreference(): Int {
return App.getInstance().preferences.getString(DOWNLOAD_STORAGE, "0")!!.toInt() return App.getInstance().preferences.getString(DOWNLOAD_STORAGE, "0")!!.toInt()

View file

@ -0,0 +1,23 @@
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:orientation="vertical">
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="12dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="4dp"
android:text="@string/streaming_cache_storage_dialog_summary" />
<TextView
android:layout_width="match_parent"
android:layout_height="wrap_content"
android:layout_marginStart="24dp"
android:layout_marginTop="8dp"
android:layout_marginEnd="24dp"
android:layout_marginBottom="4dp"
android:text="@string/streaming_cache_storage_dialog_sub_summary" />
</LinearLayout>

View file

@ -289,8 +289,9 @@
<string name="settings_scan_title">Scan library</string> <string name="settings_scan_title">Scan library</string>
<string name="settings_scrobble_title">Enable music scrobbling</string> <string name="settings_scrobble_title">Enable music scrobbling</string>
<string name="settings_share_title">Enable music sharing</string> <string name="settings_share_title">Enable music sharing</string>
<string name="settings_sub_summary_scrobble">It\'s important to note that scrobbling also relies on the server being enabled to receive this data.</string>
<string name="settings_streaming_cache_size">Size of streaming cache</string> <string name="settings_streaming_cache_size">Size of streaming cache</string>
<string name="settings_streaming_cache_storage_title">Streaming cache storage</string>
<string name="settings_sub_summary_scrobble">It\'s important to note that scrobbling also relies on the server being enabled to receive this data.</string>
<string name="settings_summary_skip_min_star_rating">When listening to an artist\'s radio, an instant mix or when shuffling all, tracks below a certain user rating will be ignored.</string> <string name="settings_summary_skip_min_star_rating">When listening to an artist\'s radio, an instant mix or when shuffling all, tracks below a certain user rating will be ignored.</string>
<string name="settings_summary_replay_gain">Replay gain is a feature that allows you to adjust the volume level of audio tracks for a consistent listening experience. This setting is only effective if the track contains the necessary metadata.</string> <string name="settings_summary_replay_gain">Replay gain is a feature that allows you to adjust the volume level of audio tracks for a consistent listening experience. This setting is only effective if the track contains the necessary metadata.</string>
<string name="settings_summary_scrobble">Scrobbling is a feature that allows your device to send information about the songs you listen to the music server. This information helps create personalized recommendations based on your music preferences.</string> <string name="settings_summary_scrobble">Scrobbling is a feature that allows your device to send information about the songs you listen to the music server. This information helps create personalized recommendations based on your music preferences.</string>
@ -355,6 +356,11 @@
<string name="starred_sync_dialog_positive_button">Continue and download</string> <string name="starred_sync_dialog_positive_button">Continue and download</string>
<string name="starred_sync_dialog_summary">Downloading starry tracks may require a large amount of data.</string> <string name="starred_sync_dialog_summary">Downloading starry tracks may require a large amount of data.</string>
<string name="starred_sync_dialog_title">Sync starred tracks</string> <string name="starred_sync_dialog_title">Sync starred tracks</string>
<string name="streaming_cache_storage_dialog_sub_summary">For the changes to take effect, restart the app.</string>
<string name="streaming_cache_storage_dialog_summary">Changing the destination of cached files from one storage to another may result in the deletion of any previously cached files in the other storage.</string>
<string name="streaming_cache_storage_dialog_title">Select storage option</string>
<string name="streaming_cache_storage_external_dialog_positive_button">External</string>
<string name="streaming_cache_storage_internal_dialog_negative_button">Internal</string>
<string name="track_info_album">Album</string> <string name="track_info_album">Album</string>
<string name="track_info_artist">Artist</string> <string name="track_info_artist">Artist</string>
<string name="track_info_bitrate">Bitrate</string> <string name="track_info_bitrate">Bitrate</string>

View file

@ -137,6 +137,10 @@
app:summary="@string/settings_buffering_strategy_summary" app:summary="@string/settings_buffering_strategy_summary"
app:useSimpleSummaryProvider="false" /> app:useSimpleSummaryProvider="false" />
<Preference
android:key="streaming_cache_storage"
app:title="@string/settings_streaming_cache_storage_title" />
<Preference <Preference
android:key="download_storage" android:key="download_storage"
app:title="@string/settings_download_storage_title" /> app:title="@string/settings_download_storage_title" />