Compare commits

...

73 Commits

Author SHA1 Message Date
Andrew Rabert 4c1bb5375d Cease development 2022-10-14 13:24:20 -04:00
Andrew Rabert f1a9686eb4 Use latest java 2022-03-31 22:11:06 -04:00
Andrew Rabert 279adc166b Update com.github.hannesa2:AndroidSlidingUpPanel to 4.4.1 2022-03-31 22:05:16 -04:00
Andrew Rabert c20a64ab15 Update deps 2022-03-31 21:59:05 -04:00
Andrew Rabert aa4c877046
Merge pull request #105 from masipcat/master
Fix search for some backends
2021-07-14 11:49:28 -04:00
Jordi Masip 09c5d7ee51 Fix search artist for some backends 2021-07-10 18:09:40 +02:00
Andrew Rabert 27b0dc742c AppCompat updates 2021-05-23 14:56:08 -04:00
Andrew Rabert 63df26cdfd Optimize imports 2021-05-23 14:49:37 -04:00
Andrew Rabert 49f15f2a0d Remove unused 2021-05-23 14:48:02 -04:00
Andrew Rabert 2c3c9ede14 update deps 2021-05-23 14:45:21 -04:00
Andrew Rabert ef2e19ebf2 Update deps 2021-05-09 13:18:16 -04:00
Andrew Rabert 4c5406c916 Update deps 2021-02-05 20:10:37 -05:00
Andrew Rabert 072a6d7870 Updates 2020-11-01 19:03:33 -05:00
Andrew Rabert 5ae04b3643
Merge pull request #93 from Refactor4Green/Refactor4Green
Improve energy efficiency by applying Cache Energy Pattern
2020-10-08 17:32:49 -04:00
Andrew Rabert 79ea6cb082
Merge pull request #96 from rerobins/master
Allow User Trusted Credentials
2020-10-08 17:30:34 -04:00
Robert Robinson 8cfae03550 Allow User Trusted Credentials
Subsonic/Ampache are self-hosted applications and should need to be able to support a user defined root certificate if that is installed on the android device.  The default of android applications is to ignore the user trusted credentials.  This patch overrides this by allowing certificates that are signed by certificates added by the user to their device.

