All traffic on all operating systems will favor WiFi above cellular connections. However for Silent Network Auth, the API request must be made using the cellular connection. We realize that users are unlikely to turn off WiFi and so the following code is provided for both iOS and Android to include in your applications that will allow a small payload (~40 bytes) to be delivered over the cellular modem, even when WiFi is connected.
This article is for apps only.
Only downloadable and installable applications are suitable for this fix. If you are attempting to use Silent Network Auth in a website this solution will not work. You should instruct users to turn off WiFi.
The following will allow Android applications using API Release M and above to use Cellular for the Silent Network Auth API request.
_26@TargetApi(Build.VERSION_CODES.LOLLIPOP)_26public static void doAPIonCellularNetwork(Context context, final String url) {_26_26 ConnectivityManager connectivityManager = (ConnectivityManager) context.getSystemService(CONNECTIVITY_SERVICE);_26_26 NetworkRequest request = new NetworkRequest.Builder()_26 .addTransportType(NetworkCapabilities.TRANSPORT_CELLULAR)_26 .addCapability(NetworkCapabilities.NET_CAPABILITY_INTERNET).build();_26_26 connectivityManager.requestNetwork(request, new ConnectivityManager.NetworkCallback() {_26_26 @Override_26 public void onAvailable(final Network network) {_26 OkHttpClient okHttpClient = new OkHttpClient.Builder().socketFactory(network.getSocketFactory()).build();_26 Request request = new Request.Builder()_26 .url(url)_26 .build();_26 try {_26 Response response = okHttpClient.newCall(request).execute();_26 Log.i("", "doAPIonCellularNetwork RESULT:\n" + response.body().string());_26 } catch (Exception ex) {_26 ex.printStackTrace();_26 }_26 }_26 });_26 }
For iOS, start by downloading the library from here.
Add the NetworkingLogic folder, which contains six files, to your project folder as shown below.
Include #import "HTTPRequester.h
in the Swift bridging header file. Also, include the code below as a member function in the ViewController that fires the EVURL.
_56//_56// EvurlRequestWithCellularData.swift_56//_56// Created by BENJAMIN BRYANT BUDIMAN on 05/09/18._56// Copyright © 2021 Boku, Inc. All rights reserved._56//_56_56import Foundation_56_56/**_56Requests the EvURL with cellular data, and checks whether the Silent Network Auth process completes or not._56Important note: this function shall always return false if cellular data is not available._56_56 - Parameter evurl: The EvURL to be requested_56 - Returns: true if the Silent Network Auth process is successful and vice versa_56 */_56func requestEvurlWithCellularData(evurl:String) -> Bool {_56 let response = requestHelper(url: evurl)_56_56 // If any internal and network errors occured in HTTPRequester.performGetRequest, the function will return "ERROR"_56 if response == "ERROR" {_56 return false;_56 }_56_56 // Boku returns "ErrorCode=0&ErrorDescription=Success" only when the Silent Network Auth process is complete_56 if response.range(of:"ErrorCode=0&ErrorDescription=Success") != nil {_56 return true;_56 }_56_56 // Any HTTP responses without the above substring indicate an incomplete Silent Network Auth process_56 return false;_56}_56_56/**_56 Recursive function that keeps requesting a new URL with cellular data when the HTTP request returns a HTTP redirect code (3xx)_56 _56 - Parameter url: The URL to be requested_56 - Returns: string response from the HTTP request_56 */_56func requestHelper(url:String) -> String {_56 // If the HTTP GET request returns a HTTP redirect code (3xx), HTTPRequester.performGetRequest returns a_56 // formatted string that contains the redirect URL. The formatted string starts with "REDIRECT:"_56 // and it's followed with the redirect URL (e.g. REDIRECT:https://www.boku.com)_56 var response = HTTPRequester.performGetRequest(URL(string: url))_56_56 if response!.range(of:"REDIRECT:") != nil {_56 // 1. Get the redirect URL by getting rid of the "REDIRECT:" substring_56 let redirectRange = response!.index(response!.startIndex, offsetBy: 9)..._56 let redirectLink = String(response![redirectRange])_56_56 // 2. Make a request to the redirect URL_56 response = requestHelper(url: redirectLink)_56 }_56_56 return response!_56}
Execute the EVURL as shown in the code sample below. Please note the EVURL will change and must be created each time.
_10override func viewDidLoad() {_10 super.viewDidLoad()_10_10 let EVURL = "http://boku-url/cimi/evurl?SKEY=BEHBuKkD3yxt6dD6NgEHKhjBLZTPwQgT2Yb06NMnCilwuVgEetIlH7lUL%2BgmAEY%2FlaFVkoxzfdndPlVmP9FBRycx%2BhKZeLAo1gmvBP9qdb0%3D"_10_10 _ = requestEvurlWithCellularData(evurl: EVURL) _10}
EVURLs are Unique!
EVURLs are unique to each request, do not hard code one. EVURLs can be created manually using the Create an EVURL endpoint.