Skip to content

Commit 5cf6093

Browse files
authored
Configurable API endpoint (#485)
1 parent d392efa commit 5cf6093

File tree

15 files changed

+480
-62
lines changed

15 files changed

+480
-62
lines changed

AndroidSDKCore/src/main/java/com/leanplum/Leanplum.java

Lines changed: 14 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -56,6 +56,7 @@
5656
import com.leanplum.internal.RequestSender;
5757
import com.leanplum.internal.RequestSenderTimer;
5858
import com.leanplum.internal.RequestUtil;
59+
import com.leanplum.internal.Socket;
5960
import com.leanplum.internal.Util;
6061
import com.leanplum.internal.Util.DeviceIdInfo;
6162
import com.leanplum.internal.VarCache;
@@ -124,25 +125,23 @@ private Leanplum() {
124125
}
125126

126127
/**
127-
* Optional. Sets the API server. The API path is of the form http[s]://hostname/servletName
128+
* Optional. Sets the API server. The API path is of the form http[s]://hostName/apiPath
128129
*
129130
* @param hostName The name of the API host, such as www.leanplum.com
130-
* @param servletName The name of the API servlet, such as api
131+
* @param apiPath The name of the API servlet, such as api
131132
* @param ssl Whether to use SSL
132133
*/
133-
public static void setApiConnectionSettings(String hostName, String servletName, boolean ssl) {
134+
public static void setApiConnectionSettings(String hostName, String apiPath, boolean ssl) {
134135
if (TextUtils.isEmpty(hostName)) {
135-
Log.i("setApiConnectionSettings - Empty hostname parameter provided.");
136+
Log.i("setApiConnectionSettings - Empty hostName parameter provided.");
136137
return;
137138
}
138-
if (TextUtils.isEmpty(servletName)) {
139-
Log.i("setApiConnectionSettings - Empty servletName parameter provided.");
139+
if (TextUtils.isEmpty(apiPath)) {
140+
Log.i("setApiConnectionSettings - Empty apiPath parameter provided.");
140141
return;
141142
}
142143

143-
Constants.API_HOST_NAME = hostName;
144-
Constants.API_SERVLET = servletName;
145-
Constants.API_SSL = ssl;
144+
APIConfig.getInstance().setApiConfig(hostName, apiPath, ssl);
146145
}
147146

148147
/**
@@ -161,8 +160,11 @@ public static void setSocketConnectionSettings(String hostName, int port) {
161160
return;
162161
}
163162

164-
Constants.SOCKET_HOST = hostName;
165-
Constants.SOCKET_PORT = port;
163+
String currentSocketHost = APIConfig.getInstance().getSocketHost();
164+
if (!hostName.equals(currentSocketHost)) {
165+
APIConfig.getInstance().setSocketConfig(hostName, port);
166+
LeanplumInternal.connectDevelopmentServer();
167+
}
166168
}
167169

168170
/**
@@ -582,7 +584,7 @@ static synchronized void start(final Context context, final String userId,
582584
LeanplumInternal.getUserAttributeChanges().add(validAttributes);
583585
}
584586

585-
APIConfig.getInstance().loadToken();
587+
APIConfig.getInstance(); // load prefs
586588
VarCache.setSilent(true);
587589
VarCache.loadDiffs();
588590
VarCache.setSilent(false);
@@ -825,7 +827,6 @@ private static void handleStartResponse(final JSONObject response) {
825827

826828
String token = response.optString(Constants.Keys.TOKEN, null);
827829
APIConfig.getInstance().setToken(token);
828-
APIConfig.getInstance().saveToken();
829830

830831
applyContentInResponse(response);
831832

AndroidSDKCore/src/main/java/com/leanplum/internal/APIConfig.java

Lines changed: 82 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2018, Leanplum, Inc. All rights reserved.
2+
* Copyright 2022, Leanplum, Inc. All rights reserved.
33
*
44
* Licensed to the Apache Software Foundation (ASF) under one
55
* or more contributor license agreements. See the NOTICE file
@@ -26,22 +26,33 @@
2626
import android.text.TextUtils;
2727
import androidx.annotation.VisibleForTesting;
2828
import com.leanplum.Leanplum;
29+
import com.leanplum.internal.Constants.Defaults;
2930
import com.leanplum.utils.SharedPreferencesUtil;
3031
import java.util.Map;
3132

3233
public class APIConfig {
3334
private static final APIConfig INSTANCE = new APIConfig();
3435

36+
// non persistable data
3537
private String appId;
3638
private String accessKey;
3739
private String deviceId;
3840
private String userId;
41+
42+
// persistable data
43+
3944
// The token is saved primarily for legacy SharedPreferences decryption. This could
4045
// likely be removed in the future.
4146
private String token;
47+
private String apiHost = "api.leanplum.com";
48+
private String apiPath = "api";
49+
private boolean apiSSL = true;
50+
private String socketHost = "dev.leanplum.com";
51+
private int socketPort = 443;
4252

4353
@VisibleForTesting
4454
APIConfig() {
55+
load();
4556
}
4657

4758
public static APIConfig getInstance() {
@@ -57,10 +68,6 @@ public void setAppId(String appId, String accessKey) {
5768
}
5869
}
5970

60-
public void loadToken(String token) {
61-
this.token = token;
62-
}
63-
6471
public String appId() {
6572
return appId;
6673
}
@@ -91,25 +98,50 @@ public String token() {
9198

9299
public void setToken(String token) {
93100
this.token = token;
101+
save();
94102
}
95103

96-
public void loadToken() {
104+
private void load() {
97105
Context context = Leanplum.getContext();
98106
SharedPreferences defaults = context.getSharedPreferences(
99107
Constants.Defaults.LEANPLUM, Context.MODE_PRIVATE);
108+
100109
String token = defaults.getString(Constants.Defaults.TOKEN_KEY, null);
101-
if (token == null) {
102-
return;
110+
if (token != null) {
111+
this.token = token;
112+
}
113+
String apiHost = defaults.getString(Defaults.API_HOST_KEY, null);
114+
if (apiHost != null) {
115+
this.apiHost = apiHost;
116+
}
117+
String apiPath = defaults.getString(Defaults.API_PATH_KEY, null);
118+
if (apiPath != null) {
119+
this.apiPath = apiPath;
120+
}
121+
this.apiSSL = defaults.getBoolean(Defaults.API_SSL_KEY, true);
122+
String socketHost = defaults.getString(Defaults.SOCKET_HOST_KEY, null);
123+
if (socketHost != null) {
124+
this.socketHost = socketHost;
125+
}
126+
int socketPort = defaults.getInt(Defaults.SOCKET_PORT_KEY, 0);
127+
if (socketPort != 0) {
128+
this.socketPort = socketPort;
103129
}
104-
setToken(token);
105130
}
106131

107-
public void saveToken() {
132+
private void save() {
108133
Context context = Leanplum.getContext();
109134
SharedPreferences defaults = context.getSharedPreferences(
110135
Constants.Defaults.LEANPLUM, Context.MODE_PRIVATE);
111136
SharedPreferences.Editor editor = defaults.edit();
112-
editor.putString(Constants.Defaults.TOKEN_KEY, APIConfig.getInstance().token());
137+
138+
editor.putString(Defaults.TOKEN_KEY, this.token);
139+
editor.putString(Defaults.API_HOST_KEY, this.apiHost);
140+
editor.putString(Defaults.API_PATH_KEY, this.apiPath);
141+
editor.putBoolean(Defaults.API_SSL_KEY, this.apiSSL);
142+
editor.putString(Defaults.SOCKET_HOST_KEY, this.socketHost);
143+
editor.putInt(Defaults.SOCKET_PORT_KEY, this.socketPort);
144+
113145
SharedPreferencesUtil.commitChanges(editor);
114146
}
115147

@@ -124,4 +156,43 @@ public boolean attachApiKeys(Map<String, Object> dict) {
124156
dict.put(Constants.Params.CLIENT, Constants.CLIENT);
125157
return true;
126158
}
159+
160+
public void setApiConfig(String apiHost, String apiPath, boolean apiSSL) {
161+
if (!TextUtils.isEmpty(apiHost)) {
162+
this.apiHost = apiHost;
163+
}
164+
if (!TextUtils.isEmpty(apiPath)) {
165+
this.apiPath = apiPath;
166+
}
167+
this.apiSSL = apiSSL;
168+
save();
169+
}
170+
171+
public void setSocketConfig(String socketHost, int socketPort) {
172+
if (!TextUtils.isEmpty(socketHost)) {
173+
this.socketHost = socketHost;
174+
this.socketPort = socketPort;
175+
save();
176+
}
177+
}
178+
179+
public String getApiHost() {
180+
return this.apiHost;
181+
}
182+
183+
public String getApiPath() {
184+
return this.apiPath;
185+
}
186+
187+
public String getSocketHost() {
188+
return this.socketHost;
189+
}
190+
191+
public int getSocketPort() {
192+
return this.socketPort;
193+
}
194+
195+
public boolean getApiSSL() {
196+
return this.apiSSL;
197+
}
127198
}

AndroidSDKCore/src/main/java/com/leanplum/internal/Constants.java

Lines changed: 8 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,11 +29,6 @@
2929
* @author Andrew First.
3030
*/
3131
public class Constants {
32-
public static String API_HOST_NAME = "api.leanplum.com";
33-
public static String API_SERVLET = "api";
34-
public static boolean API_SSL = true;
35-
public static String SOCKET_HOST = "dev.leanplum.com";
36-
public static int SOCKET_PORT = 443;
3732
public static int NETWORK_TIMEOUT_SECONDS = 10;
3833
public static int NETWORK_TIMEOUT_SECONDS_FOR_DOWNLOADS = 10;
3934
public static String LEANPLUM_VERSION = BuildConfig.SDK_VERSION;
@@ -76,6 +71,11 @@ public static class Defaults {
7671
public static final String VARIABLES_SIGN_KEY = "__leanplum_variables_signature";
7772
public static final String ATTRIBUTES_KEY = "__leanplum_attributes";
7873
public static final String TOKEN_KEY = "__leanplum_token";
74+
public static final String API_HOST_KEY = "__leanplum_api_host";
75+
public static final String API_PATH_KEY = "__leanplum_api_path";
76+
public static final String API_SSL_KEY = "__leanplum_api_ssl";
77+
public static final String SOCKET_HOST_KEY = "__leanplum_socket_host";
78+
public static final String SOCKET_PORT_KEY = "__leanplum_socket_port";
7979
public static final String MESSAGES_KEY = "__leanplum_messages";
8080
public static final String REGIONS_KEY = "regions";
8181
public static final String MESSAGING_PREF_NAME = "__leanplum_messaging__";
@@ -155,6 +155,9 @@ public static class Params {
155155
public static final String VERSION_NAME = "versionName";
156156
public static final String REQUEST_ID = "reqId";
157157
public static final String STACK_TRACE = "stackTrace";
158+
public static final String API_HOST = "apiHost";
159+
public static final String API_PATH = "apiPath";
160+
public static final String DEV_SERVER_HOST = "devServerHost";
158161
}
159162

160163
public static class Keys {

AndroidSDKCore/src/main/java/com/leanplum/internal/FileTransferManager.java

Lines changed: 7 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -99,7 +99,9 @@ void downloadFile(
9999
@Override
100100
public void run() {
101101
try {
102-
downloadHelper(request, Constants.API_HOST_NAME, Constants.API_SERVLET, path, url, dict);
102+
String apiHost = APIConfig.getInstance().getApiHost();
103+
String apiPath = APIConfig.getInstance().getApiPath();
104+
downloadHelper(request, apiHost, apiPath, path, url, dict);
103105
} catch (Throwable t) {
104106
Log.exception(t);
105107
}
@@ -125,7 +127,7 @@ private void downloadHelper(
125127
servlet,
126128
dict,
127129
httpMethod,
128-
Constants.API_SSL,
130+
APIConfig.getInstance().getApiSSL(),
129131
Constants.NETWORK_TIMEOUT_SECONDS_FOR_DOWNLOADS);
130132
} else {
131133
op = new NetworkOperation(
@@ -251,10 +253,10 @@ public void run() {
251253

252254
try {
253255
op = new UploadOperation(
254-
Constants.API_HOST_NAME,
255-
Constants.API_SERVLET,
256+
APIConfig.getInstance().getApiHost(),
257+
APIConfig.getInstance().getApiPath(),
256258
request.getHttpMethod(),
257-
Constants.API_SSL,
259+
APIConfig.getInstance().getApiSSL(),
258260
60);
259261

260262
if (op.uploadFiles(filesToUpload, streams, dict)) {

AndroidSDKCore/src/main/java/com/leanplum/internal/LeanplumInternal.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -583,14 +583,30 @@ public void onResponse(boolean success) {
583583
if (!success) {
584584
return;
585585
}
586-
if (Constants.isDevelopmentModeEnabled && !Constants.isNoop()) {
587-
Socket.getInstance();
588-
}
589586
maybePerformActions(new String[] {"start", "resume"}, null,
590587
LeanplumMessageMatchFilter.LEANPLUM_ACTION_FILTER_ALL, null, null);
591588
recordAttributeChanges();
592589
}
593590
});
591+
592+
connectDevelopmentServer();
593+
}
594+
595+
public static void connectDevelopmentServer() {
596+
Leanplum.addStartResponseHandler(new StartCallback() {
597+
@Override
598+
public void onResponse(boolean success) {
599+
if (!success) {
600+
return;
601+
}
602+
if (!inForeground) {
603+
return;
604+
}
605+
if (Constants.isDevelopmentModeEnabled && !Constants.isNoop()) {
606+
Socket.connectSocket();
607+
}
608+
}
609+
});
594610
}
595611

596612
public static void addStartIssuedHandler(Runnable handler) {

AndroidSDKCore/src/main/java/com/leanplum/internal/RequestSender.java

Lines changed: 9 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -130,17 +130,23 @@ public void sendRequests() {
130130
try {
131131
try {
132132
op = new NetworkOperation(
133-
Constants.API_HOST_NAME,
134-
Constants.API_SERVLET,
133+
APIConfig.getInstance().getApiHost(),
134+
APIConfig.getInstance().getApiPath(),
135135
multiRequestArgs,
136136
RequestBuilder.POST,
137-
Constants.API_SSL,
137+
APIConfig.getInstance().getApiSSL(),
138138
Constants.NETWORK_TIMEOUT_SECONDS);
139139

140140
JSONObject responseBody = op.getJsonResponse();
141141
int statusCode = op.getResponseCode();
142142

143143
if (statusCode >= 200 && statusCode <= 299) {
144+
if (RequestUtil.updateApiConfig(responseBody)) {
145+
// API config is changed and we need to send requests again
146+
sendRequests();
147+
return;
148+
}
149+
144150
// Parse response body and trigger callbacks
145151
invokeCallbacks(responseBody);
146152

0 commit comments

Comments
 (0)