See: https://developer.android.com/training/articles/security-config
2020-10-06 20:46:33 -06:00
Andrew Rabert 298a06ab5b optimize images
`oxipng --zopfli --opt max --strip all`
2020-09-21 16:53:03 -04:00
anasofiagribeiro 41d17f960e Refactor4Green - Cache 2020-07-29 10:42:04 +01:00
Andrew Rabert a861e035ab
Merge pull request #90 from the-salami/dark-mode
change day/night themes to support dark mode setting on Android 10+
2020-07-09 18:54:56 -04:00
Morgan Lim 4598f849ff remove unused import added by IDE 2020-07-09 17:03:47 -04:00
Morgan Lim d37a72b2a0 Remove default "light" value for theme in settings_appearance.xml. Change getTheme logic to give a default of day/night on Android 10+. 2020-07-09 17:01:34 -04:00
Andrew Rabert e102dea3d3
Merge pull request #88 from the-salami/widget-fix
fix invisible back/forward buttons on widgets (#81)
2020-07-09 16:02:58 -04:00
Andrew Rabert a69b1385c0
Merge pull request #89 from the-salami/notification-icon
change notification icon to vector audinaut logo
2020-07-09 16:02:52 -04:00
Morgan Lim f506bfb14a Rename Day/Night and Day/Black to "Dynamic". On v28/Android Pie and lower, themes still change based on time of day. On Android 10 and up, theme changes in accordance with system dark mode setting. 2020-07-09 15:54:27 -04:00
Morgan Lim 0f525befca change notification small icon to a white version of the audinaut logo instead of a generic play icon. add additional info to metadata when constructing notification to add basic support for android R's new persistent media controls
(cherry picked from commit ad5615d2bd43b7afe388e08a6a2df07472656b89)
2020-07-09 15:20:35 -04:00
Morgan Lim d3d6186fb7 define button images for forward/back in widget provider so they aren't invisible 2020-07-09 14:35:44 -04:00
Andrew Rabert d10ea92edd Remove unnecessary getUser call 2020-05-22 17:53:44 -04:00
Andrew Rabert d1f1331f35 Fix timeout pref 2020-04-30 13:13:25 -04:00
Andrew Rabert 4fd53e74c5 Release 0.5.1 2020-04-30 13:02:24 -04:00
Andrew Rabert 6704e05da2 Update deps 2020-04-30 12:56:41 -04:00
Andrew Rabert e79aff9e98 Update deps 2020-04-30 12:56:14 -04:00
Andrew Rabert ffa048177e
Merge pull request #66 from emaiannone/refactoring/aDoctor
Refactor Internal Setter smell in RecyclingImageView class
2020-04-30 12:55:58 -04:00
Andrew Rabert f6d308c37c
Merge pull request #78 from simao/bugfix/71
Use settings from preferences for readTimeout
2020-04-30 12:54:53 -04:00
Simão Mata 3c17e91ca8 Use settings from preferences for readTimeout 2020-04-30 16:26:32 +02:00
Andrew Rabert ec083cd79d
Merge pull request #73 from simao/sort-artists-offline-ci
Sort artists using case insensitive comparison when offline
2020-04-13 21:58:00 -04:00
Simão Mata cfae0d30b5 Sort artists using case insensitive comparison when offline
Signed-off-by: Simão Mata <simao.mata@here.com>
2020-04-03 15:33:55 +02:00
Andrew Rabert ecdae8c6e3 Fix switching to playlist on resume
Remove a bunch of unecessary code
2020-03-15 17:06:47 -04:00
Andrew Rabert 76efc2c62c Merge branch 'master' of github:nvllsvm/audinaut 2020-03-15 16:20:55 -04:00
Andrew Rabert 26848852ac
Merge pull request #72 from simao/start-scan-option
Start scan option
2020-03-14 11:36:40 -04:00
Simão Mata 377f21d732 Add option to force media scan on server 2020-03-14 10:41:34 +01:00
Simão Mata 8af307da28 Guard for null theme when getting them res 2020-03-14 10:40:13 +01:00
Andrew Rabert 3d7b173cb1 Update deps 2020-03-13 11:30:59 -04:00
Andrew Rabert e7ea8d4dfc
Merge pull request #67 from dddddd-mmmmmm/issue-25
#25 Add null check to fix crash whilst offline
2020-01-26 18:43:30 -05:00
dddddd-mmmmmm e2280304e4 #25 Add null check to fix crash whilst offline 2020-01-23 16:21:24 +11:00
emaiannone 061c318e05 Refactor Internal Setter smell in RecyclingImageView class 2020-01-19 09:59:20 +01:00
Andrew Rabert 8fc54ac68c Release version 0.5.0 2020-01-15 15:52:48 -05:00
Andrew Rabert 8f4d3be90b Updates 2020-01-15 15:43:28 -05:00
Andrew Rabert a6a784037e
Merge pull request #65 from dddddd-mmmmmm/issue-26
issue-26: Add support for p= authentication method
2020-01-15 15:38:49 -05:00
dddddd-mmmmmm 2ed89ab72f Fix authMethod preference check 2020-01-14 09:14:32 +11:00
Andrew Rabert d5b56eecdd
Merge pull request #64 from dddddd-mmmmmm/issue-48
issue-48: hide keyboard when switching to now playing
2020-01-13 11:01:02 -05:00
dddddd-mmmmmm 81086c4a3a Call hideKeyboard when Panel begins to slide. 2020-01-13 23:36:55 +11:00
dddddd-mmmmmm 02d94e1a6c Add hideKeyboard util method. 2020-01-13 23:36:35 +11:00
dddddd-mmmmmm 5141eb6e81 Use p= authentication parameter when authMethod is false. 2020-01-13 22:08:01 +11:00
dddddd-mmmmmm 4254c8ad9f Add authMethod preference 2020-01-13 22:06:45 +11:00
Andrew Rabert bf9e9ad1e6
Merge pull request #63 from mlim15/mediaStyle-clean
Implement glennguy's MediaStyle notifications
2020-01-11 17:54:39 -05:00
Andrew Rabert 02a8b1909a
Merge pull request #62 from mlim15/master
Fix missing now playing icon on light theme
2020-01-11 17:51:53 -05:00
Morgan Lim ff4a1f3b13 Remove unused import 2020-01-11 04:13:32 -05:00
Morgan Lim 153ccdd46a Manually define duration metadata as -1 to ensure mediastyle notification does not produce unimplemented seek bar on Android 10 2020-01-11 04:12:02 -05:00
Morgan Lim 507c9008aa Colorize MediaStyle notification from album art 2020-01-11 02:33:54 -05:00
Morgan Lim 35a112509e Implement glennguy's MediaStyle notifications daneren2005/Subsonic#914 2020-01-11 02:33:45 -05:00
Andrew Rabert af89b8ea76
Merge pull request #61 from mlim15/vector-adaptive-icon
Change adaptive icon to use vector with shadow
2020-01-11 01:58:17 -05:00
Morgan Lim 0a84e9376a Fix missing now playing icon on light theme 2020-01-10 23:51:57 -05:00
Morgan Lim 717cab5dd5 Change adaptive icon to use vector with shadow 2020-01-10 20:55:02 -05:00
Andrew Rabert 13810a07a5 Revert "Extremely clumsy initial dark mode "support". This does nothing"
This reverts commit cf4ab6bf05.
2020-01-09 17:47:22 -05:00
Andrew Rabert b147cc10dc
Merge pull request #60 from mlim15/bitrate-option
Add 24Kbps (equivalent to Spotify low) and 48Kbps options
2020-01-09 17:45:21 -05:00
mlim15 357cbd2ba1 Add 24Kbps (equivalent to Spotify low) and 48Kbps options for more fine-grained bitrate options 2020-01-09 13:44:19 -05:00
Andrew Rabert 435d770716
Merge pull request #58 from mlim15/location-fix
Add ACCESS_FINE_LOCATION permission to fix LAN access on Android 10
2020-01-09 12:54:28 -05:00
Andrew Rabert 4503ae4133
Merge pull request #56 from mlim15/dark-notifications
Ensure that widget controls change color properly when dark mode is enabled
2020-01-09 12:52:51 -05:00
Andrew Rabert d43cfb1ce3
Merge pull request #59 from mlim15/adaptive-icon
Adaptive icon
2020-01-09 12:52:44 -05:00
mlim15 cc0faa19ce Add ACCESS_FINE_LOCATION permission to fix LAN access on Android 10 2020-01-09 06:33:44 -05:00
mlim15 8078eeff74 Remove smudge from mdpi adaptiveicon 2020-01-09 06:30:21 -05:00
mlim15 d176ed4036 Add initial support for android adaptive icons. TODO: Add backdrop shadow layer with vectors to adaptive icon 2020-01-09 06:00:43 -05:00
mlim15 cf4ab6bf05 Extremely clumsy initial dark mode "support". This does nothing
but ensure that widget controls change color properly when dark mode
is enabled. TODO: Instead of duplicating images, enable DayNight theme
support and use the dynamic colors from that. This would also mean
the app could change to dark by default when system Dark Mode is enabled.
2020-01-09 05:50:20 -05:00
90 changed files with 513 additions and 717 deletions

View File

@ -1,6 +1,24 @@
Changelog
=========
## Version 0.5.1
_2020-04-30_
* Add option to force server-side media scan
* Change to local artist sorting (case-insensitive)
* Fix crash while offline (#25)
* Fix read timeout not being respected
* Fix switching to playlist on app resume
## Version 0.5.0
_2020-01-15_
* Add 24kbps and 48kbps options
* Add adaptive icon
* Add support for p= authentication
* Change to MediaStyle playback notification
* Fix SSID selection
* Fix keyboard being visible when switching to now playing
* Fix now playing icon when using light theme
## Version 0.4.1
_2019-12-28_
* Revert attempt to fix infinite loop as it sometimes deleted valid files.

View File

@ -1,4 +1,11 @@
# Audinaut
⚠ No longer maintained.
Although not a direct replacement, I've since moved onto syncing an Opus version
of my entire library to my phone using [harmonize](https://github.com/nvllsvm/harmonize)
and [Syncthing](https://syncthing.net/).
---
<img src="audinaut.png" align="left" width="200" hspace="10" vspace="10">
A Subsonic client for Android.

View File

@ -2,23 +2,18 @@ apply plugin: 'com.android.application'
apply plugin: 'kotlin-android'
android {
compileSdkVersion 29
buildToolsVersion "29.0.2"
compileSdkVersion 31
buildToolsVersion "31.0.0"
defaultConfig {
applicationId "net.nullsum.audinaut"
minSdkVersion 21
targetSdkVersion 29
versionCode 200
versionName '0.4.1'
targetSdkVersion 30
versionCode 202
versionName '0.5.1'
setProperty("archivesBaseName", "Audinaut $versionName")
}
compileOptions {
sourceCompatibility JavaVersion.VERSION_1_8
targetCompatibility JavaVersion.VERSION_1_8
}
lintOptions {
checkReleaseBuilds false
warning 'InvalidPackage'
@ -31,14 +26,16 @@ android {
dependencies {
implementation 'com.esotericsoftware:kryo:4.0.2'
implementation 'com.google.android.material:material:1.0.0'
implementation 'com.github.hannesa2:AndroidSlidingUpPanel:4.1.0'
implementation 'com.squareup.okhttp3:okhttp:4.2.2'
implementation 'com.google.android.material:material:1.5.0'
implementation 'com.github.hannesa2:AndroidSlidingUpPanel:4.4.1'
implementation 'com.squareup.okhttp3:okhttp:4.9.3'
implementation "org.jetbrains.kotlin:kotlin-stdlib:$kotlin_version"
implementation "androidx.media:media:1.5.0"
implementation 'androidx.legacy:legacy-support-v4:1.0.0'
}
buildscript {
ext.kotlin_version = '1.3.61'
ext.kotlin_version = '1.6.0'
repositories {
mavenCentral()
}

View File

@ -13,6 +13,7 @@
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS" />
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE" />
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
@ -46,6 +47,7 @@
android:icon="@drawable/launch"
android:label="@string/common.appname"
android:usesCleartextTraffic="true"
android:networkSecurityConfig="@xml/network_security_config"
android:theme="@style/LaunchScreen">
<uses-library android:name="android.test.runner" />

View File

@ -65,10 +65,10 @@ public class QueryReceiverActivity extends AppCompatActivity {
intent.putExtra(Constants.INTENT_EXTRA_VIEW_ALBUM, true);
if (albumId.indexOf("ar-") == 0) {
intent.putExtra(Constants.INTENT_EXTRA_NAME_ARTIST, true);
albumId = albumId.replace("ar-", "");
albumId = albumId.replaceFirst("ar-", "");
} else if (albumId.indexOf("so-") == 0) {
intent.putExtra(Constants.INTENT_EXTRA_SEARCH_SONG, name);
albumId = albumId.replace("so-", "");
albumId = albumId.replaceFirst("so-", "");
}
intent.putExtra(Constants.INTENT_EXTRA_NAME_ID, albumId);
if (name != null) {

View File

@ -21,11 +21,10 @@ package net.nullsum.audinaut.activity;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.media.AudioManager;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.util.Log;
import android.view.LayoutInflater;
@ -68,8 +67,6 @@ import net.nullsum.audinaut.util.UserUtil;
import net.nullsum.audinaut.util.Util;
import net.nullsum.audinaut.view.UpdateView;
import java.io.File;
import java.io.PrintWriter;
import java.util.ArrayList;
import java.util.List;
@ -85,7 +82,13 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
private static ImageLoader IMAGE_LOADER;
static {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
// If Android Pie or older, set night mode by system clock
if (Build.VERSION.SDK_INT<29) {
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_AUTO);
} else {
// Else, for Android 10+, follow system dark mode setting
AppCompatDelegate.setDefaultNightMode(AppCompatDelegate.MODE_NIGHT_FOLLOW_SYSTEM);
}
}
final List<SubsonicFragment> backStack = new ArrayList<>();
@ -835,7 +838,6 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
}
Util.setActiveServer(this, instance);
invalidate();
UserUtil.refreshCurrentUser(this);
updateDrawerHeader();
}
}
@ -863,7 +865,6 @@ public class SubsonicActivity extends AppCompatActivity implements OnItemSelecte
service.setOnline(isOffline);
}
UserUtil.seedCurrentUser(this);
this.updateDrawerHeader();
drawer.closeDrawers();
}

View File

@ -37,8 +37,9 @@ import androidx.appcompat.widget.Toolbar;
import androidx.fragment.app.FragmentManager;
import androidx.fragment.app.FragmentTransaction;
import com.sothree.slidinguppanel.PanelSlideListener;
import com.sothree.slidinguppanel.PanelState;
import com.sothree.slidinguppanel.SlidingUpPanelLayout;
import com.sothree.slidinguppanel.SlidingUpPanelLayout.PanelState;
import net.nullsum.audinaut.R;
import net.nullsum.audinaut.domain.MusicDirectory;
@ -56,7 +57,6 @@ import net.nullsum.audinaut.updates.Updater;
import net.nullsum.audinaut.util.Constants;
import net.nullsum.audinaut.util.FileUtil;
import net.nullsum.audinaut.util.SilentBackgroundTask;
import net.nullsum.audinaut.util.UserUtil;
import net.nullsum.audinaut.util.Util;
import java.io.File;
@ -69,7 +69,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
private static boolean infoDialogDisplayed;
private static boolean sessionInitialized = false;
private SlidingUpPanelLayout slideUpPanel;
private SlidingUpPanelLayout.PanelSlideListener panelSlideListener;
private PanelSlideListener panelSlideListener;
private boolean isPanelClosing = false;
private boolean resuming = false;
private NowPlayingFragment nowPlayingFragment;
@ -168,9 +168,10 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
}
slideUpPanel = findViewById(R.id.slide_up_panel);
panelSlideListener = new SlidingUpPanelLayout.PanelSlideListener() {
panelSlideListener = new PanelSlideListener() {
@Override
public void onPanelSlide(View panel, float slideOffset) {
Util.hideKeyboard(panel);
}
@Override
@ -366,7 +367,6 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
getIntent().removeExtra(Constants.INTENT_EXTRA_VIEW_ALBUM);
}
UserUtil.seedCurrentUser(this);
createAccount();
runWhenServiceAvailable(() -> getDownloadService().addOnSongChangedListener(SubsonicFragmentActivity.this));
resuming = false;
@ -415,7 +415,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
drawerToggle.setDrawerIndicatorEnabled(false);
}
if (savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == SlidingUpPanelLayout.PanelState.EXPANDED.hashCode()) {
if (savedInstanceState.getInt(Constants.MAIN_SLIDE_PANEL_STATE, -1) == PanelState.EXPANDED.hashCode()) {
panelSlideListener.onPanelStateChanged(null, null, PanelState.EXPANDED);
}
}
@ -534,12 +534,12 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
@Override
public void openNowPlaying() {
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.EXPANDED);
slideUpPanel.setPanelState(PanelState.EXPANDED);
}
@Override
public void closeNowPlaying() {
slideUpPanel.setPanelState(SlidingUpPanelLayout.PanelState.COLLAPSED);
slideUpPanel.setPanelState(PanelState.COLLAPSED);
isPanelClosing = true;
}
@ -704,7 +704,7 @@ public class SubsonicFragmentActivity extends SubsonicActivity implements Downlo
getImageLoader().loadImage(coverArtView, song, false, height, false);
// We need to update it immediately since it won't update if updater is not running for it
if (nowPlayingFragment != null && slideUpPanel.getPanelState() == SlidingUpPanelLayout.PanelState.COLLAPSED) {
if (nowPlayingFragment != null && slideUpPanel.getPanelState() == PanelState.COLLAPSED) {
nowPlayingFragment.onMetadataUpdate(song, fieldChange);
}
}

View File

@ -17,17 +17,12 @@ package net.nullsum.audinaut.adapter;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Resources;
import android.os.Build;
import android.util.Log;
import android.util.TypedValue;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.view.View;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.widget.PopupMenu;
import androidx.appcompat.view.ActionMode;

View File

@ -17,7 +17,6 @@ package net.nullsum.audinaut.fragments;
import android.content.Intent;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.os.Handler;
import android.util.DisplayMetrics;
import android.view.GestureDetector;
import android.view.GestureDetector.OnGestureListener;
@ -57,17 +56,12 @@ import net.nullsum.audinaut.util.MenuUtil;
import net.nullsum.audinaut.util.SilentBackgroundTask;
import net.nullsum.audinaut.util.Util;
import net.nullsum.audinaut.view.AutoRepeatButton;
import net.nullsum.audinaut.view.FadeOutAnimation;
import net.nullsum.audinaut.view.FastScroller;
import net.nullsum.audinaut.view.UpdateView;
import java.util.ArrayList;
import java.util.LinkedList;
import java.util.List;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.ScheduledFuture;
import java.util.concurrent.TimeUnit;
import static net.nullsum.audinaut.domain.MusicDirectory.Entry;
import static net.nullsum.audinaut.domain.PlayerState.COMPLETED;
@ -105,11 +99,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
private ImageButton repeatButton;
private View toggleListButton;
private ScheduledExecutorService executorService;
private DownloadFile currentPlaying;
private int swipeDistance;
private int swipeVelocity;
private ScheduledFuture<?> hideControlsFuture;
private List<DownloadFile> songList;
private DownloadFileAdapter songListAdapter;
private boolean seekInProgress = false;
@ -201,7 +193,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
return null;
}
}.execute();
setControlsVisible(true);
});
previousButton.setOnRepeatListener(() -> changeProgress(true));
@ -214,7 +205,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
return true;
}
}.execute();
setControlsVisible(true);
});
nextButton.setOnRepeatListener(() -> changeProgress(false));
@ -269,12 +259,10 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
break;
}
updateRepeatButton();
setControlsVisible(true);
});
toggleListButton.setOnClickListener(view -> {
toggleFullscreenAlbumArt();
setControlsVisible(true);
});
View overlay = rootView.findViewById(R.id.download_overlay_buttons);
@ -308,7 +296,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
public void onProgressChanged(final SeekBar seekBar, final int position, final boolean fromUser) {
if (fromUser) {
positionTextView.setText(Util.formatDuration(position / 1000));
setControlsVisible(true);
}
}
});
@ -473,7 +460,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
if (controller != null) {
SubsonicFragment fragment = new EqualizerFragment();
replaceFragment(fragment);
setControlsVisible(true);
return true;
}
@ -510,19 +496,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
private void onResumeHandlers() {
executorService = Executors.newSingleThreadScheduledExecutor();
setControlsVisible(true);
final DownloadService downloadService = getDownloadService();
if (downloadService == null || downloadService.getCurrentPlaying() == null || startFlipped) {
playlistFlipper.setDisplayedChild(1);
startFlipped = false;
}
if (currentPlaying == null && downloadService != null && null == downloadService.getCurrentPlaying()) {
setAlbumArt(null, false);
}
context.runWhenServiceAvailable(() -> {
if (primaryFragment) {
DownloadService downloadService1 = getDownloadService();
@ -540,11 +513,9 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
}
private void onPauseHandlers() {
if (executorService != null) {
DownloadService downloadService = getDownloadService();
if (downloadService != null) {
downloadService.removeOnSongChangeListener(this);
}
DownloadService downloadService = getDownloadService();
if (downloadService != null) {
downloadService.removeOnSongChangeListener(this);
}
}
@ -581,29 +552,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
return songListAdapter;
}
private void scheduleHideControls() {
if (hideControlsFuture != null) {
hideControlsFuture.cancel(false);
}
final Handler handler = new Handler();
Runnable runnable = () -> handler.post(() -> setControlsVisible(false));
hideControlsFuture = executorService.schedule(runnable, 3000L, TimeUnit.MILLISECONDS);
}
private void setControlsVisible(boolean visible) {
try {
long duration = 1700L;
FadeOutAnimation.createAndStart(rootView.findViewById(R.id.download_overlay_buttons), !visible, duration);
if (visible) {
scheduleHideControls();
}
} catch (Exception ignored) {
}
}
// Scroll to current playing/downloading.
private void scrollToCurrent() {
if (getDownloadService() == null || songListAdapter == null) {
@ -693,7 +641,6 @@ public class NowPlayingFragment extends SubsonicFragment implements OnGestureLis
@Override
public boolean onDown(MotionEvent me) {
setControlsVisible(true);
return false;
}

View File

@ -169,7 +169,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
String musicFolderId = Util.getSelectedMusicFolderId(context);
Indexes indexes = musicService.getIndexes(musicFolderId, refresh, context, listener);
indexes.sortChildren(context);
indexes.sortChildren();
items = new ArrayList<>(indexes.getShortcuts().size() + indexes.getArtists().size());
items.addAll(indexes.getShortcuts());
items.addAll(indexes.getArtists());
@ -184,8 +184,7 @@ public class SelectArtistFragment extends SelectRecyclerFragment<Serializable> i
}
Indexes indexes = new Indexes();
//indexes.setArtists = artists;
indexes.sortChildren(context);
indexes.sortChildren();
items = new ArrayList<>(indexes.getArtists());
entries = dir.getChildren(false, true);

View File

@ -28,6 +28,7 @@ import android.preference.ListPreference;
import android.preference.Preference;
import android.preference.PreferenceCategory;
import android.preference.PreferenceScreen;
import android.preference.SwitchPreference;
import android.text.InputType;
import android.util.Log;
import android.view.View;
@ -469,6 +470,12 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
serverPasswordPreference.setSummary("***");
serverPasswordPreference.setTitle(R.string.settings_server_password);
final SwitchPreference authMethodPreference = new SwitchPreference(context);
authMethodPreference.setKey(Constants.PREFERENCES_KEY_AUTH_METHOD + instance);
authMethodPreference.setSummary(R.string.settings_auth_summary);
authMethodPreference.setDefaultValue(true); // use Token/Salt by default
authMethodPreference.setTitle(R.string.settings_auth_method);
final Preference serverOpenBrowser = new Preference(context);
serverOpenBrowser.setKey(Constants.PREFERENCES_KEY_OPEN_BROWSER);
serverOpenBrowser.setPersistent(false);
@ -523,13 +530,24 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
return false;
});
Preference serverStartScanPreference = new Preference(context);
serverStartScanPreference.setKey(Constants.PREFERENCES_KEY_START_SCAN + instance);
serverStartScanPreference.setPersistent(false);
serverStartScanPreference.setTitle(R.string.settings_start_scan_title);
serverStartScanPreference.setOnPreferenceClickListener(preference -> {
startScan(instance);
return false;
});
screen.addPreference(serverNamePreference);
screen.addPreference(serverUrlPreference);
screen.addPreference(serverInternalUrlPreference);
screen.addPreference(serverLocalNetworkSSIDPreference);
screen.addPreference(serverUsernamePreference);
screen.addPreference(serverPasswordPreference);
screen.addPreference(authMethodPreference);
screen.addPreference(serverTestConnectionPreference);
screen.addPreference(serverStartScanPreference);
screen.addPreference(serverOpenBrowser);
screen.addPreference(serverRemoveServerPreference);
@ -599,6 +617,42 @@ public class SettingsFragment extends PreferenceCompatFragment implements Shared
}
}
private void startScan(final int instance) {
LoadingTask<Boolean> task = new LoadingTask<Boolean>(context) {
@Override
protected Boolean doInBackground() throws Throwable {
MusicService musicService = MusicServiceFactory.getOnlineService();
try {
musicService.setInstance(instance);
musicService.startScan(context);
return true;
} finally {
musicService.setInstance(null);
}
}
@Override
protected void done(Boolean licenseValid) {
Log.d(TAG, "Finished media scan start");
Util.toast(context, R.string.settings_media_scan_started);
}
@Override
public void cancel() {
super.cancel();
}
@Override
protected void error(Throwable error) {
Log.w(TAG, error.toString(), error);
new ErrorDialog(context, getResources().getString(R.string.settings_media_scan_start_failed) +
" " + getErrorMessage(error), false);
}
};
task.execute();
}
private void testConnection(final int instance) {
LoadingTask<Boolean> task = new LoadingTask<Boolean>(context) {
private int previousInstance;

View File

@ -245,6 +245,10 @@ public class AudinautWidgetProvider extends AppWidgetProvider {
views.setImageViewResource(R.id.control_play, R.drawable.widget_media_start);
}
// Set next/back button images
views.setImageViewResource(R.id.control_next, R.drawable.widget_media_forward);
views.setImageViewResource(R.id.control_previous, R.drawable.widget_media_backward);
// Set the cover art
try {
boolean large = false;

View File

@ -24,21 +24,30 @@ import net.nullsum.audinaut.service.DownloadService;
import net.nullsum.audinaut.util.Constants;
public class PlayActionReceiver extends BroadcastReceiver {
private Bundle lastdata = null;
@Override
public void onReceive(Context context, Intent intent) {
if (lastdata.equals(intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE))) {
// nothing has changed; we can safely return
return;
}
updateValues(intent);
if (intent.hasExtra(Constants.TASKER_EXTRA_BUNDLE)) {
Bundle data = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
Boolean startShuffled = data.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE);
Boolean startShuffled = lastdata.getBoolean(Constants.INTENT_EXTRA_NAME_SHUFFLE);
Intent start = new Intent(context, DownloadService.class);
start.setAction(DownloadService.START_PLAY);
start.putExtra(Constants.INTENT_EXTRA_NAME_SHUFFLE, startShuffled);
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR));
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR));
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, data.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE));
start.putExtra(Constants.PREFERENCES_KEY_OFFLINE, data.getInt(Constants.PREFERENCES_KEY_OFFLINE));
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR, lastdata.getString(Constants.PREFERENCES_KEY_SHUFFLE_START_YEAR));
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR, lastdata.getString(Constants.PREFERENCES_KEY_SHUFFLE_END_YEAR));
start.putExtra(Constants.PREFERENCES_KEY_SHUFFLE_GENRE, lastdata.getString(Constants.PREFERENCES_KEY_SHUFFLE_GENRE));
start.putExtra(Constants.PREFERENCES_KEY_OFFLINE, lastdata.getInt(Constants.PREFERENCES_KEY_OFFLINE));
context.startService(start);
}
}
private void updateValues(Intent intent) {
lastdata = intent.getBundleExtra(Constants.TASKER_EXTRA_BUNDLE);
}
}

