Network Service
Overview
The NetworkService
provides shared functionality to make asynchronous network requests and handle their responses.
Usage
The following code snippet details how to make a simple network request and handle the response.
Java
Copied to your clipboardimport com.adobe.marketing.mobile.services.NetworkRequest;import com.adobe.marketing.mobile.services.ServiceProvider;final int CONNECTION_TIMEOUT_MS = 5000;final int READ_TIMEOUT_MS = 5000;final String URL_TO_CONNECT = "URL_TO_CONNNECT_TO";final byte[] body = "SampleRequestBody".getBytes(StandardCharsets.UTF_8);final Map<String, String> headers = new HashMap<>();headers.put("myCustomHeaderName", "myCustomHeaderValue");// Create a NetworkRequestfinal NetworkRequest networkRequest = new NetworkRequest(URL_TO_CONNECT, HttpMethod.GET, body, headers, CONNECTION_TIMEOUT_MS, READ_TIMEOUT_MS);// Make the requestServiceProvider.getInstance().getNetworkService().connectAsync(networkRequest, response -> {// handle connection response// close the responseif (response != null) {response.close();}});
Copied to your clipboard/*** A sample implementation of Networking to enable overriding the default implementation of network service.*/class MyCustomNetworkService implements Networking {private final ExecutorService executorService = ///*** Initiate an asynchronous network request.** @param request {@link NetworkRequest} used for network connection* @param callback {@link NetworkCallback} that will receive the {@link HttpConnecting} instance asynchronously.**/@Overridepublic void connectAsync(final NetworkRequest request, final NetworkCallback callback) {// Use an executor service for initiating the network request and dispatching the response.executorService.submit(() -> {try {// 1. If the network is down, for example, if the device is in airplane mode, the callback should be invoked immediately with a null connection. When the null connection is passed to the callback, the SDK will treat it as a recoverable failure and handle it accordingly.// callback.call(null);// 2. If the network is available, the SDK should send out the request and invoke the callback with the corresponding connection.final HttpConnecting connection = doConnection(request);if (callback != null) {// If a callback was provided, invoke the callback with the connectioncallback.call(connection);} else {// If no callback is passed by the client, close the connection.connection.close();}} catch (Exception e) {// 3. The connectAsync method should never throw exceptions. Catch any exceptions and invoke the callback with an error response.if (callback != null) {callback.call(new ErrorResponse());}}});}/*** Utility method to perform the network connection.* @praram - the `NetworkRequest` whose details should be used for connecting** @return `MyCustomResponse` after making a connection*/private MyCustomResponse doConnection(final NetworkRequest request) {HttpsURLConnection connection = null;try {final URL obj = new URL(request.getUrl());connection = (HttpsURLConnection) obj.openConnection();// Set the request methodconnection.setRequestMethod(request.getMethod().toString());// Set the read and connect timeoutsconnection.setConnectTimeout(request.getConnectTimeout());connection.setReadTimeout(request.getReadTimeout());// set the request propertiesfinal Set<Map.Entry<String, String>> entries = request.getHeaders().entrySet();for (Map.Entry<String, String> entry : entries) {connection.setRequestProperty(entry.getKey(), entry.getValue());}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH) {connection.setSSLSocketFactory(TLSSocketFactory.getInstance());}final boolean isPostRequest = "POST".equalsIgnoreCase(connection.getRequestMethod());if (isPostRequest && request.getBody() != null) {// If the method is POST, set the length before connectionconnection.setFixedLengthStreamingMode(request.getBody().length);}connection.connect();// if the command is POST, send the data to the URL.if (isPostRequest && request.getBody() != null) {// Consume the payloadfinal OutputStream os = new BufferedOutputStream(connection.getOutputStream());os.write(request.getBody());os.flush();os.close();}} catch (Exception e) {// handle exceptions}// create and return a response object conforming to the `HttpConnecting` interface.return new MyCustomResponse(connection);}}
- Override the default implementation of
NetworkService
provided byServiceProvider
. This step should occur prior to any other interactions with the SDK. While it is possible to register the network override at any point during the application lifecycle, the override will only function for network requests performed after the registration has taken place.
Copied to your clipboardpublic class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Set the network override prior to making any other calls to the SDKServiceProvider.getInstance().setNetworkService(new MyCustomNetworkService());MobileCore.setApplication(this);List<Class<? extends Extension>> extensions = Arrays.asList(...);MobileCore.registerExtensions(extensions, o -> {// Any other post registration processing});}}
Swift
Copied to your clipboardimport AEPServices// Create your `NetworkRequest`, for more details see `NetworkRequest.swift`let networkRequest = NetworkRequest(url: url, httpMethod: .get, httpHeaders: headers)// Get an instance of the current network servicelet networkService = ServiceProvider.shared.networkService// Make a requestnetworkService.connectAsync(networkRequest: networkRequest) { httpConnection in// handle `httpConnection`}
Copied to your clipboard/*** A sample implementation of Networking to enable overriding the default implementation of network service.*/class MyCustomNetworkService implements Networking {private final ExecutorService executorService = ///*** Initiate an asynchronous network request.** @param request {@link NetworkRequest} used for network connection* @param callback {@link NetworkCallback} that will receive the {@link HttpConnecting} instance asynchronously.**/@Overridepublic void connectAsync(final NetworkRequest request, final NetworkCallback callback) {// Use an executor service for initiating the network request and dispatching the response.executorService.submit(() -> {try {// 1. If the network is down, for example, if the device is in airplane mode, the callback should be invoked immediately with a null connection. When the null connection is passed to the callback, the SDK will treat it as a recoverable failure and handle it accordingly.// callback.call(null);// 2. If the network is available, the SDK should send out the request and invoke the callback with the corresponding connection.final HttpConnecting connection = doConnection(request);if (callback != null) {// If a callback was provided, invoke the callback with the connectioncallback.call(connection);} else {// If no callback is passed by the client, close the connection.connection.close();}} catch (Exception e) {// 3. The connectAsync method should never throw exceptions. Catch any exceptions and invoke the callback with an error response.if (callback != null) {callback.call(new ErrorResponse());}}});}/*** Utility method to perform the network connection.* @praram - the `NetworkRequest` whose details should be used for connecting** @return `MyCustomResponse` after making a connection*/private MyCustomResponse doConnection(final NetworkRequest request) {HttpsURLConnection connection = null;try {final URL obj = new URL(request.getUrl());connection = (HttpsURLConnection) obj.openConnection();// Set the request methodconnection.setRequestMethod(request.getMethod().toString());// Set the read and connect timeoutsconnection.setConnectTimeout(request.getConnectTimeout());connection.setReadTimeout(request.getReadTimeout());// set the request propertiesfinal Set<Map.Entry<String, String>> entries = request.getHeaders().entrySet();for (Map.Entry<String, String> entry : entries) {connection.setRequestProperty(entry.getKey(), entry.getValue());}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH) {connection.setSSLSocketFactory(TLSSocketFactory.getInstance());}final boolean isPostRequest = "POST".equalsIgnoreCase(connection.getRequestMethod());if (isPostRequest && request.getBody() != null) {// If the method is POST, set the length before connectionconnection.setFixedLengthStreamingMode(request.getBody().length);}connection.connect();// if the command is POST, send the data to the URL.if (isPostRequest && request.getBody() != null) {// Consume the payloadfinal OutputStream os = new BufferedOutputStream(connection.getOutputStream());os.write(request.getBody());os.flush();os.close();}} catch (Exception e) {// handle exceptions}// create and return a response object conforming to the `HttpConnecting` interface.return new MyCustomResponse(connection);}}
- Override the default implementation of
NetworkService
provided byServiceProvider
. This step should occur prior to any other interactions with the SDK. While it is possible to register the network override at any point during the application lifecycle, the override will only function for network requests performed after the registration has taken place.
Copied to your clipboardpublic class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Set the network override prior to making any other calls to the SDKServiceProvider.getInstance().setNetworkService(new MyCustomNetworkService());MobileCore.setApplication(this);List<Class<? extends Extension>> extensions = Arrays.asList(...);MobileCore.registerExtensions(extensions, o -> {// Any other post registration processing});}}
Java
Copied to your clipboardimport com.adobe.marketing.mobile.services.NetworkRequest;import com.adobe.marketing.mobile.services.ServiceProvider;final int CONNECTION_TIMEOUT_MS = 5000;final int READ_TIMEOUT_MS = 5000;final String URL_TO_CONNECT = "URL_TO_CONNNECT_TO";final byte[] body = "SampleRequestBody".getBytes(StandardCharsets.UTF_8);final Map<String, String> headers = new HashMap<>();headers.put("myCustomHeaderName", "myCustomHeaderValue");// Create a NetworkRequestfinal NetworkRequest networkRequest = new NetworkRequest(URL_TO_CONNECT, HttpMethod.GET, body, headers, CONNECTION_TIMEOUT_MS, READ_TIMEOUT_MS);// Make the requestServiceProvider.getInstance().getNetworkService().connectAsync(networkRequest, response -> {// handle connection response// close the responseif (response != null) {response.close();}});
Copied to your clipboard/*** A sample implementation of Networking to enable overriding the default implementation of network service.*/class MyCustomNetworkService implements Networking {private final ExecutorService executorService = ///*** Initiate an asynchronous network request.** @param request {@link NetworkRequest} used for network connection* @param callback {@link NetworkCallback} that will receive the {@link HttpConnecting} instance asynchronously.**/@Overridepublic void connectAsync(final NetworkRequest request, final NetworkCallback callback) {// Use an executor service for initiating the network request and dispatching the response.executorService.submit(() -> {try {// 1. If the network is down, for example, if the device is in airplane mode, the callback should be invoked immediately with a null connection. When the null connection is passed to the callback, the SDK will treat it as a recoverable failure and handle it accordingly.// callback.call(null);// 2. If the network is available, the SDK should send out the request and invoke the callback with the corresponding connection.final HttpConnecting connection = doConnection(request);if (callback != null) {// If a callback was provided, invoke the callback with the connectioncallback.call(connection);} else {// If no callback is passed by the client, close the connection.connection.close();}} catch (Exception e) {// 3. The connectAsync method should never throw exceptions. Catch any exceptions and invoke the callback with an error response.if (callback != null) {callback.call(new ErrorResponse());}}});}/*** Utility method to perform the network connection.* @praram - the `NetworkRequest` whose details should be used for connecting** @return `MyCustomResponse` after making a connection*/private MyCustomResponse doConnection(final NetworkRequest request) {HttpsURLConnection connection = null;try {final URL obj = new URL(request.getUrl());connection = (HttpsURLConnection) obj.openConnection();// Set the request methodconnection.setRequestMethod(request.getMethod().toString());// Set the read and connect timeoutsconnection.setConnectTimeout(request.getConnectTimeout());connection.setReadTimeout(request.getReadTimeout());// set the request propertiesfinal Set<Map.Entry<String, String>> entries = request.getHeaders().entrySet();for (Map.Entry<String, String> entry : entries) {connection.setRequestProperty(entry.getKey(), entry.getValue());}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH) {connection.setSSLSocketFactory(TLSSocketFactory.getInstance());}final boolean isPostRequest = "POST".equalsIgnoreCase(connection.getRequestMethod());if (isPostRequest && request.getBody() != null) {// If the method is POST, set the length before connectionconnection.setFixedLengthStreamingMode(request.getBody().length);}connection.connect();// if the command is POST, send the data to the URL.if (isPostRequest && request.getBody() != null) {// Consume the payloadfinal OutputStream os = new BufferedOutputStream(connection.getOutputStream());os.write(request.getBody());os.flush();os.close();}} catch (Exception e) {// handle exceptions}// create and return a response object conforming to the `HttpConnecting` interface.return new MyCustomResponse(connection);}}
- Override the default implementation of
NetworkService
provided byServiceProvider
. This step should occur prior to any other interactions with the SDK. While it is possible to register the network override at any point during the application lifecycle, the override will only function for network requests performed after the registration has taken place.
Copied to your clipboardpublic class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Set the network override prior to making any other calls to the SDKServiceProvider.getInstance().setNetworkService(new MyCustomNetworkService());MobileCore.setApplication(this);List<Class<? extends Extension>> extensions = Arrays.asList(...);MobileCore.registerExtensions(extensions, o -> {// Any other post registration processing});}}
Swift
Copied to your clipboardimport AEPServices// Create your `NetworkRequest`, for more details see `NetworkRequest.swift`let networkRequest = NetworkRequest(url: url, httpMethod: .get, httpHeaders: headers)// Get an instance of the current network servicelet networkService = ServiceProvider.shared.networkService// Make a requestnetworkService.connectAsync(networkRequest: networkRequest) { httpConnection in// handle `httpConnection`}
Copied to your clipboard/*** A sample implementation of Networking to enable overriding the default implementation of network service.*/class MyCustomNetworkService implements Networking {private final ExecutorService executorService = ///*** Initiate an asynchronous network request.** @param request {@link NetworkRequest} used for network connection* @param callback {@link NetworkCallback} that will receive the {@link HttpConnecting} instance asynchronously.**/@Overridepublic void connectAsync(final NetworkRequest request, final NetworkCallback callback) {// Use an executor service for initiating the network request and dispatching the response.executorService.submit(() -> {try {// 1. If the network is down, for example, if the device is in airplane mode, the callback should be invoked immediately with a null connection. When the null connection is passed to the callback, the SDK will treat it as a recoverable failure and handle it accordingly.// callback.call(null);// 2. If the network is available, the SDK should send out the request and invoke the callback with the corresponding connection.final HttpConnecting connection = doConnection(request);if (callback != null) {// If a callback was provided, invoke the callback with the connectioncallback.call(connection);} else {// If no callback is passed by the client, close the connection.connection.close();}} catch (Exception e) {// 3. The connectAsync method should never throw exceptions. Catch any exceptions and invoke the callback with an error response.if (callback != null) {callback.call(new ErrorResponse());}}});}/*** Utility method to perform the network connection.* @praram - the `NetworkRequest` whose details should be used for connecting** @return `MyCustomResponse` after making a connection*/private MyCustomResponse doConnection(final NetworkRequest request) {HttpsURLConnection connection = null;try {final URL obj = new URL(request.getUrl());connection = (HttpsURLConnection) obj.openConnection();// Set the request methodconnection.setRequestMethod(request.getMethod().toString());// Set the read and connect timeoutsconnection.setConnectTimeout(request.getConnectTimeout());connection.setReadTimeout(request.getReadTimeout());// set the request propertiesfinal Set<Map.Entry<String, String>> entries = request.getHeaders().entrySet();for (Map.Entry<String, String> entry : entries) {connection.setRequestProperty(entry.getKey(), entry.getValue());}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH) {connection.setSSLSocketFactory(TLSSocketFactory.getInstance());}final boolean isPostRequest = "POST".equalsIgnoreCase(connection.getRequestMethod());if (isPostRequest && request.getBody() != null) {// If the method is POST, set the length before connectionconnection.setFixedLengthStreamingMode(request.getBody().length);}connection.connect();// if the command is POST, send the data to the URL.if (isPostRequest && request.getBody() != null) {// Consume the payloadfinal OutputStream os = new BufferedOutputStream(connection.getOutputStream());os.write(request.getBody());os.flush();os.close();}} catch (Exception e) {// handle exceptions}// create and return a response object conforming to the `HttpConnecting` interface.return new MyCustomResponse(connection);}}
- Override the default implementation of
NetworkService
provided byServiceProvider
. This step should occur prior to any other interactions with the SDK. While it is possible to register the network override at any point during the application lifecycle, the override will only function for network requests performed after the registration has taken place.
Copied to your clipboardpublic class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Set the network override prior to making any other calls to the SDKServiceProvider.getInstance().setNetworkService(new MyCustomNetworkService());MobileCore.setApplication(this);List<Class<? extends Extension>> extensions = Arrays.asList(...);MobileCore.registerExtensions(extensions, o -> {// Any other post registration processing});}}
Overriding NetworkService
The default implementation of the NetworkService
provided by the SDK can be overriden to use a custom implementation to cater to your app requirements. This section walks through the steps necessary to create a custom network override, and register it with the SDK.
Java
- Create a custom implementation of
HttpConnecting
that represents a response to a network request. Also, create antoher implementation ofHttpConnecting
that represents the error response. They will be used to handle network completion when overriding the network stack in place of internal network connection implementation.
- MyCustomResponse
Copied to your clipboardclass MyCustomResponse implements HttpConnecting {private final HttpsURLConnection connection;MyCustomResponse(final HttpsURLConnection connection) {this.connection = connection;}@Overridepublic InputStream getInputStream() {try {return connection.getInputStream();} catch (IOException e) {// handle exception}}@Overridepublic InputStream getErrorStream() {return connection.getErrorStream();}@Overridepublic int getResponseCode() {try {return connection.getResponseCode();} catch (IOException e) {// handle exception}}@Overridepublic String getResponseMessage() {try {return connection.getResponseMessage();} catch (IOException e) {// handle exception}}@Overridepublic String getResponsePropertyValue(String responsePropertyKey) {return connection.getHeaderField(responsePropertyKey);}@Overridepublic void close() {final InputStream inputStream = this.getInputStream();final InputStream errorStream = this.getErrorStream();if (inputStream != null) {try {inputStream.close();} catch (final Exception e) {// handle exceptions}}if (errorStream != null) {try {errorStream.close();} catch (final Exception e) {// handle exceptions}connection.disconnect();}}}
- ErrorResponse
Copied to your clipboardclass ErrorResponse implements HttpConnecting {@Overridepublic InputStream getInputStream() {return null;}@Overridepublic InputStream getErrorStream() {return null;}@Overridepublic int getResponseCode() {return -1;}@Overridepublic String getResponseMessage() {return "";}@Overridepublic String getResponsePropertyValue(String responsePropertyKey) {return "";}@Overridepublic void close() { }}
- Create a custom implementation of
Networking
interface and, implement theconnectAsync
method. The implementation ofconnectAsync
should handle the connection establishment with the details provided in theNetworkRequest
and, notify the caller of a response using theNetworkCallback
parameter.
Copied to your clipboard/*** A sample implementation of Networking to enable overriding the default implementation of network service.*/class MyCustomNetworkService implements Networking {private final ExecutorService executorService = ///*** Initiate an asynchronous network request.** @param request {@link NetworkRequest} used for network connection* @param callback {@link NetworkCallback} that will receive the {@link HttpConnecting} instance asynchronously.**/@Overridepublic void connectAsync(final NetworkRequest request, final NetworkCallback callback) {// Use an executor service for initiating the network request and dispatching the response.executorService.submit(() -> {try {// 1. If the network is down, for example, if the device is in airplane mode, the callback should be invoked immediately with a null connection. When the null connection is passed to the callback, the SDK will treat it as a recoverable failure and handle it accordingly.// callback.call(null);// 2. If the network is available, the SDK should send out the request and invoke the callback with the corresponding connection.final HttpConnecting connection = doConnection(request);if (callback != null) {// If a callback was provided, invoke the callback with the connectioncallback.call(connection);} else {// If no callback is passed by the client, close the connection.connection.close();}} catch (Exception e) {// 3. The connectAsync method should never throw exceptions. Catch any exceptions and invoke the callback with an error response.if (callback != null) {callback.call(new ErrorResponse());}}});}/*** Utility method to perform the network connection.* @praram - the `NetworkRequest` whose details should be used for connecting** @return `MyCustomResponse` after making a connection*/private MyCustomResponse doConnection(final NetworkRequest request) {HttpsURLConnection connection = null;try {final URL obj = new URL(request.getUrl());connection = (HttpsURLConnection) obj.openConnection();// Set the request methodconnection.setRequestMethod(request.getMethod().toString());// Set the read and connect timeoutsconnection.setConnectTimeout(request.getConnectTimeout());connection.setReadTimeout(request.getReadTimeout());// set the request propertiesfinal Set<Map.Entry<String, String>> entries = request.getHeaders().entrySet();for (Map.Entry<String, String> entry : entries) {connection.setRequestProperty(entry.getKey(), entry.getValue());}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH) {connection.setSSLSocketFactory(TLSSocketFactory.getInstance());}final boolean isPostRequest = "POST".equalsIgnoreCase(connection.getRequestMethod());if (isPostRequest && request.getBody() != null) {// If the method is POST, set the length before connectionconnection.setFixedLengthStreamingMode(request.getBody().length);}connection.connect();// if the command is POST, send the data to the URL.if (isPostRequest && request.getBody() != null) {// Consume the payloadfinal OutputStream os = new BufferedOutputStream(connection.getOutputStream());os.write(request.getBody());os.flush();os.close();}} catch (Exception e) {// handle exceptions}// create and return a response object conforming to the `HttpConnecting` interface.return new MyCustomResponse(connection);}}
- Override the default implementation of
NetworkService
provided byServiceProvider
. This step should occur prior to any other interactions with the SDK. While it is possible to register the network override at any point during the application lifecycle, the override will only function for network requests performed after the registration has taken place.
Copied to your clipboardpublic class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Set the network override prior to making any other calls to the SDKServiceProvider.getInstance().setNetworkService(new MyCustomNetworkService());MobileCore.setApplication(this);List<Class<? extends Extension>> extensions = Arrays.asList(...);MobileCore.registerExtensions(extensions, o -> {// Any other post registration processing});}}
Copied to your clipboard/*** A sample implementation of Networking to enable overriding the default implementation of network service.*/class MyCustomNetworkService implements Networking {private final ExecutorService executorService = ///*** Initiate an asynchronous network request.** @param request {@link NetworkRequest} used for network connection* @param callback {@link NetworkCallback} that will receive the {@link HttpConnecting} instance asynchronously.**/@Overridepublic void connectAsync(final NetworkRequest request, final NetworkCallback callback) {// Use an executor service for initiating the network request and dispatching the response.executorService.submit(() -> {try {// 1. If the network is down, for example, if the device is in airplane mode, the callback should be invoked immediately with a null connection. When the null connection is passed to the callback, the SDK will treat it as a recoverable failure and handle it accordingly.// callback.call(null);// 2. If the network is available, the SDK should send out the request and invoke the callback with the corresponding connection.final HttpConnecting connection = doConnection(request);if (callback != null) {// If a callback was provided, invoke the callback with the connectioncallback.call(connection);} else {// If no callback is passed by the client, close the connection.connection.close();}} catch (Exception e) {// 3. The connectAsync method should never throw exceptions. Catch any exceptions and invoke the callback with an error response.if (callback != null) {callback.call(new ErrorResponse());}}});}/*** Utility method to perform the network connection.* @praram - the `NetworkRequest` whose details should be used for connecting** @return `MyCustomResponse` after making a connection*/private MyCustomResponse doConnection(final NetworkRequest request) {HttpsURLConnection connection = null;try {final URL obj = new URL(request.getUrl());connection = (HttpsURLConnection) obj.openConnection();// Set the request methodconnection.setRequestMethod(request.getMethod().toString());// Set the read and connect timeoutsconnection.setConnectTimeout(request.getConnectTimeout());connection.setReadTimeout(request.getReadTimeout());// set the request propertiesfinal Set<Map.Entry<String, String>> entries = request.getHeaders().entrySet();for (Map.Entry<String, String> entry : entries) {connection.setRequestProperty(entry.getKey(), entry.getValue());}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH) {connection.setSSLSocketFactory(TLSSocketFactory.getInstance());}final boolean isPostRequest = "POST".equalsIgnoreCase(connection.getRequestMethod());if (isPostRequest && request.getBody() != null) {// If the method is POST, set the length before connectionconnection.setFixedLengthStreamingMode(request.getBody().length);}connection.connect();// if the command is POST, send the data to the URL.if (isPostRequest && request.getBody() != null) {// Consume the payloadfinal OutputStream os = new BufferedOutputStream(connection.getOutputStream());os.write(request.getBody());os.flush();os.close();}} catch (Exception e) {// handle exceptions}// create and return a response object conforming to the `HttpConnecting` interface.return new MyCustomResponse(connection);}}
- Override the default implementation of
NetworkService
provided byServiceProvider
. This step should occur prior to any other interactions with the SDK. While it is possible to register the network override at any point during the application lifecycle, the override will only function for network requests performed after the registration has taken place.
Copied to your clipboardpublic class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Set the network override prior to making any other calls to the SDKServiceProvider.getInstance().setNetworkService(new MyCustomNetworkService());MobileCore.setApplication(this);List<Class<? extends Extension>> extensions = Arrays.asList(...);MobileCore.registerExtensions(extensions, o -> {// Any other post registration processing});}}
Swift
First, you must implement the Networking
protocol which has just one method: connectAsync(networkRequest: completionHandler:)
. Your implementation will probably be more robust, but the important aspects are highlighted below.
- You must use the
AEPServices.NetworkRequest
to pass the relevant data needed to start a network request. - You must call the completionHandler with an
AEPServices.HttpConnection
Copied to your clipboardimport AEPServicesclass SampleNetworkOverride: Networking {func connectAsync(networkRequest: AEPServices.NetworkRequest, completionHandler: ((AEPServices.HttpConnection) -> Void)?) {let urlRequest = URLRequest(url: networkRequest.url)let urlSession = URLSession(configuration: .default)let task = urlSession.dataTask(with: urlRequest) { data, response, error inif let completionHandler = completionHandler {let httpConnection = HttpConnection(data: data, response: response as? HTTPURLResponse, error: error)completionHandler(httpConnection)}}task.resume()}}
Once you have implemented the Networking
protocol, all that's left is to override the ServiceProvider's NetworkService as follows:
Copied to your clipboardServiceProvider.shared.networkService = SampleNetworkOverride()
If you would like to revert back to the default NetworkService
, set the networkService
to nil.
Copied to your clipboardServiceProvider.shared.networkService = nil
Java
- Create a custom implementation of
HttpConnecting
that represents a response to a network request. Also, create antoher implementation ofHttpConnecting
that represents the error response. They will be used to handle network completion when overriding the network stack in place of internal network connection implementation.
- MyCustomResponse
Copied to your clipboardclass MyCustomResponse implements HttpConnecting {private final HttpsURLConnection connection;MyCustomResponse(final HttpsURLConnection connection) {this.connection = connection;}@Overridepublic InputStream getInputStream() {try {return connection.getInputStream();} catch (IOException e) {// handle exception}}@Overridepublic InputStream getErrorStream() {return connection.getErrorStream();}@Overridepublic int getResponseCode() {try {return connection.getResponseCode();} catch (IOException e) {// handle exception}}@Overridepublic String getResponseMessage() {try {return connection.getResponseMessage();} catch (IOException e) {// handle exception}}@Overridepublic String getResponsePropertyValue(String responsePropertyKey) {return connection.getHeaderField(responsePropertyKey);}@Overridepublic void close() {final InputStream inputStream = this.getInputStream();final InputStream errorStream = this.getErrorStream();if (inputStream != null) {try {inputStream.close();} catch (final Exception e) {// handle exceptions}}if (errorStream != null) {try {errorStream.close();} catch (final Exception e) {// handle exceptions}connection.disconnect();}}}
- ErrorResponse
Copied to your clipboardclass ErrorResponse implements HttpConnecting {@Overridepublic InputStream getInputStream() {return null;}@Overridepublic InputStream getErrorStream() {return null;}@Overridepublic int getResponseCode() {return -1;}@Overridepublic String getResponseMessage() {return "";}@Overridepublic String getResponsePropertyValue(String responsePropertyKey) {return "";}@Overridepublic void close() { }}
- Create a custom implementation of
Networking
interface and, implement theconnectAsync
method. The implementation ofconnectAsync
should handle the connection establishment with the details provided in theNetworkRequest
and, notify the caller of a response using theNetworkCallback
parameter.
Copied to your clipboard/*** A sample implementation of Networking to enable overriding the default implementation of network service.*/class MyCustomNetworkService implements Networking {private final ExecutorService executorService = ///*** Initiate an asynchronous network request.** @param request {@link NetworkRequest} used for network connection* @param callback {@link NetworkCallback} that will receive the {@link HttpConnecting} instance asynchronously.**/@Overridepublic void connectAsync(final NetworkRequest request, final NetworkCallback callback) {// Use an executor service for initiating the network request and dispatching the response.executorService.submit(() -> {try {// 1. If the network is down, for example, if the device is in airplane mode, the callback should be invoked immediately with a null connection. When the null connection is passed to the callback, the SDK will treat it as a recoverable failure and handle it accordingly.// callback.call(null);// 2. If the network is available, the SDK should send out the request and invoke the callback with the corresponding connection.final HttpConnecting connection = doConnection(request);if (callback != null) {// If a callback was provided, invoke the callback with the connectioncallback.call(connection);} else {// If no callback is passed by the client, close the connection.connection.close();}} catch (Exception e) {// 3. The connectAsync method should never throw exceptions. Catch any exceptions and invoke the callback with an error response.if (callback != null) {callback.call(new ErrorResponse());}}});}/*** Utility method to perform the network connection.* @praram - the `NetworkRequest` whose details should be used for connecting** @return `MyCustomResponse` after making a connection*/private MyCustomResponse doConnection(final NetworkRequest request) {HttpsURLConnection connection = null;try {final URL obj = new URL(request.getUrl());connection = (HttpsURLConnection) obj.openConnection();// Set the request methodconnection.setRequestMethod(request.getMethod().toString());// Set the read and connect timeoutsconnection.setConnectTimeout(request.getConnectTimeout());connection.setReadTimeout(request.getReadTimeout());// set the request propertiesfinal Set<Map.Entry<String, String>> entries = request.getHeaders().entrySet();for (Map.Entry<String, String> entry : entries) {connection.setRequestProperty(entry.getKey(), entry.getValue());}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH) {connection.setSSLSocketFactory(TLSSocketFactory.getInstance());}final boolean isPostRequest = "POST".equalsIgnoreCase(connection.getRequestMethod());if (isPostRequest && request.getBody() != null) {// If the method is POST, set the length before connectionconnection.setFixedLengthStreamingMode(request.getBody().length);}connection.connect();// if the command is POST, send the data to the URL.if (isPostRequest && request.getBody() != null) {// Consume the payloadfinal OutputStream os = new BufferedOutputStream(connection.getOutputStream());os.write(request.getBody());os.flush();os.close();}} catch (Exception e) {// handle exceptions}// create and return a response object conforming to the `HttpConnecting` interface.return new MyCustomResponse(connection);}}
- Override the default implementation of
NetworkService
provided byServiceProvider
. This step should occur prior to any other interactions with the SDK. While it is possible to register the network override at any point during the application lifecycle, the override will only function for network requests performed after the registration has taken place.
Copied to your clipboardpublic class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Set the network override prior to making any other calls to the SDKServiceProvider.getInstance().setNetworkService(new MyCustomNetworkService());MobileCore.setApplication(this);List<Class<? extends Extension>> extensions = Arrays.asList(...);MobileCore.registerExtensions(extensions, o -> {// Any other post registration processing});}}
Copied to your clipboard/*** A sample implementation of Networking to enable overriding the default implementation of network service.*/class MyCustomNetworkService implements Networking {private final ExecutorService executorService = ///*** Initiate an asynchronous network request.** @param request {@link NetworkRequest} used for network connection* @param callback {@link NetworkCallback} that will receive the {@link HttpConnecting} instance asynchronously.**/@Overridepublic void connectAsync(final NetworkRequest request, final NetworkCallback callback) {// Use an executor service for initiating the network request and dispatching the response.executorService.submit(() -> {try {// 1. If the network is down, for example, if the device is in airplane mode, the callback should be invoked immediately with a null connection. When the null connection is passed to the callback, the SDK will treat it as a recoverable failure and handle it accordingly.// callback.call(null);// 2. If the network is available, the SDK should send out the request and invoke the callback with the corresponding connection.final HttpConnecting connection = doConnection(request);if (callback != null) {// If a callback was provided, invoke the callback with the connectioncallback.call(connection);} else {// If no callback is passed by the client, close the connection.connection.close();}} catch (Exception e) {// 3. The connectAsync method should never throw exceptions. Catch any exceptions and invoke the callback with an error response.if (callback != null) {callback.call(new ErrorResponse());}}});}/*** Utility method to perform the network connection.* @praram - the `NetworkRequest` whose details should be used for connecting** @return `MyCustomResponse` after making a connection*/private MyCustomResponse doConnection(final NetworkRequest request) {HttpsURLConnection connection = null;try {final URL obj = new URL(request.getUrl());connection = (HttpsURLConnection) obj.openConnection();// Set the request methodconnection.setRequestMethod(request.getMethod().toString());// Set the read and connect timeoutsconnection.setConnectTimeout(request.getConnectTimeout());connection.setReadTimeout(request.getReadTimeout());// set the request propertiesfinal Set<Map.Entry<String, String>> entries = request.getHeaders().entrySet();for (Map.Entry<String, String> entry : entries) {connection.setRequestProperty(entry.getKey(), entry.getValue());}if (Build.VERSION.SDK_INT < Build.VERSION_CODES.KITKAT_WATCH) {connection.setSSLSocketFactory(TLSSocketFactory.getInstance());}final boolean isPostRequest = "POST".equalsIgnoreCase(connection.getRequestMethod());if (isPostRequest && request.getBody() != null) {// If the method is POST, set the length before connectionconnection.setFixedLengthStreamingMode(request.getBody().length);}connection.connect();// if the command is POST, send the data to the URL.if (isPostRequest && request.getBody() != null) {// Consume the payloadfinal OutputStream os = new BufferedOutputStream(connection.getOutputStream());os.write(request.getBody());os.flush();os.close();}} catch (Exception e) {// handle exceptions}// create and return a response object conforming to the `HttpConnecting` interface.return new MyCustomResponse(connection);}}
- Override the default implementation of
NetworkService
provided byServiceProvider
. This step should occur prior to any other interactions with the SDK. While it is possible to register the network override at any point during the application lifecycle, the override will only function for network requests performed after the registration has taken place.
Copied to your clipboardpublic class MyApp extends Application {@Overridepublic void onCreate() {super.onCreate();// Set the network override prior to making any other calls to the SDKServiceProvider.getInstance().setNetworkService(new MyCustomNetworkService());MobileCore.setApplication(this);List<Class<? extends Extension>> extensions = Arrays.asList(...);MobileCore.registerExtensions(extensions, o -> {// Any other post registration processing});}}
Swift
First, you must implement the Networking
protocol which has just one method: connectAsync(networkRequest: completionHandler:)
. Your implementation will probably be more robust, but the important aspects are highlighted below.
- You must use the
AEPServices.NetworkRequest
to pass the relevant data needed to start a network request. - You must call the completionHandler with an
AEPServices.HttpConnection
Copied to your clipboardimport AEPServicesclass SampleNetworkOverride: Networking {func connectAsync(networkRequest: AEPServices.NetworkRequest, completionHandler: ((AEPServices.HttpConnection) -> Void)?) {let urlRequest = URLRequest(url: networkRequest.url)let urlSession = URLSession(configuration: .default)let task = urlSession.dataTask(with: urlRequest) { data, response, error inif let completionHandler = completionHandler {let httpConnection = HttpConnection(data: data, response: response as? HTTPURLResponse, error: error)completionHandler(httpConnection)}}task.resume()}}
Once you have implemented the Networking
protocol, all that's left is to override the ServiceProvider's NetworkService as follows:
Copied to your clipboardServiceProvider.shared.networkService = SampleNetworkOverride()
If you would like to revert back to the default NetworkService
, set the networkService
to nil.
Copied to your clipboardServiceProvider.shared.networkService = nil