Skip to content

Commit 12f55b2

Browse files
committed
Merge branch 'edge'
2 parents 0ff92da + c04e82e commit 12f55b2

35 files changed

+339
-117
lines changed

.gitignore

+2-1
Original file line numberDiff line numberDiff line change
@@ -13,4 +13,5 @@ proguard_logs/
1313
.gradle/*
1414
/build/
1515
local.properties
16-
*Thumbs.db
16+
*Thumbs.db
17+
app/google/release

app/build.gradle

+10-3
Original file line numberDiff line numberDiff line change
@@ -6,11 +6,18 @@ android {
66
defaultConfig {
77
applicationId "github.daneren2005.dsub"
88
minSdkVersion 15
9-
targetSdkVersion 26
10-
versionCode 203
11-
versionName '5.5.0'
9+
targetSdkVersion 29
10+
versionCode 206
11+
versionName '5.5.2'
1212
setProperty("archivesBaseName", "DSub $versionName")
1313
resConfigs "de", "es", "fr", "hu", "nl", "pt-rPT", "ru", "sv"
14+
vectorDrawables.useSupportLibrary = true
15+
resValue 'string', 'account_type.subsonic', applicationId + ".subsonic"
16+
resValue 'string', 'provider.search', applicationId + ".provider.DSubSearchProvider"
17+
resValue 'string', 'provider.playlist', applicationId + ".playlists.provider"
18+
resValue 'string', 'provider.podcast', applicationId + ".podcasts.provider"
19+
resValue 'string', 'provider.starred', applicationId + ".starred.provider"
20+
resValue 'string', 'provider.recently_added', applicationId + ".mostrecent.provider"
1421
}
1522
buildTypes {
1623
release {

app/src/google/java/github/daneren2005/dsub/service/ChromeCastController.java

+4-2
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
import github.daneren2005.serverproxy.ServerProxy;
5050
import github.daneren2005.serverproxy.WebProxy;
5151

52+
import static github.daneren2005.dsub.util.compat.GoogleCompat.castApplicationId;
53+
5254
/**
5355
* Created by owner on 2/9/14.
5456
*/
@@ -421,14 +423,14 @@ public void onConnectionSuspended(int cause) {
421423

422424
void launchApplication() {
423425
try {
424-
Cast.CastApi.launchApplication(apiClient, EnvironmentVariables.CAST_APPLICATION_ID, false).setResultCallback(resultCallback);
426+
Cast.CastApi.launchApplication(apiClient, castApplicationId(), false).setResultCallback(resultCallback);
425427
} catch (Exception e) {
426428
Log.e(TAG, "Failed to launch application", e);
427429
}
428430
}
429431
void reconnectApplication() {
430432
try {
431-
Cast.CastApi.joinApplication(apiClient, EnvironmentVariables.CAST_APPLICATION_ID, sessionId).setResultCallback(resultCallback);
433+
Cast.CastApi.joinApplication(apiClient, castApplicationId(), sessionId).setResultCallback(resultCallback);
432434
} catch (Exception e) {
433435
Log.e(TAG, "Failed to reconnect application", e);
434436
}

app/src/google/java/github/daneren2005/dsub/util/compat/GoogleCompat.java

+12-4
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@
99
import com.google.android.gms.common.ConnectionResult;
1010
import com.google.android.gms.common.GoogleApiAvailability;
1111
import com.google.android.gms.security.ProviderInstaller;
12+
import static com.google.android.gms.cast.CastMediaControlIntent.DEFAULT_MEDIA_RECEIVER_APPLICATION_ID;
1213

1314
import github.daneren2005.dsub.service.ChromeCastController;
1415
import github.daneren2005.dsub.service.DownloadService;
@@ -32,10 +33,17 @@ public static void installProvider(Context context) throws Exception{
3233
ProviderInstaller.installIfNeeded(context);
3334
}
3435

36+
public static String castApplicationId() {
37+
if (EnvironmentVariables.CAST_APPLICATION_ID != null) {
38+
return EnvironmentVariables.CAST_APPLICATION_ID;
39+
} else {
40+
return DEFAULT_MEDIA_RECEIVER_APPLICATION_ID;
41+
}
42+
}
43+
3544
public static boolean castAvailable() {
36-
if (EnvironmentVariables.CAST_APPLICATION_ID == null) {
37-
Log.w(TAG, "CAST_APPLICATION_ID not provided");
38-
return false;
45+
if (castApplicationId() == DEFAULT_MEDIA_RECEIVER_APPLICATION_ID) {
46+
Log.i(TAG, "Using DEFAULT_MEDIA_RECEIVER_APPLICATION_ID for casting");
3947
}
4048
try {
4149
Class.forName("com.google.android.gms.cast.CastDevice");
@@ -56,6 +64,6 @@ public static RemoteController getController(DownloadService downloadService, Me
5664
}
5765

5866
public static String getCastControlCategory() {
59-
return CastMediaControlIntent.categoryForCast(EnvironmentVariables.CAST_APPLICATION_ID);
67+
return CastMediaControlIntent.categoryForCast(castApplicationId());
6068
}
6169
}

app/src/main/AndroidManifest.xml

+13-11
Original file line numberDiff line numberDiff line change
@@ -16,14 +16,14 @@
1616
<uses-permission android:name="android.permission.MODIFY_AUDIO_SETTINGS"/>
1717
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
1818
<uses-permission android:name="android.permission.BLUETOOTH"/>
19-
<uses-permission android:name="android.permission.READ_LOGS"/>
2019
<uses-permission android:name="android.permission.READ_SYNC_SETTINGS"/>
2120
<uses-permission android:name="android.permission.WRITE_SYNC_SETTINGS"/>
2221
<uses-permission android:name="android.permission.AUTHENTICATE_ACCOUNTS"/>
2322
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE"/>
2423
<uses-permission android:name="android.permission.CHANGE_WIFI_MULTICAST_STATE"/>
2524
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
26-
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION"/>
25+
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION"/>
26+
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" />
2727

2828
<uses-feature android:name="android.hardware.touchscreen" android:required="false" />
2929
<uses-feature android:name="android.hardware.bluetooth" android:required="false" />
@@ -39,7 +39,8 @@
3939
android:backupAgent="github.daneren2005.dsub.util.SettingsBackupAgent"
4040
android:icon="@drawable/launch"
4141
android:theme="@style/Theme.DSub.Light"
42-
android:largeHeap="true">
42+
android:largeHeap="true"
43+
android:usesCleartextTraffic="true">
4344

4445
<uses-library android:name="android.test.runner" />
4546

@@ -89,10 +90,11 @@
8990
</intent-filter>
9091
</activity>
9192

92-
<service android:name=".service.DownloadService"
93-
android:label="DSub Playback Service"/>
93+
<service android:name="github.daneren2005.dsub.service.DownloadService"
94+
android:label="DSub Playback Service"
95+
android:foregroundServiceType="location"/>
9496

95-
<service android:name=".service.AutoMediaBrowserService"
97+
<service android:name="github.daneren2005.dsub.service.AutoMediaBrowserService"
9698
android:exported="true">
9799

98100
<intent-filter>
@@ -214,24 +216,24 @@
214216
</receiver>
215217

216218
<provider android:name="github.daneren2005.dsub.provider.DSubSearchProvider"
217-
android:authorities="github.daneren2005.dsub.provider.DSubSearchProvider"/>
219+
android:authorities="@string/provider.search"/>
218220
<provider android:name="github.daneren2005.dsub.provider.PlaylistStubProvider"
219-
android:authorities="github.daneren2005.dsub.playlists.provider"
221+
android:authorities="@string/provider.playlist"
220222
android:label="@string/button_bar.playlists"
221223
android:exported="false"
222224
android:syncable="true"/>
223225
<provider android:name="github.daneren2005.dsub.provider.PodcastStubProvider"
224-
android:authorities="github.daneren2005.dsub.podcasts.provider"
226+
android:authorities="@string/provider.podcast"
225227
android:label="@string/button_bar.podcasts"
226228
android:exported="false"
227229
android:syncable="true"/>
228230
<provider android:name="github.daneren2005.dsub.provider.StarredStubProvider"
229-
android:authorities="github.daneren2005.dsub.starred.provider"
231+
android:authorities="@string/provider.starred"
230232
android:label="@string/main.albums_starred"
231233
android:exported="false"
232234
android:syncable="true"/>
233235
<provider android:name="github.daneren2005.dsub.provider.MostRecentStubProvider"
234-
android:authorities="github.daneren2005.dsub.mostrecent.provider"
236+
android:authorities="@string/provider.recently_added"
235237
android:label="@string/main.albums_newest"
236238
android:exported="false"
237239
android:syncable="true"/>

app/src/main/java/github/daneren2005/dsub/activity/SubsonicActivity.java

+21-1
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,7 @@
1818
*/
1919
package github.daneren2005.dsub.activity;
2020

21+
import android.Manifest;
2122
import android.app.UiModeManager;
2223
import android.content.Context;
2324
import android.content.DialogInterface;
@@ -184,6 +185,17 @@ public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, Strin
184185
if (ContextCompat.checkSelfPermission(this, permission.WRITE_EXTERNAL_STORAGE) != PackageManager.PERMISSION_GRANTED) {
185186
ActivityCompat.requestPermissions(this, new String[]{ permission.WRITE_EXTERNAL_STORAGE }, PERMISSIONS_REQUEST_WRITE_EXTERNAL_STORAGE);
186187
}
188+
189+
SharedPreferences prefs = Util.getPreferences(this);
190+
int instance = prefs.getInt(Constants.PREFERENCES_KEY_SERVER_INSTANCE, 1);
191+
String expectedSSID = prefs.getString(Constants.PREFERENCES_KEY_SERVER_LOCAL_NETWORK_SSID + instance, "");
192+
if(!expectedSSID.isEmpty()) {
193+
String currentSSID = Util.getSSID(this);
194+
195+
if(currentSSID == "<unknown ssid>" && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
196+
ActivityCompat.requestPermissions(this, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, SubsonicActivity.PERMISSIONS_REQUEST_LOCATION);
197+
}
198+
}
187199
}
188200

189201
@Override
@@ -198,6 +210,14 @@ public void onRequestPermissionsResult(int requestCode, String permissions[], in
198210
finish();
199211
}
200212
}
213+
case PERMISSIONS_REQUEST_LOCATION: {
214+
// If request is cancelled, the result arrays are empty.
215+
if (grantResults.length > 0 && grantResults[0] == PackageManager.PERMISSION_GRANTED) {
216+
217+
} else {
218+
Util.toast(this, R.string.permission_location_failed);
219+
}
220+
}
201221
}
202222
}
203223

