Skip to content

Commit 0e3e902

Browse files
committed
implement configuration to adjust reconnect delay and autoreconnect
1 parent 2c68595 commit 0e3e902

File tree

9 files changed

+272
-86
lines changed

9 files changed

+272
-86
lines changed

README.md

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ repositories {
2323
}
2424
2525
dependencies {
26-
implementation 'com.github.LabyStudio:java-spotify-api:1.1.9:all'
26+
implementation 'com.github.LabyStudio:java-spotify-api:1.1.10:all'
2727
}
2828
```
2929

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ plugins {
44
}
55

66
group 'de.labystudio'
7-
version '1.1.9'
7+
version '1.1.10'
88

99
compileJava {
1010
sourceCompatibility = '1.8'

src/main/java/de/labystudio/spotifyapi/SpotifyAPI.java

Lines changed: 34 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,6 @@
11
package de.labystudio.spotifyapi;
22

3+
import de.labystudio.spotifyapi.config.SpotifyConfiguration;
34
import de.labystudio.spotifyapi.model.MediaKey;
45
import de.labystudio.spotifyapi.model.Track;
56

@@ -17,14 +18,39 @@ public interface SpotifyAPI {
1718
/**
1819
* Initialize the SpotifyAPI and connect to the Spotify process.
1920
* Initializing the api will block the current thread until the connection is established.
21+
* It will use a default configuration.
2022
*
2123
* @return the initialized SpotifyAPI
2224
*/
23-
SpotifyAPI initialize();
25+
default SpotifyAPI initialize() {
26+
return this.initialize(new SpotifyConfiguration.Builder().build());
27+
}
28+
29+
/**
30+
* Initialize the SpotifyAPI and connect to the Spotify process.
31+
* Initializing the api will block the current thread until the connection is established.
32+
*
33+
* @param configuration the configuration for the api
34+
* @return the initialized SpotifyAPI
35+
*/
36+
SpotifyAPI initialize(SpotifyConfiguration configuration);
37+
2438

2539
/**
2640
* Initialize the SpotifyAPI and connect to the Spotify process asynchronously.
2741
*
42+
* @param configuration the configuration for the api
43+
* @return a future that will contain the initialized SpotifyAPI
44+
*/
45+
default CompletableFuture<SpotifyAPI> initializeAsync(SpotifyConfiguration configuration) {
46+
return CompletableFuture.supplyAsync(() -> this.initialize(configuration));
47+
}
48+
49+
50+
/**
51+
* Initialize the SpotifyAPI and connect to the Spotify process asynchronously.
52+
* It will use a default configuration.
53+
*
2854
* @return a future that will contain the initialized SpotifyAPI
2955
*/
3056
default CompletableFuture<SpotifyAPI> initializeAsync() {
@@ -114,6 +140,13 @@ default boolean hasTrack() {
114140
*/
115141
void unregisterListener(SpotifyListener listener);
116142

143+
/**
144+
* Returns the current set configuration of the api.
145+
*
146+
* @return the current set configuration of the api
147+
*/
148+
SpotifyConfiguration getConfiguration();
149+
117150
/**
118151
* Disconnect from the Spotify application and stop all background tasks.
119152
*/

src/main/java/de/labystudio/spotifyapi/SpotifyAPIFactory.java

Lines changed: 25 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,11 @@
11
package de.labystudio.spotifyapi;
22

3-
import de.labystudio.spotifyapi.platform.windows.WinSpotifyAPI;
3+
import de.labystudio.spotifyapi.config.SpotifyConfiguration;
44
import de.labystudio.spotifyapi.platform.osx.OSXSpotifyApi;
5+
import de.labystudio.spotifyapi.platform.windows.WinSpotifyAPI;
56

67
import java.util.Locale;
78
import java.util.concurrent.CompletableFuture;
8-
import java.util.concurrent.Executors;
9-
import java.util.concurrent.Future;
109

1110
/**
1211
* Factory class for creating SpotifyAPI instances.
@@ -38,13 +37,25 @@ public static SpotifyAPI create() {
3837
/**
3938
* Create an initialized SpotifyAPI instance.
4039
* Initializing will block the current thread until the SpotifyAPI instance is ready.
40+
* It will use a default configuration.
4141
*
4242
* @return A new SpotifyAPI instance.
4343
*/
4444
public static SpotifyAPI createInitialized() {
4545
return create().initialize();
4646
}
4747

48+
/**
49+
* Create an initialized SpotifyAPI instance.
50+
* Initializing will block the current thread until the SpotifyAPI instance is ready.
51+
*
52+
* @param configuration The configuration for the SpotifyAPI instance.
53+
* @return A new SpotifyAPI instance.
54+
*/
55+
public static SpotifyAPI createInitialized(SpotifyConfiguration configuration) {
56+
return create().initialize(configuration);
57+
}
58+
4859
/**
4960
* Creates a new SpotifyAPI instance for the current platform asynchronously.
5061
* Currently, only Windows and OSX are supported.
@@ -55,4 +66,15 @@ public static CompletableFuture<SpotifyAPI> createInitializedAsync() {
5566
return CompletableFuture.supplyAsync(SpotifyAPIFactory::createInitialized);
5667
}
5768

69+
/**
70+
* Creates a new SpotifyAPI instance for the current platform asynchronously.
71+
* Currently, only Windows and OSX are supported.
72+
* It will use a default configuration.
73+
*
74+
* @param configuration The configuration for the SpotifyAPI instance.
75+
* @return A future that will contain the SpotifyAPI instance.
76+
*/
77+
public static CompletableFuture<SpotifyAPI> createInitializedAsync(SpotifyConfiguration configuration) {
78+
return CompletableFuture.supplyAsync(() -> createInitialized(configuration));
79+
}
5880
}
Lines changed: 74 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,74 @@
1+
package de.labystudio.spotifyapi.config;
2+
3+
/**
4+
* A configuration for the spotify api
5+
*
6+
* @author LabyStudio
7+
*/
8+
public class SpotifyConfiguration {
9+
10+
private long exceptionReconnectDelay;
11+
private boolean autoReconnect;
12+
13+
private SpotifyConfiguration(
14+
long exceptionReconnectDelay,
15+
boolean autoReconnect
16+
) {
17+
this.exceptionReconnectDelay = exceptionReconnectDelay;
18+
this.autoReconnect = autoReconnect;
19+
}
20+
21+
public void setExceptionReconnectDelay(long exceptionReconnectDelay) {
22+
this.exceptionReconnectDelay = exceptionReconnectDelay;
23+
}
24+
25+
public void setAutoReconnect(boolean autoReconnect) {
26+
this.autoReconnect = autoReconnect;
27+
}
28+
29+
public long getExceptionReconnectDelay() {
30+
return this.exceptionReconnectDelay;
31+
}
32+
33+
public boolean isAutoReconnect() {
34+
return this.autoReconnect;
35+
}
36+
37+
/**
38+
* Builder to create a new spotify configuration
39+
*/
40+
public static class Builder {
41+
42+
private long exceptionReconnectDelay = 1000 * 10L;
43+
private boolean autoReconnect = true;
44+
45+
/**
46+
* Set the delay between reconnects when an exception occurs
47+
*
48+
* @param exceptionReconnectDelay The delay in milliseconds
49+
* @return The builder instance
50+
*/
51+
public Builder exceptionReconnectDelay(long exceptionReconnectDelay) {
52+
this.exceptionReconnectDelay = exceptionReconnectDelay;
53+
return this;
54+
}
55+
56+
/**
57+
* Set if the api should automatically reconnect when an exception occurs
58+
*
59+
* @param autoReconnect The auto reconnect state
60+
* @return The builder instance
61+
*/
62+
public Builder autoReconnect(boolean autoReconnect) {
63+
this.autoReconnect = autoReconnect;
64+
return this;
65+
}
66+
67+
public SpotifyConfiguration build() {
68+
return new SpotifyConfiguration(
69+
this.exceptionReconnectDelay,
70+
this.autoReconnect
71+
);
72+
}
73+
}
74+
}

src/main/java/de/labystudio/spotifyapi/open/OpenSpotifyAPI.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ private AccessTokenResponse generateAccessToken() throws IOException {
6868

6969
// Read response
7070
JsonReader reader = new JsonReader(new InputStreamReader(connection.getInputStream()));
71-
return new Gson().fromJson(reader, AccessTokenResponse.class);
71+
return GSON.fromJson(reader, AccessTokenResponse.class);
7272
}
7373

7474
/**

src/main/java/de/labystudio/spotifyapi/platform/AbstractTickSpotifyAPI.java

Lines changed: 53 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,13 @@
22

33
import de.labystudio.spotifyapi.SpotifyAPI;
44
import de.labystudio.spotifyapi.SpotifyListener;
5+
import de.labystudio.spotifyapi.config.SpotifyConfiguration;
56

67
import java.util.ArrayList;
78
import java.util.List;
89
import java.util.concurrent.Executors;
910
import java.util.concurrent.ScheduledFuture;
11+
import java.util.concurrent.TimeUnit;
1012

1113
/**
1214
* Abstract tick class for SpotifyAPI implementations.
@@ -20,7 +22,10 @@ public abstract class AbstractTickSpotifyAPI implements SpotifyAPI {
2022
*/
2123
protected final List<SpotifyListener> listeners = new ArrayList<>();
2224

25+
private SpotifyConfiguration configuration;
26+
2327
private ScheduledFuture<?> task;
28+
private long timeLastException = -1;
2429

2530
/**
2631
* Initialize the SpotifyAPI abstract tick implementation.
@@ -29,20 +34,48 @@ public abstract class AbstractTickSpotifyAPI implements SpotifyAPI {
2934
* @return the initialized SpotifyAPI
3035
* @throws IllegalStateException if the API is already initialized
3136
*/
32-
public SpotifyAPI initialize() {
33-
if (this.isInitialized()) {
34-
throw new IllegalStateException("The SpotifyAPI is already initialized");
37+
@Override
38+
public SpotifyAPI initialize(SpotifyConfiguration configuration) {
39+
synchronized (this) {
40+
this.configuration = configuration;
41+
42+
if (this.isInitialized()) {
43+
throw new IllegalStateException("The SpotifyAPI is already initialized");
44+
}
45+
46+
// Start task to update every second
47+
this.task = Executors.newScheduledThreadPool(1)
48+
.scheduleWithFixedDelay(
49+
this::onInternalTick,
50+
0,
51+
1,
52+
TimeUnit.SECONDS
53+
);
3554
}
55+
return this;
56+
}
3657

37-
// Initial tick
38-
this.onTick();
58+
private void onInternalTick() {
59+
try {
60+
// Check if we passed the exception timeout
61+
long timeSinceLastException = System.currentTimeMillis() - this.timeLastException;
62+
if (timeSinceLastException < this.configuration.getExceptionReconnectDelay()) {
63+
return;
64+
}
3965

40-
// Start task to update every second
41-
this.task = Executors.newScheduledThreadPool(1).scheduleWithFixedDelay(
42-
this::onTick, 1, 1, java.util.concurrent.TimeUnit.SECONDS
43-
);
66+
this.onTick();
67+
} catch (Exception e) {
68+
this.timeLastException = System.currentTimeMillis();
69+
this.stop();
4470

45-
return this;
71+
// Fire on disconnect
72+
this.listeners.forEach(listener -> listener.onDisconnect(e));
73+
74+
// Restart the process
75+
if (this.configuration.isAutoReconnect()) {
76+
this.initialize(this.configuration);
77+
}
78+
}
4679
}
4780

4881
protected abstract void onTick();
@@ -62,11 +95,18 @@ public boolean isInitialized() {
6295
return this.task != null;
6396
}
6497

98+
@Override
99+
public SpotifyConfiguration getConfiguration() {
100+
return this.configuration;
101+
}
102+
65103
@Override
66104
public void stop() {
67-
if (this.task != null) {
68-
this.task.cancel(true);
69-
this.task = null;
105+
synchronized (this) {
106+
if (this.task != null) {
107+
this.task.cancel(true);
108+
this.task = null;
109+
}
70110
}
71111
}
72112
}

0 commit comments

Comments
 (0)