View File

@ -30,7 +30,6 @@ import net.nullsum.audinaut.domain.MusicFolder;
import net.nullsum.audinaut.domain.Playlist;
import net.nullsum.audinaut.domain.SearchCritera;
import net.nullsum.audinaut.domain.SearchResult;
import net.nullsum.audinaut.domain.User;
import net.nullsum.audinaut.util.FileUtil;
import net.nullsum.audinaut.util.ProgressListener;
import net.nullsum.audinaut.util.SilentBackgroundTask;
@ -617,21 +616,8 @@ public class CachedMusicService implements MusicService {
}
@Override
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) {
User result = null;
try {
result = musicService.getUser(refresh, username, context, progressListener);
FileUtil.serialize(context, result, getCacheName(context, "user-" + username));
} catch (Exception e) {
// Don't care
}
if (result == null && !refresh) {
result = FileUtil.deserialize(context, getCacheName(context, "user-" + username), User.class);
}
return result;
public void startScan(Context c) throws Exception {
musicService.startScan(c);
}
@Override

View File

@ -28,7 +28,6 @@ import net.nullsum.audinaut.domain.MusicFolder;
import net.nullsum.audinaut.domain.Playlist;
import net.nullsum.audinaut.domain.SearchCritera;
import net.nullsum.audinaut.domain.SearchResult;
import net.nullsum.audinaut.domain.User;
import net.nullsum.audinaut.util.ProgressListener;
import net.nullsum.audinaut.util.SilentBackgroundTask;
@ -87,7 +86,7 @@ public interface MusicService {
MusicDirectory getSongsByGenre(String genre, int count, int offset, Context context, ProgressListener progressListener) throws Exception;
User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception;
void startScan(Context c) throws Exception;
void setInstance(Integer instance) throws Exception;
}

View File

@ -31,7 +31,6 @@ import net.nullsum.audinaut.domain.MusicFolder;
import net.nullsum.audinaut.domain.Playlist;
import net.nullsum.audinaut.domain.SearchCritera;
import net.nullsum.audinaut.domain.SearchResult;
import net.nullsum.audinaut.domain.User;
import net.nullsum.audinaut.util.Constants;
import net.nullsum.audinaut.util.FileUtil;
import net.nullsum.audinaut.util.ProgressListener;
@ -70,6 +69,7 @@ public class OfflineMusicService implements MusicService {
public Indexes getIndexes(String musicFolderId, boolean refresh, Context context, ProgressListener progressListener) {
List<Artist> artists = new ArrayList<>();
List<Entry> entries = new ArrayList<>();
File root = FileUtil.getMusicDirectory(context);
for (File file : FileUtil.listFiles(root)) {
if (file.isDirectory()) {
@ -499,7 +499,7 @@ public class OfflineMusicService implements MusicService {
}
@Override
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception {
public void startScan(Context c) throws Exception {
throw new OfflineException();
}

View File

@ -25,6 +25,7 @@ import android.util.Log;
import androidx.annotation.Nullable;
import net.nullsum.audinaut.R;
import net.nullsum.audinaut.domain.Genre;
import net.nullsum.audinaut.domain.Indexes;
import net.nullsum.audinaut.domain.MusicDirectory;
@ -32,7 +33,6 @@ import net.nullsum.audinaut.domain.MusicFolder;
import net.nullsum.audinaut.domain.Playlist;
import net.nullsum.audinaut.domain.SearchCritera;
import net.nullsum.audinaut.domain.SearchResult;
import net.nullsum.audinaut.domain.User;
import net.nullsum.audinaut.fragments.MainFragment;
import net.nullsum.audinaut.service.parser.EntryListParser;
import net.nullsum.audinaut.service.parser.ErrorParser;
@ -44,7 +44,6 @@ import net.nullsum.audinaut.service.parser.PlaylistParser;
import net.nullsum.audinaut.service.parser.PlaylistsParser;
import net.nullsum.audinaut.service.parser.RandomSongsParser;
import net.nullsum.audinaut.service.parser.SearchResult2Parser;
import net.nullsum.audinaut.service.parser.UserParser;
import net.nullsum.audinaut.util.Constants;
import net.nullsum.audinaut.util.FileUtil;
import net.nullsum.audinaut.util.Pair;
@ -591,7 +590,7 @@ public class RESTMusicService implements MusicService {
public Response getDownloadInputStream(Context context, MusicDirectory.Entry song, long offset, int maxBitrate, SilentBackgroundTask task) throws Exception {
OkHttpClient eagerClient = client.newBuilder()
.readTimeout(30, TimeUnit.SECONDS)
.readTimeout(Util.getNetworkTimeoutMs(context), TimeUnit.MILLISECONDS)
.build();
Map<String, String> parameters = new HashMap<>();
@ -656,24 +655,17 @@ public class RESTMusicService implements MusicService {
}
@Override
public User getUser(boolean refresh, String username, Context context, ProgressListener progressListener) throws Exception {
Map<String, String> parameters = new HashMap<>();
public void startScan(Context context) throws Exception {
String url = getRestUrl(context, "startScan", null);
parameters.put("username", username);
String url = getRestUrl(context, "getUser", parameters);
Request request = new Request.Builder()
.url(url)
.build();
Request request = new Request.Builder().url(url).build();
try (Response response = client.newCall(request).execute()) {
List<User> users = new UserParser(context, getInstance(context)).parse(response.body().byteStream());
if (users.size() > 0) {
// Should only have returned one anyways
return users.get(0);
if (response.isSuccessful()) {
Log.d(TAG, "Media scan started" + response.toString());
} else {
return null;
Log.w(TAG, "media scan start failed" + response.toString());
Util.toast(context, R.string.settings_media_scan_start_failed);
}
}
}

View File

@ -3,7 +3,6 @@ package net.nullsum.audinaut.util;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.ColorMatrix;
import android.graphics.ColorMatrixColorFilter;
import android.graphics.Paint;

View File

@ -67,10 +67,12 @@ public final class Constants {
public static final String PREFERENCES_KEY_SERVER_INTERNAL_URL = "serverInternalUrl";
public static final String PREFERENCES_KEY_SERVER_LOCAL_NETWORK_SSID = "serverLocalNetworkSSID";
public static final String PREFERENCES_KEY_TEST_CONNECTION = "serverTestConnection";
public static final String PREFERENCES_KEY_START_SCAN = "serverStartScan";
public static final String PREFERENCES_KEY_OPEN_BROWSER = "openBrowser";
public static final String PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId";
public static final String PREFERENCES_KEY_USERNAME = "username";
public static final String PREFERENCES_KEY_PASSWORD = "password";
public static final String PREFERENCES_KEY_AUTH_METHOD = "authMethod";
public static final String PREFERENCES_KEY_THEME = "theme";
public static final String PREFERENCES_KEY_FULL_SCREEN = "fullScreen";
public static final String PREFERENCES_KEY_DISPLAY_TRACK = "displayTrack";

View File

@ -23,14 +23,16 @@ import android.content.ComponentName;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.os.Build;
import android.os.Handler;
import android.support.v4.media.MediaMetadataCompat;
import android.support.v4.media.session.MediaSessionCompat;
import android.util.Log;
import android.view.KeyEvent;
import android.view.View;
import android.widget.RemoteViews;
import androidx.core.app.NotificationCompat;
import androidx.media.app.NotificationCompat.MediaStyle;
import net.nullsum.audinaut.R;
import net.nullsum.audinaut.activity.SubsonicActivity;
@ -67,28 +69,52 @@ public final class Notifications {
}
final boolean playing = downloadService.getPlayerState() == PlayerState.STARTED;
RemoteViews expandedContentView = new RemoteViews(context.getPackageName(), R.layout.notification_expanded);
setupViews(expandedContentView, context, song, true, playing);
RemoteViews smallContentView = new RemoteViews(context.getPackageName(), R.layout.notification);
setupViews(smallContentView, context, song, false, playing);
Intent notificationIntent = new Intent(context, SubsonicFragmentActivity.class);
notificationIntent.putExtra(Constants.INTENT_EXTRA_NAME_DOWNLOAD, true);
notificationIntent.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
final Notification notification = new NotificationCompat.Builder(context, CHANNEL_PLAYING_ID)
Intent cancelIntent = new Intent("KEYCODE_MEDIA_STOP")
.setComponent(new ComponentName(context, DownloadService.class))
.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
int[] compactActions = new int[]{0, 1, 2};
MediaSessionCompat mediaSession = new MediaSessionCompat(context, "Audinaut");
MediaSessionCompat.Token mediaToken = mediaSession.getSessionToken();
MediaMetadataCompat.Builder metadataBuilder = new MediaMetadataCompat.Builder();
mediaSession.setMetadata(metadataBuilder
.putLong(MediaMetadataCompat.METADATA_KEY_DURATION, -1)
.putBitmap(MediaMetadataCompat.METADATA_KEY_ALBUM_ART, getAlbumArt(context, song))
//.putBitmap(MediaMetadataCompat.METADATA_KEY_DISPLAY_ICON, R.drawable.notification_logo)
.putString(MediaMetadataCompat.METADATA_KEY_TITLE, song.getTitle())
.putString(MediaMetadataCompat.METADATA_KEY_ARTIST, song.getArtist())
.build() );
MediaStyle mediaStyle = new MediaStyle()
.setShowActionsInCompactView(compactActions)
.setShowCancelButton(true)
.setCancelButtonIntent(PendingIntent.getService(context, 0, cancelIntent, 0))
.setMediaSession(mediaToken);
NotificationCompat.Builder builder = new NotificationCompat.Builder(context, CHANNEL_PLAYING_ID)
.setChannelId(CHANNEL_PLAYING_ID)
.setSmallIcon(R.drawable.stat_notify_playing)
.setContentTitle(song.getTitle())
.setContentText(song.getTitle())
.setContentText(song.getArtist())
.setSubText(song.getAlbum())
.setTicker(song.getTitle())
.setOngoing(playing)
.setVisibility(Notification.VISIBILITY_PUBLIC)
.setCustomContentView(smallContentView)
.setCustomBigContentView(expandedContentView)
.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, 0))
.setPriority(NotificationCompat.PRIORITY_LOW).build();
.setVisibility(NotificationCompat.VISIBILITY_PUBLIC)
.setShowWhen(false)
.setLargeIcon(getAlbumArt(context, song))
.setSmallIcon(R.drawable.notification_logo)
.setStyle(mediaStyle)
.setContentIntent(PendingIntent.getActivity(context, 0, notificationIntent, 0));
addActions(context, builder, playing);
final Notification notification = builder.build();
if(playing) {
notification.flags |= Notification.FLAG_NO_CLEAR | Notification.FLAG_ONGOING_EVENT;
}
playShowing = true;
if (downloadForeground && downloadShowing) {
@ -116,13 +142,7 @@ public final class Notifications {
AudinautWidgetProvider.notifyInstances(context, downloadService, playing);
}
private static void setupViews(RemoteViews rv, Context context, MusicDirectory.Entry song, boolean expanded, boolean playing) {
// Use the same text for the ticker and the expanded notification
String title = song.getTitle();
String arist = song.getArtist();
String album = song.getAlbum();
// Set the album art.
private static Bitmap getAlbumArt(Context context, MusicDirectory.Entry song) {
try {
ImageLoader imageLoader = SubsonicActivity.getStaticImageLoader(context);
Bitmap bitmap = null;
@ -131,90 +151,42 @@ public final class Notifications {
}
if (bitmap == null) {
// set default album art
rv.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
return BitmapFactory.decodeResource(context.getResources(), R.drawable.unknown_album);
} else {
imageLoader.setNowPlayingSmall(bitmap);
rv.setImageViewBitmap(R.id.notification_image, bitmap);
return bitmap;
}
} catch (Exception x) {
Log.w(TAG, "Failed to get notification cover art", x);
rv.setImageViewResource(R.id.notification_image, R.drawable.unknown_album);
return BitmapFactory.decodeResource(context.getResources(), R.drawable.unknown_album);
}
}
// set the text for the notifications
rv.setTextViewText(R.id.notification_title, title);
rv.setTextViewText(R.id.notification_artist, arist);
rv.setTextViewText(R.id.notification_album, album);
boolean persistent = Util.getPreferences(context).getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false);
if (persistent) {
if (expanded) {
rv.setImageViewResource(R.id.control_pause, playing ? R.drawable.notification_media_pause : R.drawable.notification_media_start);
rv.setImageViewResource(R.id.control_previous, R.drawable.notification_media_backward);
rv.setImageViewResource(R.id.control_next, R.drawable.notification_media_forward);
} else {
rv.setImageViewResource(R.id.control_previous, playing ? R.drawable.notification_media_pause : R.drawable.notification_media_start);
rv.setImageViewResource(R.id.control_pause, R.drawable.notification_media_forward);
rv.setImageViewResource(R.id.control_next, R.drawable.notification_close);
}
} else {
// Necessary for switching back since it appears to re-use the same layout
rv.setImageViewResource(R.id.control_previous, R.drawable.notification_media_backward);
rv.setImageViewResource(R.id.control_pause, R.drawable.notification_media_pause);
rv.setImageViewResource(R.id.control_next, R.drawable.notification_media_forward);
}
// Create actions for media buttons
private static void addActions(final Context context, final NotificationCompat.Builder builder, final boolean playing) {
PendingIntent pendingIntent;
int previous = 0, pause, next, close = 0;
if (persistent && !expanded) {
pause = R.id.control_previous;
next = R.id.control_pause;
close = R.id.control_next;
} else {
previous = R.id.control_previous;
pause = R.id.control_pause;
next = R.id.control_next;
}
if (persistent && close == 0 && expanded) {
close = R.id.notification_close;
rv.setViewVisibility(close, View.VISIBLE);
}
if (previous > 0) {
Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
rv.setOnClickPendingIntent(previous, pendingIntent);
}
Intent prevIntent = new Intent("KEYCODE_MEDIA_PREVIOUS");
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PREVIOUS));
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
builder.addAction(R.drawable.notification_media_backward, "Previous", pendingIntent);
if (playing) {
Intent pauseIntent = new Intent("KEYCODE_MEDIA_PLAY_PAUSE");
pauseIntent.setComponent(new ComponentName(context, DownloadService.class));
pauseIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY_PAUSE));
pendingIntent = PendingIntent.getService(context, 0, pauseIntent, 0);
rv.setOnClickPendingIntent(pause, pendingIntent);
builder.addAction(R.drawable.notification_media_pause, "Pause", pendingIntent);
} else {
Intent prevIntent = new Intent("KEYCODE_MEDIA_START");
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
rv.setOnClickPendingIntent(pause, pendingIntent);
Intent playIntent = new Intent("KEYCODE_MEDIA_PLAY");
playIntent.setComponent(new ComponentName(context, DownloadService.class));
playIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_PLAY));
pendingIntent = PendingIntent.getService(context, 0, playIntent, 0);
builder.addAction(R.drawable.notification_media_start, "Play", pendingIntent);
}
Intent nextIntent = new Intent("KEYCODE_MEDIA_NEXT");
nextIntent.setComponent(new ComponentName(context, DownloadService.class));
nextIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_NEXT));
pendingIntent = PendingIntent.getService(context, 0, nextIntent, 0);
rv.setOnClickPendingIntent(next, pendingIntent);
if (close > 0) {
Intent prevIntent = new Intent("KEYCODE_MEDIA_STOP");
prevIntent.setComponent(new ComponentName(context, DownloadService.class));
prevIntent.putExtra(Intent.EXTRA_KEY_EVENT, new KeyEvent(KeyEvent.ACTION_UP, KeyEvent.KEYCODE_MEDIA_STOP));
pendingIntent = PendingIntent.getService(context, 0, prevIntent, 0);
rv.setOnClickPendingIntent(close, pendingIntent);
}
builder.addAction(R.drawable.notification_media_forward, "Next", pendingIntent);
}
public static void hidePlayingNotification(final Context context, final DownloadService downloadService, Handler handler) {

View File

@ -18,10 +18,9 @@ package net.nullsum.audinaut.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.content.res.Configuration;
import android.os.Build;
import net.nullsum.audinaut.R;
import net.nullsum.audinaut.activity.SettingsActivity;
import net.nullsum.audinaut.activity.SubsonicFragmentActivity;
public final class ThemeUtil {
private static final String THEME_DARK = "dark";
@ -32,7 +31,15 @@ public final class ThemeUtil {
public static String getTheme(Context context) {
SharedPreferences prefs = Util.getPreferences(context);
String theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, null);
String theme;
if (Build.VERSION.SDK_INT<29) {
// If Android Pie or older, default to null (handled below as light)
theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, null);
} else {
// Else, for Android 10+, default to follow system dark mode setting
theme = prefs.getString(Constants.PREFERENCES_KEY_THEME, THEME_DAY_NIGHT);
}
if (THEME_DAY_NIGHT.equals(theme)) {
int currentNightMode = context.getResources().getConfiguration().uiMode & Configuration.UI_MODE_NIGHT_MASK;
@ -58,6 +65,9 @@ public final class ThemeUtil {
}
private static int getThemeRes(Context context, String theme) {
if(theme == null)
return R.style.Theme_Audinaut_Light;
switch (theme) {
case THEME_DARK:
return R.style.Theme_Audinaut_Dark;

View File

@ -17,63 +17,8 @@ package net.nullsum.audinaut.util;
import android.content.Context;
import android.content.SharedPreferences;
import android.util.Log;
import androidx.appcompat.app.AppCompatActivity;
import net.nullsum.audinaut.domain.User;
import net.nullsum.audinaut.service.MusicServiceFactory;
public final class UserUtil {
private static final String TAG = UserUtil.class.getSimpleName();
private static int instance = -1;
private static int instanceHash = -1;
private static User currentUser;
public static void refreshCurrentUser(Context context) {
currentUser = null;
seedCurrentUser(context);
}
public static void seedCurrentUser(Context context) {
// Only try to seed if online
if (Util.isOffline(context)) {
currentUser = null;
return;
}
final int instance = Util.getActiveServer(context);
final int instanceHash = (instance == 0) ? 0 : Util.getRestUrl(context).hashCode();
if (UserUtil.instance == instance && UserUtil.instanceHash == instanceHash && currentUser != null) {
return;
} else {
UserUtil.instance = instance;
UserUtil.instanceHash = instanceHash;
}
new SilentBackgroundTask<Void>(context) {
@Override
protected Void doInBackground() throws Throwable {
currentUser = MusicServiceFactory.getMusicService(context).getUser(false, getCurrentUsername(context, instance), context, null);
return null;
}
@Override
protected void done(Void result) {
if (context instanceof AppCompatActivity) {
((AppCompatActivity) context).supportInvalidateOptionsMenu();
}
}
@Override
protected void error(Throwable error) {
// Don't do anything, supposed to be background pull
Log.e(TAG, "Failed to seed user information");
}
}.execute();
}
private static String getCurrentUsername(Context context, int instance) {
SharedPreferences prefs = Util.getPreferences(context);
return prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);

View File

@ -41,6 +41,8 @@ import android.text.util.Linkify;
import android.util.Log;
import android.util.SparseArray;
import android.view.Gravity;
import android.view.View;
import android.view.inputmethod.InputMethodManager;
import android.widget.ListView;
import android.widget.TextView;
import android.widget.Toast;
@ -119,6 +121,11 @@ public final class Util {
editor.apply();
}
public static int getNetworkTimeoutMs(Context context) {
SharedPreferences prefs = getPreferences(context);
return Integer.parseInt(prefs.getString(Constants.PREFERENCES_KEY_NETWORK_TIMEOUT, "30000"));
}
public static boolean isScreenLitOnDownload(Context context) {
SharedPreferences prefs = getPreferences(context);
return prefs.getBoolean(Constants.PREFERENCES_KEY_SCREEN_LIT_ON_DOWNLOAD, false);
@ -298,6 +305,8 @@ public final class Util {
private static String getRestUrl(Context context, String method, SharedPreferences prefs, int instance, boolean allowAltAddress, @Nullable Map<String, String> parameters) {
String serverUrl = prefs.getString(Constants.PREFERENCES_KEY_SERVER_URL + instance, null);
if (serverUrl == null) return "OFFLINE";
HttpUrl.Builder builder;
builder = HttpUrl.parse(serverUrl).newBuilder();
@ -323,18 +332,24 @@ public final class Util {
builder.addPathSegment("rest");
builder.addPathSegment(method + ".view");
int hash = (username + password).hashCode();
Pair<String, String> values = tokens.get(hash);
if (values == null) {
String salt = new BigInteger(130, getRandom()).toString(32);
String token = md5Hex(password + salt);
values = new Pair<>(salt, token);
tokens.put(hash, values);
builder.addQueryParameter("u", username);
if (prefs.getBoolean(Constants.PREFERENCES_KEY_AUTH_METHOD + instance, true)) {
int hash = (username + password).hashCode();
Pair<String, String> values = tokens.get(hash);
if (values == null) {
String salt = new BigInteger(130, getRandom()).toString(32);
String token = md5Hex(password + salt);
values = new Pair<>(salt, token);
tokens.put(hash, values);
}
builder.addQueryParameter("s", values.getFirst());
builder.addQueryParameter("t", values.getSecond());
} else {
builder.addQueryParameter("p", password);
}
builder.addQueryParameter("u", username);
builder.addQueryParameter("s", values.getFirst());
builder.addQueryParameter("t", values.getSecond());
builder.addQueryParameter("v", Constants.REST_PROTOCOL_VERSION_SUBSONIC);
builder.addQueryParameter("c", Constants.REST_CLIENT_ID);
@ -1135,4 +1150,10 @@ public final class Util {
return random;
}
public static void hideKeyboard(View view) {
InputMethodManager imm = (InputMethodManager) view.getContext().getSystemService(AppCompatActivity.INPUT_METHOD_SERVICE);
imm.hideSoftInputFromWindow(view.getWindowToken(), 0);
}
}

View File

@ -46,7 +46,7 @@ public class RecyclingImageView extends AppCompatImageView {
if (drawable instanceof BitmapDrawable) {
if (isBitmapRecycled(drawable)) {
this.setImageDrawable(null);
setInvalidated(true);
this.invalidated = true;
}
} else if (drawable instanceof TransitionDrawable) {
TransitionDrawable transitionDrawable = (TransitionDrawable) drawable;

View File

@ -1,11 +1,15 @@
package net.nullsum.audinaut.domain
import android.content.Context
import java.io.Serializable
import java.util.*
class Indexes(var shortcuts: MutableList<Artist> = mutableListOf(),
var artists: MutableList<Artist> = mutableListOf(),
var entries: MutableList<MusicDirectory.Entry> = mutableListOf()) : Serializable {
fun sortChildren(context: Context) {
fun sortChildren() {
shortcuts.sortBy { s -> s.id.toLowerCase(Locale.ROOT) }
artists.sortBy { a -> a.name.toLowerCase(Locale.ROOT) }
entries.sortBy { e -> e.artist.toLowerCase(Locale.ROOT) }
}
}

View File

@ -0,0 +1,5 @@
<adaptive-icon
xmlns:android="http://schemas.android.com/apk/res/android">
<background android:drawable="@drawable/ic_launcher_background"/>
<foreground android:drawable="@drawable/ic_launcher_foreground" />
</adaptive-icon>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

After

Width:  |  Height:  |  Size: 2.8 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 349 B

After

Width:  |  Height:  |  Size: 343 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 35 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 7.3 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<size android:width="1dip" />
<solid android:color="@android:color/darker_gray" />
</shape>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/lightElement" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/lightElement" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
</vector>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 18 KiB

After

Width:  |  Height:  |  Size: 18 KiB

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M19,9h-4V3H9v6H5l7,7 7,-7zM5,18v2h14v-2H5z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M6,6h2v12L6,18zM9.5,12l8.5,6L18,6z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M6,18l8.5,-6L6,6v12zM16,6v12h2V6h-2z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M6,19h4L10,5L6,5v14zM14,5v14h4L18,5h-4z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M11,18L11,6l-8.5,6 8.5,6zM11.5,12l8.5,6L20,6l-8.5,6z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M8,5v14l11,-7z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M6,6h12v12H6z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M3.24,6.15C2.51,6.43 2,7.17 2,8v12c0,1.1 0.89,2 2,2h16c1.11,0 2,-0.9 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2L8.3,6l8.26,-3.34L15.88,1 3.24,6.15zM7,20c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM20,12h-2v-2h-2v2L4,12L4,8h16v4z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/actionbar_element_color" android:pathData="M10.59,9.17L5.41,4 4,5.41l5.17,5.17 1.42,-1.41zM14.5,4l2.04,2.04L4,18.59 5.41,20 17.96,7.46 20,9.5L20,4h-5.5zM14.83,13.41l-1.41,1.41 3.13,3.13L14.5,20L20,20v-5.5l-2.04,2.04 -3.13,-3.13z"/>
</vector>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@color/background_material_dark" />
<corners android:radius="@dimen/Card.Radius" />
<padding
android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip" />
</shape>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/black" />
<corners android:radius="@dimen/Card.Radius" />
<padding
android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip" />
</shape>

View File

@ -1,10 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<shape xmlns:android="http://schemas.android.com/apk/res/android">
<solid android:color="@android:color/white" />
<corners android:radius="@dimen/Card.Radius" />
<padding
android:bottom="0dip"
android:left="0dip"
android:right="0dip"
android:top="0dip" />
</shape>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/darkElement" android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/darkElement" android:pathData="M11.99,2C6.47,2 2,6.48 2,12s4.47,10 9.99,10C17.52,22 22,17.52 22,12S17.52,2 11.99,2zM12,20c-4.42,0 -8,-3.58 -8,-8s3.58,-8 8,-8 8,3.58 8,8 -3.58,8 -8,8zM12.5,7H11v6l5.25,3.15 0.75,-1.23 -4.5,-2.67z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M15,3L6,3c-0.83,0 -1.54,0.5 -1.84,1.22l-3.02,7.05c-0.09,0.23 -0.14,0.47 -0.14,0.73v1.91l0.01,0.01L1,14c0,1.1 0.9,2 2,2h6.31l-0.95,4.57 -0.03,0.32c0,0.41 0.17,0.79 0.44,1.06L9.83,23l6.59,-6.59c0.36,-0.36 0.58,-0.86 0.58,-1.41L17,5c0,-1.1 -0.9,-2 -2,-2zM19,3v12h4L23,3h-4z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M15,3L6,3c-0.83,0 -1.54,0.5 -1.84,1.22l-3.02,7.05c-0.09,0.23 -0.14,0.47 -0.14,0.73v1.91l0.01,0.01L1,14c0,1.1 0.9,2 2,2h6.31l-0.95,4.57 -0.03,0.32c0,0.41 0.17,0.79 0.44,1.06L9.83,23l6.59,-6.59c0.36,-0.36 0.58,-0.86 0.58,-1.41L17,5c0,-1.1 -0.9,-2 -2,-2zM19,3v12h4L23,3h-4z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-1.91l-0.01,-0.01L23,10z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M1,21h4L5,9L1,9v12zM23,10c0,-1.1 -0.9,-2 -2,-2h-6.31l0.95,-4.57 0.03,-0.32c0,-0.41 -0.17,-0.79 -0.44,-1.06L14.17,1 7.59,7.59C7.22,7.95 7,8.45 7,9v10c0,1.1 0.9,2 2,2h9c0.83,0 1.54,-0.5 1.84,-1.22l3.02,-7.05c0.09,-0.23 0.14,-0.47 0.14,-0.73v-1.91l-0.01,-0.01L23,10z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,3v10.55c-0.59,-0.34 -1.27,-0.55 -2,-0.55 -2.21,0 -4,1.79 -4,4s1.79,4 4,4 4,-1.79 4,-4V7h4V3h-6z"/>
</vector>

View File

@ -0,0 +1,9 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="108dp"
android:height="108dp"
android:viewportWidth="48.0"
android:viewportHeight="48.0">
<path
android:fillColor="#3F3F3F"
android:pathData="M0,0 l 0,-100 100,100 0,0 -100,100z" />
</vector>

View File

@ -0,0 +1,184 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android" xmlns:aapt="http://schemas.android.com/aapt"
android:viewportWidth="590.5714"
android:viewportHeight="590.5714"
android:width="590.5714dp"
android:height="590.5714dp">
<group
android:translateX="-82.92544"
android:translateY="-164.7266">
<group
android:scaleX="0.6475929"
android:scaleY="0.6468909"
android:translateX="148.4574"
android:translateY="176.1372">
<clip-path
android:pathData="M226.37425 605.31463L578.5552 898.41451 815.86565 898.59552 814.7542 566.66728 403.02131 236.4829C258.46412 375.28405 223.29168 363.17172 252.15774 479.26269Z" />
<path
android:pathData="M249.6397 165.7266H697.3483A165.7143 165.7143 0 0 1 863.0626 331.4409V777.1119A165.7143 165.7143 0 0 1 697.3483 942.8262H249.6397A165.7143 165.7143 0 0 1 83.92544 777.1119V331.4409A165.7143 165.7143 0 0 1 249.6397 165.7266Z">
<aapt:attr
name="android:fillColor">
<gradient
android:startX="116.0774"
android:startY="243.6558"
android:endX="601.3173"
android:endY="689.3493"
android:tileMode="clamp">
<item
android:color="#77000000"
android:offset="0" />
<item
android:color="#00000000"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
</group>
<path
android:pathData="M331.62492 552.7354c0.72527 -15.24559 14.13826 -34.3497 26.05629 -45.50156 3.40059 18.08281 -2.90069 -13.669 17.31711 60.04752 21.02632 -65.64317 12.62531 -7.02152 24.01543 -58.59228 5.88355 -18.08321 14.10692 11.92488 21.20653 38.40148 40.60438 -54.45752 19.35837 -68.73406 30.4072 -97.83931l-122.65619 -8.56713 -20.26856 37.61178c8.86185 31.34374 13.36152 31.6047 23.92219 74.4395z"
android:fillType="evenOdd"
android:strokeColor="#D0B0B0"
android:strokeWidth="0.5397026">
<aapt:attr
name="android:fillColor">
<gradient
android:startX="372.3981"
android:startY="459.9542"
android:endX="374.6396"
android:endY="647.8042"
android:tileMode="clamp">
<item
android:color="#C83D00"
android:offset="0" />
<item
android:color="#FFFFFF"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M327.02744 492.83652l11.39671 27.80674c6.79448 -10.33546 8.27016 -36.53845 18.79995 -42.39154 4.75016 22.51793 16.67487 45.33845 20.77813 63.04779 8.76249 -23.32953 14.06952 -67.27625 24.62406 -60.07173 12.47 5.64487 22.66228 33.95061 17.85786 43.41171 -0.36026 0.70945 35.97493 -32.83724 35.67943 -34.61028 -0.29551 -1.77303 -54.66862 -56.88491 -57.47592 -58.21469 -2.80731 -1.32977 -72.39899 1.77304 -72.39899 1.77304l-22.16295 39.0068z"
android:fillType="evenOdd"
android:strokeColor="#DEA369"
android:strokeWidth="0.5397026">
<aapt:attr
name="android:fillColor">
<gradient
android:startX="373.7826"
android:startY="457.2065"
android:endX="376.2011"
android:endY="575.4747"
android:tileMode="clamp">
<item
android:color="#D0BF40"
android:offset="0" />
<item
android:color="#FE4732"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
<path
android:pathData="M326.27022 455.5126c8.77351 -0.49739 14.82934 48.41956 21.22148 22.83644 5.80358 -23.22752 31.21007 10.70757 32.13581 31.47907 -2.31737 -36.26359 19.4236 -64.78742 30.87794 -41.70038 31.76438 64.02339 11.22662 -7.2515 28.66653 -8.53564 -1.62528 -2.65955 -57.47593 -48.31523 -73.2855 -47.13321 -15.80957 1.18202 -39.61626 43.05372 -39.61626 43.05372z"
android:fillType="evenOdd"
android:strokeColor="#C1AB34"
android:strokeWidth="0.5397026">
<aapt:attr
name="android:fillColor">
<gradient
android:startX="374.4492"
android:startY="448.3223"
android:endX="380.7424"
android:endY="541.3069"
android:tileMode="clamp">
<item
android:color="#FFFD93"
android:offset="0" />
<item
android:color="#FF7D13"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
<group
android:scaleX="0.5397026"
android:scaleY="0.5397026"
android:translateX="167.3064"
android:translateY="192.7248">
<path
android:pathData="M393.65234 238.15234c-96.76642 -1.43358 -195.7063 134.17501 -186.63867 413.01563 58.19797 133.75726 33.29955 -86.18552 79.46875 -153.75391 22.24905 -32.56135 165.71666 -29.49247 183.60156 -6.66211 75.47168 96.3408 29.83239 302.6978 97.16016 156.63867 17.76663 -269.32857 -76.82538 -407.8047 -173.5918 -409.23828z"
android:fillType="evenOdd"
android:strokeColor="#F5F5F5"
android:strokeWidth="4">
<aapt:attr
name="android:fillColor">
<gradient
android:startX="387.6964"
android:startY="771.4392"
android:endX="389.097"
android:endY="147.1536"
android:tileMode="clamp">
<item
android:color="#267797"
android:offset="0" />
<item
android:color="#A77797"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
</group>
<group
android:scaleX="0.5397026"
android:scaleY="0.5397026"
android:translateX="167.2811"
android:translateY="192.7248">
<clip-path
android:pathData="M295.66887 424.96942l62.04175 53.59779 191.5675 31.59449 1.08845 -85.47437L431.99745 300.28404 313.90043 407.19752Z" />
<path
android:pathData="M393.65234 238.15234c-96.76642 -1.43358 -195.7063 134.17501 -186.63867 413.01563 58.19797 133.75726 33.29955 -86.18552 79.46875 -153.75391 22.24905 -32.56135 165.71666 -29.49247 183.60156 -6.66211 75.47168 96.3408 29.83239 302.6978 97.16016 156.63867 17.76663 -269.32857 -76.82538 -407.8047 -173.5918 -409.23828z"
android:fillType="evenOdd"
android:strokeColor="#F5F5F5"
android:strokeAlpha="0.232"
android:strokeWidth="4">
<aapt:attr
name="android:fillColor">
<gradient
android:startX="294.0023"
android:startY="324.6501"
android:endX="517.636"
android:endY="480.116"
android:tileMode="clamp">
<item
android:color="#3B000000"
android:offset="0" />
<item
android:color="#00000000"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
</group>
<path
android:pathData="M328.178 420.70284c38.22209 -5.6969 41.4239 -10.23485 100.5871 1.67162 -17.23601 -102.43063 -84.93377 -94.98395 -100.5871 -1.67162z"
android:fillType="evenOdd"
android:strokeColor="#F1F1F1"
android:strokeWidth="2.15881">
<aapt:attr
name="android:fillColor">
<gradient
android:startX="351.1998"
android:startY="341.9985"
android:endX="415.4821"
android:endY="379.1636"
android:tileMode="clamp">
<item
android:color="#9FA5D4"
android:offset="0" />
<item
android:color="#A2C6DB"
android:offset="1" />
</gradient>
</aapt:attr>
</path>
</group>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M16.5,12c1.38,0 2.49,-1.12 2.49,-2.5S17.88,7 16.5,7C15.12,7 14,8.12 14,9.5s1.12,2.5 2.5,2.5zM9,11c1.66,0 2.99,-1.34 2.99,-3S10.66,5 9,5C7.34,5 6,6.34 6,8s1.34,3 3,3zM16.5,14c-1.83,0 -5.5,0.92 -5.5,2.75L11,19h11v-2.25c0,-1.83 -3.67,-2.75 -5.5,-2.75zM9,13c-2.33,0 -7,1.17 -7,3.5L2,19h7v-2.25c0,-0.85 0.33,-2.34 2.37,-3.47C10.5,13.1 9.66,13 9,13z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M17,3H7c-1.1,0 -1.99,0.9 -1.99,2L5,21l7,-3 7,3V5c0,-1.1 -0.9,-2 -2,-2z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M20,2L4,2c-1.1,0 -1.99,0.9 -1.99,2L2,22l4,-4h14c1.1,0 2,-0.9 2,-2L22,4c0,-1.1 -0.9,-2 -2,-2zM6,9h12v2L6,11L6,9zM14,14L6,14v-2h8v2zM18,8L6,8L6,6h12v2z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M2.01,21L23,12 2.01,3 2,10l15,2 -15,2z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M12,1c-4.97,0 -9,4.03 -9,9v7c0,1.66 1.34,3 3,3h3v-8H5v-2c0,-3.87 3.13,-7 7,-7s7,3.13 7,7v2h-4v8h3c1.66,0 3,-1.34 3,-3v-7c0,-4.97 -4.03,-9 -9,-9z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M3.24,6.15C2.51,6.43 2,7.17 2,8v12c0,1.1 0.89,2 2,2h16c1.11,0 2,-0.9 2,-2L22,8c0,-1.11 -0.89,-2 -2,-2L8.3,6l8.26,-3.34L15.88,1 3.24,6.15zM7,20c-1.66,0 -3,-1.34 -3,-3s1.34,-3 3,-3 3,1.34 3,3 -1.34,3 -3,3zM20,12h-2v-2h-2v2L4,12L4,8h16v4z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M18,16.08c-0.76,0 -1.44,0.3 -1.96,0.77L8.91,12.7c0.05,-0.23 0.09,-0.46 0.09,-0.7s-0.04,-0.47 -0.09,-0.7l7.05,-4.11c0.54,0.5 1.25,0.81 2.04,0.81 1.66,0 3,-1.34 3,-3s-1.34,-3 -3,-3 -3,1.34 -3,3c0,0.24 0.04,0.47 0.09,0.7L8.04,9.81C7.5,9.31 6.79,9 6,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3c0.79,0 1.5,-0.31 2.04,-0.81l7.12,4.16c-0.05,0.21 -0.08,0.43 -0.08,0.65 0,1.61 1.31,2.92 2.92,2.92 1.61,0 2.92,-1.31 2.92,-2.92s-1.31,-2.92 -2.92,-2.92z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="126dp" android:tint="@color/lightPrimary"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="126dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,12c2.21,0 4,-1.79 4,-4s-1.79,-4 -4,-4 -4,1.79 -4,4 1.79,4 4,4zM12,14c-2.67,0 -8,1.34 -8,4v2h16v-2c0,-2.66 -5.33,-4 -8,-4z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:alpha="0.5" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,4.5C7,4.5 2.73,7.61 1,12c1.73,4.39 6,7.5 11,7.5s9.27,-3.11 11,-7.5c-1.73,-4.39 -6,-7.5 -11,-7.5zM12,17c-2.76,0 -5,-2.24 -5,-5s2.24,-5 5,-5 5,2.24 5,5 -2.24,5 -5,5zM12,9c-1.66,0 -3,1.34 -3,3s1.34,3 3,3 3,-1.34 3,-3 -1.34,-3 -3,-3z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M22,9.24l-7.19,-0.62L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21 12,17.27 18.18,21l-1.63,-7.03L22,9.24zM12,15.4l-3.76,2.27 1,-4.28 -3.32,-2.88 4.38,-0.38L12,6.1l1.71,4.04 4.38,0.38 -3.32,2.88 1,4.28L12,15.4z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:alpha="0.8" android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:alpha="0.5" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M12,17.27L18.18,21l-1.64,-7.03L22,9.24l-7.19,-0.61L12,2 9.19,8.63 2,9.24l5.46,4.73L5.82,21z"/>
</vector>

View File

@ -0,0 +1,22 @@
<vector xmlns:android="http://schemas.android.com/apk/res/android"
android:width="166.67238dp"
android:height="166.67238dp"
android:viewportWidth="590.5714"
android:viewportHeight="590.5714">
<path
android:pathData="M206.005,279.058L168.45,348.748C184.87,406.824 193.208,407.309 212.776,486.676C214.12,458.428 238.971,423.03 261.053,402.367C267.354,435.872 255.68,377.04 293.141,513.627C332.1,391.999 316.533,500.618 337.637,405.064C348.539,371.558 363.777,427.159 376.932,476.217C452.166,375.314 412.799,348.86 433.271,294.932L371.724,290.632C392.73,306.667 408.833,320.407 409.993,322.306C377.679,324.685 415.733,456.748 356.878,338.121C335.655,295.343 295.371,348.196 299.665,415.388C297.95,376.901 250.874,314.022 240.121,357.059C228.277,404.462 217.057,313.826 200.801,314.747C200.801,314.747 210.188,298.25 223.167,280.258L206.005,279.058z"
android:strokeLineJoin="miter"
android:strokeWidth="1.06667"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:strokeLineCap="butt"/>
<path
android:pathData="M299.698,57.766C203.66,58.469 106.33,194.128 115.327,470.79C173.525,604.547 148.628,384.605 194.797,317.036C217.046,284.475 360.513,287.543 378.398,310.373C453.87,406.714 408.23,613.071 475.558,467.012C493.324,197.684 398.733,59.207 301.967,57.773C301.211,57.762 300.454,57.761 299.698,57.766zM300.304,107.547C338.677,107.626 377.044,151.72 392.763,245.132C283.141,223.071 277.21,231.481 206.389,242.036C221.118,154.237 260.713,107.465 300.304,107.547z"
android:strokeLineJoin="miter"
android:strokeWidth="4.26667"
android:fillColor="#ffffff"
android:strokeColor="#00000000"
android:fillType="evenOdd"
android:strokeLineCap="butt"/>
</vector>

View File

@ -1,4 +1,4 @@
<vector android:alpha="0.8" android:height="24dp" android:tint="#FFFFFF"
<vector android:alpha="0.8" android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="?attr/element_color" android:pathData="M8,5v14l11,-7z"/>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp" android:tint="#FFFFFF"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="#FF000000" android:pathData="M8,5v14l11,-7z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/darkElement" android:pathData="M12,4L12,1L8,5l4,4L12,6c3.31,0 6,2.69 6,6 0,1.01 -0.25,1.97 -0.7,2.8l1.46,1.46C19.54,15.03 20,13.57 20,12c0,-4.42 -3.58,-8 -8,-8zM12,18c-3.31,0 -6,-2.69 -6,-6 0,-1.01 0.25,-1.97 0.7,-2.8L5.24,7.74C4.46,8.97 4,10.43 4,12c0,4.42 3.58,8 8,8v3l4,-4 -4,-4v3z"/>
</vector>

View File

@ -1,5 +0,0 @@
<vector android:height="24dp"
android:viewportHeight="24.0" android:viewportWidth="24.0"
android:width="24dp" xmlns:android="http://schemas.android.com/apk/res/android">
<path android:fillColor="@color/darkElement" android:pathData="M4,18l8.5,-6L4,6v12zM13,6v12l8.5,-6L13,6z"/>
</vector>

View File

@ -1,66 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="horizontal">
<ImageView
android:id="@+id/notification_image"
android:layout_width="64.0dip"
android:layout_height="64.0dip"
android:layout_weight="0.0"
android:gravity="center" />
<LinearLayout
android:layout_width="0dip"
android:layout_height="wrap_content"
android:layout_gravity="center_vertical"
android:layout_weight="1"
android:orientation="vertical"
android:paddingLeft="11.0dip">
<TextView
android:id="@+id/notification_title"
style="@style/NotificationText.Title"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:ellipsize="marquee"
android:focusable="true"
android:singleLine="true" />
<TextView
android:id="@+id/notification_artist"
style="@style/NotificationText.Content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:ellipsize="end"
android:maxLines="1"
android:scrollHorizontally="true" />
<TextView
android:id="@+id/notification_album"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:visibility="gone" />
</LinearLayout>
<ImageButton
android:id="@+id/control_previous"
style="@style/NotificationButton"
app:srcCompat="@drawable/notification_media_backward" />
<ImageButton
android:id="@+id/control_pause"
style="@style/NotificationButton"
android:layout_width="54dip"
android:padding="0dip"
app:srcCompat="@drawable/notification_media_pause" />
<ImageButton
android:id="@+id/control_next"
style="@style/NotificationButton"
app:srcCompat="@drawable/notification_media_forward" />
</LinearLayout>

View File

@ -1,97 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:app="http://schemas.android.com/apk/res-auto"
android:layout_width="fill_parent"
android:layout_height="128dp"
android:orientation="horizontal">
<ImageView
android:id="@+id/notification_image"
android:layout_width="128dp"
android:layout_height="128dp"
android:gravity="center" />
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:orientation="vertical"
android:paddingLeft="11.0dip">
<LinearLayout
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<TextView
android:id="@+id/notification_title"
style="@style/NotificationText.Title"
android:layout_width="0dp"
android:layout_height="wrap_content"
android:layout_gravity="left|center_vertical"
android:layout_weight="1"
android:ellipsize="marquee"
android:focusable="true"
android:singleLine="true" />
<ImageButton
android:id="@+id/notification_close"
style="@style/NotificationButton"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="right"
app:srcCompat="@drawable/notification_close"
android:visibility="invisible" />
</LinearLayout>
<TextView
android:id="@+id/notification_artist"
style="@style/NotificationText.Content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:ellipsize="end"
android:maxLines="1"
android:scrollHorizontally="true" />
<TextView
android:id="@+id/notification_album"
style="@style/NotificationText.Content"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_gravity="left"
android:ellipsize="end"
android:maxLines="1"
android:paddingBottom="10dp"
android:scrollHorizontally="true" />
<ImageView
style="@style/NotificationDivider"
android:layout_width="fill_parent"
android:layout_height="1dp" />
<LinearLayout
style="@style/NotificationLayoutDivider"
android:layout_width="fill_parent"
android:layout_height="0dp"
android:layout_weight="1"
android:orientation="horizontal"
android:showDividers="middle">
<ImageButton
android:id="@+id/control_previous"
style="@style/NotificationButton.Expanded"
app:srcCompat="@drawable/notification_media_backward" />
<ImageButton
android:id="@+id/control_pause"
style="@style/NotificationButton.Expanded"
app:srcCompat="@drawable/notification_media_pause" />
<ImageButton
android:id="@+id/control_next"
style="@style/NotificationButton.Expanded"
app:srcCompat="@drawable/notification_media_forward" />
</LinearLayout>
</LinearLayout>
</LinearLayout>

View File

@ -37,7 +37,9 @@
</string-array>
<string-array name="maxBitrateValues">
<item>24</item>
<item>32</item>
<item>48</item>
<item>64</item>
<item>80</item>
<item>96</item>
@ -51,7 +53,9 @@
</string-array>
<string-array name="maxBitrateNames">
<item>@string/settings.max_bitrate_24</item>
<item>@string/settings.max_bitrate_32</item>
<item>@string/settings.max_bitrate_48</item>
<item>@string/settings.max_bitrate_64</item>
<item>@string/settings.max_bitrate_80</item>
<item>@string/settings.max_bitrate_96</item>

View File

@ -11,5 +11,4 @@
<color name="black">#000000</color>
<color name="darkElement">#CCFFFFFF</color>
<color name="nowPlayingShadow">#44000000</color>
</resources>

View File

@ -95,7 +95,6 @@
<string name="download.playerstate_downloading">Downloading - %s</string>
<string name="download.playerstate_mobile_disabled">Waiting for WiFi network to download</string>
<string name="download.playerstate_buffering">Buffering</string>
<string name="download.playerstate_playing_shuffle">Shuffle mode</string>
<string name="download.menu_show_album">Show Album</string>
<string name="download.menu_remove_all">Remove all</string>
<string name="download.menu_shuffle">Shuffle</string>
@ -124,6 +123,7 @@
<string name="settings.title">Settings</string>
<string name="settings.test_connection_title">Test connection</string>
<string name="settings.start_scan_title">Start Media Scan Now</string>
<string name="settings.servers_add">Add Server</string>
<string name="settings.servers_remove">Remove Server</string>
<string name="settings.servers_title">Servers</string>
@ -135,6 +135,8 @@
<string name="settings.server_internal_address">Local network address</string>
<string name="settings.server_username">Username</string>
<string name="settings.server_password">Password</string>
<string name="settings.auth_method">Authentication Method</string>
<string name="settings.auth_summary">Use token/salt authentication?</string>
<string name="settings.server_open_browser">Open in browser</string>
<string name="settings.cache_title">Music cache</string>
<string name="settings.preload_wifi">Songs to preload (Wifi)</string>
@ -150,6 +152,8 @@
<string name="settings.testing_connection">Testing connection…</string>
<string name="settings.testing_ok">Connection is OK</string>
<string name="settings.connection_failure">Connection failure.</string>
<string name="settings.media_scan_started">Media scan started</string>
<string name="settings.media_scan_start_failed">Could not start media scan</string>
<string name="settings.invalid_url">Please specify a valid URL.</string>
<string name="settings.invalid_username">Please specify a valid username (no trailing spaces).</string>
<string name="settings.appearance_title">Appearance</string>
@ -157,8 +161,8 @@
<string name="settings.theme_light">Light</string>
<string name="settings.theme_dark">Dark</string>
<string name="settings.theme_black">Black</string>
<string name="settings.theme_day_night">Day/Night</string>
<string name="settings.theme_day_black_night">Day/Black Night</string>
<string name="settings.theme_day_night">Dynamic (Light/Dark)</string>
<string name="settings.theme_day_black_night">Dynamic (Light/Black)</string>
<string name="settings.theme_fullscreen">Fullscreen</string>
<string name="settings.theme_fullscreen_summary">Hide as many UI elements as Android will allow</string>
<string name="settings.track_title">Display Track #</string>
@ -168,7 +172,9 @@
<string name="settings.network_title">Network</string>
<string name="settings.max_bitrate_wifi">Max Audio bitrate - Wi-Fi</string>
<string name="settings.max_bitrate_mobile">Max Audio bitrate - Mobile</string>
<string name="settings.max_bitrate_24">24 Kbps</string>
<string name="settings.max_bitrate_32">32 Kbps</string>
<string name="settings.max_bitrate_48">48 Kbps</string>
<string name="settings.max_bitrate_64">64 Kbps</string>
<string name="settings.max_bitrate_80">80 Kbps</string>
<string name="settings.max_bitrate_96">96 Kbps</string>

View File

@ -19,32 +19,6 @@
<item name="background">?attr/selectableItemBackgroundBorderless</item>
</style>
<style name="NotificationButton.ExpandedBase">
<item name="android:padding">2dip</item>
<item name="background">?attr/selectableItemBackgroundBorderless</item>
<item name="android:layout_width">0dp</item>
<item name="android:layout_height">fill_parent</item>
<item name="android:layout_weight">1</item>
<item name="android:layout_gravity">center</item>
<item name="android:scaleType">fitCenter</item>
</style>
<style name="NotificationButton.Expanded" parent="@style/NotificationButton.ExpandedBase">
<item name="android:padding">10dip</item>
</style>
<style name="NotificationText.Title" parent="@android:style/TextAppearance.Material.Notification.Title" />
<style name="NotificationText.Content" parent="@android:style/TextAppearance.Material.Notification" />
<style name="NotificationLayoutDivider">
<item name="divider">@drawable/notification_divider</item>
</style>
<style name="NotificationDivider">
<item name="background">@drawable/notification_divider</item>
</style>
<style name="MoreButton" parent="@style/BasicButton">
<item name="android:paddingRight">2dp</item>
</style>

View File

@ -147,10 +147,6 @@
<item name="android:textColor">?android:attr/textColorPrimary</item>
</style>
<style name="DarkSpinnerItem" parent="Widget.AppCompat.TextView.SpinnerItem">
<item name="android:textColor">?android:attr/textColorPrimaryInverse</item>
</style>
<style name="LightActionMode" parent="@style/Widget.AppCompat.ActionMode">
<item name="titleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Title.Inverse</item>
<item name="subtitleTextStyle">@style/TextAppearance.AppCompat.Widget.ActionBar.Subtitle.Inverse</item>

View File

@ -0,0 +1,13 @@
<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
<base-config cleartextTrafficPermitted="true">
<trust-anchors>
<!-- Trust preinstalled CAs -->
<certificates src="system"/>
<!-- Additionally trust user added CAs -->
<certificates src="user"/>
</trust-anchors>
</base-config>
</network-security-config>

View File

@ -3,7 +3,6 @@
android:title="@string/settings.appearance_title">
<ListPreference
android:defaultValue="light"
android:entries="@array/themeNames"
android:entryValues="@array/themeValues"
android:key="theme"

Binary file not shown.

Before

Width:  |  Height:  |  Size: 47 KiB

After

Width:  |  Height:  |  Size: 47 KiB

View File

@ -4,7 +4,7 @@ buildscript {
google()
}
dependencies {
classpath 'com.android.tools.build:gradle:3.5.3'
classpath 'com.android.tools.build:gradle:7.1.2'
}
}

View File

@ -1,6 +1,6 @@
#Sat Aug 24 13:47:57 EDT 2019
#Sun Nov 01 18:55:24 EST 2020
distributionBase=GRADLE_USER_HOME
distributionPath=wrapper/dists
zipStoreBase=GRADLE_USER_HOME
zipStorePath=wrapper/dists
distributionUrl=https\://services.gradle.org/distributions/gradle-5.4.1-all.zip
distributionUrl=https\://services.gradle.org/distributions/gradle-7.2-all.zip