@@ -1248,7 +1268,7 @@ public void uncaughtException(Thread thread, Throwable throwable) {
12481268
PrintWriter printWriter = null;
12491269
try {
12501270

1251-
PackageInfo packageInfo = context.getPackageManager().getPackageInfo("github.daneren2005.dsub", 0);
1271+
PackageInfo packageInfo = context.getPackageManager().getPackageInfo(context.getPackageName(), 0);
12521272
file = new File(Environment.getExternalStorageDirectory(), "dsub-stacktrace.txt");
12531273
printWriter = new PrintWriter(file);
12541274
printWriter.println("Android API level: " + Build.VERSION.SDK);

app/src/main/java/github/daneren2005/dsub/fragments/SettingsFragment.java

+14-3
Original file line numberDiff line numberDiff line change
@@ -214,7 +214,7 @@ else if(Constants.PREFERENCES_KEY_SYNC_MOST_RECENT.equals(key)) {
214214
if(downloadService != null) {
215215
MediaRouteManager mediaRouter = downloadService.getMediaRouter();
216216

217-
Boolean enabled = sharedPreferences.getBoolean(key, true);
217+
Boolean enabled = sharedPreferences.getBoolean(key, false);
218218
if (enabled) {
219219
mediaRouter.addDLNAProvider();
220220
} else {
@@ -528,6 +528,10 @@ protected void onAddEditTextToDialogView(View dialogView, final EditText editTex
528528
super.onAddEditTextToDialogView(dialogView, editText);
529529
ViewGroup root = (ViewGroup) ((ViewGroup) dialogView).getChildAt(0);
530530

531+
if(internalSSID == "<unknown ssid>" && ActivityCompat.checkSelfPermission(context, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
532+
ActivityCompat.requestPermissions(context, new String[]{Manifest.permission.ACCESS_FINE_LOCATION}, SubsonicActivity.PERMISSIONS_REQUEST_LOCATION);
533+
}
534+
531535
Button defaultButton = new Button(getContext());
532536
defaultButton.setText(internalSSIDDisplay);
533537
defaultButton.setOnClickListener(new View.OnClickListener() {
@@ -575,6 +579,12 @@ public void onClick(View v) {
575579
serverSyncPreference.setSummary(R.string.settings_server_sync_summary);
576580
serverSyncPreference.setTitle(R.string.settings_server_sync);
577581

582+
final CheckBoxPreference serverAuthHeaderPreference = new CheckBoxPreference(context);
583+
serverAuthHeaderPreference.setKey(Constants.PREFERENCES_KEY_SERVER_AUTHHEADER + instance);
584+
serverAuthHeaderPreference.setChecked(Util.isAuthHeaderEnabled(context, instance));
585+
serverAuthHeaderPreference.setSummary(R.string.settings_server_authheaders_summary);
586+
serverAuthHeaderPreference.setTitle(R.string.settings_server_authheaders);
587+
578588
final Preference serverOpenBrowser = new Preference(context);
579589
serverOpenBrowser.setKey(Constants.PREFERENCES_KEY_OPEN_BROWSER);
580590
serverOpenBrowser.setPersistent(false);
@@ -649,6 +659,7 @@ public boolean onPreferenceClick(Preference preference) {
649659
screen.addPreference(serverPasswordPreference);
650660
screen.addPreference(serverTagPreference);
651661
screen.addPreference(serverSyncPreference);
662+
screen.addPreference(serverAuthHeaderPreference);
652663
screen.addPreference(serverTestConnectionPreference);
653664
screen.addPreference(serverOpenBrowser);
654665
screen.addPreference(serverRemoveServerPreference);
@@ -803,7 +814,7 @@ public boolean onPreferenceChange(Preference preference, Object value) {
803814
try {
804815
String url = (String) value;
805816
new URL(url);
806-
if (url.contains(" ") || url.contains("@")) {
817+
if (url.contains(" ")) {
807818
throw new Exception();
808819
}
809820
} catch (Exception x) {
@@ -824,7 +835,7 @@ public boolean onPreferenceChange(Preference preference, Object value) {
824835
}
825836

826837
new URL(url);
827-
if (url.contains(" ") || url.contains("@")) {
838+
if (url.contains(" ")) {
828839
throw new Exception();
829840
}
830841
} catch (Exception x) {

app/src/main/java/github/daneren2005/dsub/service/DownloadService.java

+10-6
Original file line numberDiff line numberDiff line change
@@ -310,7 +310,9 @@ public boolean onError(MediaPlayer mediaPlayer, int what, int more) {
310310
public int onStartCommand(Intent intent, int flags, int startId) {
311311
super.onStartCommand(intent, flags, startId);
312312
lifecycleSupport.onStart(intent);
313-
if(Build.VERSION.SDK_INT >= 26 && !this.isForeground()) {
313+
314+
String action = intent.getAction();
315+
if(Build.VERSION.SDK_INT >= 26 && !this.isForeground() && !"KEYCODE_MEDIA_START".equals(action)) {
314316
Notifications.shutGoogleUpNotification(this);
315317
}
316318
return START_NOT_STICKY;
@@ -1081,7 +1083,7 @@ public synchronized List<DownloadFile> getDownloads() {
10811083

10821084
public synchronized List<DownloadFile> getRecentDownloads() {
10831085
int from = Math.max(currentPlayingIndex - 10, 0);
1084-
int songsToKeep = Math.max(Util.getPreloadCount(this), 20);
1086+
int songsToKeep = Math.min(Math.max(Util.getPreloadCount(this), 20), downloadList.size());
10851087
int to = Math.min(currentPlayingIndex + songsToKeep, Math.max(downloadList.size() - 1, 0));
10861088
List<DownloadFile> temp = downloadList.subList(from, to);
10871089
temp.addAll(backgroundDownloadList);
@@ -1519,12 +1521,14 @@ public synchronized void setPlayerState(final PlayerState playerState) {
15191521
Util.requestAudioFocus(this, audioManager);
15201522
}
15211523

1524+
SharedPreferences prefs = Util.getPreferences(this);
1525+
boolean usingMediaStyleNotification = prefs.getBoolean(Constants.PREFERENCES_KEY_MEDIA_STYLE_NOTIFICATION, true) && Build.VERSION.SDK_INT >= Build.VERSION_CODES.LOLLIPOP;
1526+
15221527
if (show) {
1523-
Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong());
1528+
Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong(), usingMediaStyleNotification);
15241529
} else if (pause) {
1525-
SharedPreferences prefs = Util.getPreferences(this);
1526-
if(prefs.getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) {
1527-
Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong());
1530+
if (prefs.getBoolean(Constants.PREFERENCES_KEY_PERSISTENT_NOTIFICATION, false)) {
1531+
Notifications.showPlayingNotification(this, this, handler, currentPlaying.getSong(), usingMediaStyleNotification);
15281532
} else {
15291533
Notifications.hidePlayingNotification(this, this, handler);
15301534
}

app/src/main/java/github/daneren2005/dsub/service/RESTMusicService.java

+10-5
Original file line numberDiff line numberDiff line change
@@ -1911,11 +1911,16 @@ private HttpURLConnection getConnectionDirect(Context context, String url, Map<S
19111911

19121912
SharedPreferences prefs = Util.getPreferences(context);
19131913
int instance = getInstance(context);
1914-
String username = prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
1915-
String password = prefs.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null);
1916-
if (prefs.getBoolean(Constants.PREFERENCES_KEY_ENCRYPTED_PASSWORD + instance, false)) password = KeyStoreUtil.decrypt(password);
1917-
String encoded = Base64.encodeToString((username + ":" + password).getBytes("UTF-8"), Base64.NO_WRAP);;
1918-
connection.setRequestProperty("Authorization", "Basic " + encoded);
1914+
boolean authHeader = prefs.getBoolean(Constants.PREFERENCES_KEY_SERVER_AUTHHEADER + instance, true);
1915+
if(authHeader) {
1916+
String username = prefs.getString(Constants.PREFERENCES_KEY_USERNAME + instance, null);
1917+
String password = prefs.getString(Constants.PREFERENCES_KEY_PASSWORD + instance, null);
1918+
if (prefs.getBoolean(Constants.PREFERENCES_KEY_ENCRYPTED_PASSWORD + instance, false)) {
1919+
password = KeyStoreUtil.decrypt(password);
1920+
}
1921+
String encoded = Base64.encodeToString((username + ":" + password).getBytes("UTF-8"), Base64.NO_WRAP);
1922+
connection.setRequestProperty("Authorization", "Basic " + encoded);
1923+
}
19191924

19201925
// Force the connection to initiate
19211926
if(connection.getResponseCode() >= 500) {

app/src/main/java/github/daneren2005/dsub/util/Constants.java

+11-7
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,8 @@
1818
*/
1919
package github.daneren2005.dsub.util;
2020

21+
import github.daneren2005.dsub.BuildConfig;
22+
2123
/**
2224
* @author Sindre Mehus
2325
* @version $Id$
@@ -85,6 +87,7 @@ public final class Constants {
8587
public static final String PREFERENCES_KEY_MUSIC_FOLDER_ID = "musicFolderId";
8688
public static final String PREFERENCES_KEY_USERNAME = "username";
8789
public static final String PREFERENCES_KEY_PASSWORD = "password";
90+
public static final String PREFERENCES_KEY_SERVER_AUTHHEADER = "authHeader";
8891
public static final String PREFERENCES_KEY_ENCRYPTED_PASSWORD = "encryptedPassword";
8992
public static final String PREFERENCES_KEY_INSTALL_TIME = "installTime";
9093
public static final String PREFERENCES_KEY_THEME = "theme";
@@ -117,6 +120,7 @@ public final class Constants {
117120
public static final String PREFERENCES_EQUALIZER_ON = "equalizerOn";
118121
public static final String PREFERENCES_EQUALIZER_SETTINGS = "equalizerSettings";
119122
public static final String PREFERENCES_KEY_PERSISTENT_NOTIFICATION = "persistentNotification";
123+
public static final String PREFERENCES_KEY_MEDIA_STYLE_NOTIFICATION = "mediaStyleNotification";
120124
public static final String PREFERENCES_KEY_GAPLESS_PLAYBACK = "gaplessPlayback";
121125
public static final String PREFERENCES_KEY_REMOVE_PLAYED = "removePlayed";
122126
public static final String PREFERENCES_KEY_KEEP_PLAYED_CNT = "keepPlayedCount";
@@ -212,17 +216,17 @@ public final class Constants {
212216
public static final String FRAGMENT_POSITION = "fragmentPosition";
213217

214218
// Name of the preferences file.
215-
public static final String PREFERENCES_FILE_NAME = "github.daneren2005.dsub_preferences";
216-
public static final String OFFLINE_SYNC_NAME = "github.daneren2005.dsub.offline";
219+
public static final String PREFERENCES_FILE_NAME = BuildConfig.APPLICATION_ID + "_preferences";
220+
public static final String OFFLINE_SYNC_NAME = BuildConfig.APPLICATION_ID + ".offline";
217221
public static final String OFFLINE_SYNC_DEFAULT = "syncDefaults";
218222

219223
// Account prefs
220224
public static final String SYNC_ACCOUNT_NAME = "Subsonic Account";
221-
public static final String SYNC_ACCOUNT_TYPE = "subsonic.org";
222-
public static final String SYNC_ACCOUNT_PLAYLIST_AUTHORITY = "github.daneren2005.dsub.playlists.provider";
223-
public static final String SYNC_ACCOUNT_PODCAST_AUTHORITY = "github.daneren2005.dsub.podcasts.provider";
224-
public static final String SYNC_ACCOUNT_STARRED_AUTHORITY = "github.daneren2005.dsub.starred.provider";
225-
public static final String SYNC_ACCOUNT_MOST_RECENT_AUTHORITY = "github.daneren2005.dsub.mostrecent.provider";
225+
public static final String SYNC_ACCOUNT_TYPE = BuildConfig.APPLICATION_ID + ".subsonic";
226+
public static final String SYNC_ACCOUNT_PLAYLIST_AUTHORITY = BuildConfig.APPLICATION_ID + ".playlists.provider";
227+
public static final String SYNC_ACCOUNT_PODCAST_AUTHORITY = BuildConfig.APPLICATION_ID + ".podcasts.provider";
228+
public static final String SYNC_ACCOUNT_STARRED_AUTHORITY = BuildConfig.APPLICATION_ID + ".starred.provider";
229+
public static final String SYNC_ACCOUNT_MOST_RECENT_AUTHORITY = BuildConfig.APPLICATION_ID + ".mostrecent.provider";
226230

227231
public static final String TASKER_EXTRA_BUNDLE = "com.twofortyfouram.locale.intent.extra.BUNDLE";
228232

0 commit comments

Comments
 (0)