Increase time interval in Firebase HTTPs Callable iOS Swift - ios

I'm working with my iOS Swift code, and have successfully installed all dependencies.
now, I'm trying to increase timeoutInterval in Firebase function.
functions.httpsCallable("getData").call(){ (result, error) in
guard error == nil else {
print(error)
return
}
.........
}

You cannot do it from client side. You will have to increase the timeout in your functions like thi:
const runtimeOpts = {
timeoutSeconds: 300,
memory: '1GB'
}
exports.getData = functions
.runWith(runtimeOpts)
https.onCall((data, ctx) = > {
// the function
});
The maximum value for timeoutSeconds is 540, or 9 minutes.
Detailed information can be found in the documentation

I found the answer. at first you have to set time in Firebase server, then in client side(Swift) use this code:
functions.httpsCallable("getData").timeoutInterval = 120

Related

Kotlin Multiplaform iOS Exceptions showing in Xcode, not in Firebase

We have noticed in our project, we are getting allot of exceptions logged in Xcode (->Organiser->Crashes) logged in production...
However these Share crashes don't give any extra debug infomation, nor are they logged in our Firebase exceptions.
This is how network API calls are being made using ktor 1.6:
#Throws(CancellationException::class, ResponseException::class, Exception::class)
suspend fun getProfileGoals(profileId : Int) : ProfileGoal{
val url = "$base/api/goals/$profileId"
var client = HttpClient {
install(JsonFeature) {
serializer = KotlinxSerializer(kotlinx.serialization.json.Json {
prettyPrint = true
isLenient = true
ignoreUnknownKeys = true
useAlternativeNames = false
coerceInputValues = true
encodeDefaults = true
})
}
return client.get(url){
headers {
header(DEVICE_ID, deviceId)
}
}
}
And this is how it is used in iOS:
func getGoals(){
profilesApi?.getProfileGoals(profileId: Int32(selfProfile!.profileId), completionHandler: { profileGoal, error in
if let profileGoal = profileGoal {
self.profileGoals = profileGoal
....
}
}
self.collectionView.reloadData()
})
}
There are obviously lots of other API calls, but they are all done in a similar way.
I guess my question is, is anything obviously wrong or done the incorrect way or how to get these exceptions appearing in Firebase Crashlytics, which may hopefully have more info for debugging

Stuck with Api response Ktor

I am trying to build a KMM application using Ktor for our ApiServices. I have created a BaseApiClass where I have all of the api related code.
Code for BaseApiClass :-
class BaseAPIClass {
//Create Http Client
private val httpClient by lazy {
HttpClient {
defaultRequest {
host = ApiEndPoints.Base.url
contentType(ContentType.Application.Json)
header(CONNECTION, CLOSE)
}
install(Logging) {
logger = Logger.DEFAULT
level = LogLevel.ALL
}
install(HttpTimeout) {
requestTimeoutMillis = NETWORK_REQUEST_TIMEOUT
}
expectSuccess = false
// JSON Deserializer
install(JsonFeature) {
val json = Json {
ignoreUnknownKeys = true
coerceInputValues = true
}
serializer = KotlinxSerializer(json)
}
}
}
// Api Calling Functions I have few more similar to this but issue is random and comes in any of the api
#Throws(Exception::class)
suspend fun sampleApi(requestBody: RequestBody?) : Either<CustomException, BaseResponse<EmptyResponseModel>> {
return try {
val response = httpClient.post<BaseResponse<EmptyResponseModel>> {
url(ApiEndPoints.sample.url)
if (requestBody != null) {
body = requestBody
}
}
Success(response)
}
catch (e: Exception) {
Failure(e as CustomException)
}
}
Here's how I call the api from iOS app :-
val apiClass = BaseApiClass()
func callApi() {
apiClass.sampleApi(requestBody: .init(string: "value here")) { (result, error) in
result?.fold(failed: { (error) -> Any? in
// Error here
}, succeeded: { (result) -> Any? in
// Success here
})
}
}
Now here if I try to call similar few more api's with the same object i.e apiClass then after few calls it get stuck inside my function callApi it don't send even api request (Because I can't see Request Logs printed in my console) and because of that I cannot do any other operations as I don't get anything from api.
As soon as I change my screen or close the app and try to call the same api then it works good.
But instead of creating a object only at one time like this apiClass = BaseApiClass() if I try to do with BaseApiClass().sampleApi(request params here) {// completion handler here} it works fine I don't get any issues with this.
I am not sure what causes this to happen everything works good in Android this is faced only with iOS.
Try to set LogLevel.NONE in the install(Logging) block.
At the moment I resolved in this way because it seems a bug of Ktor.
See: https://youtrack.jetbrains.com/issue/KTOR-2711
It should be fixed in the version 1.6.0.
Are you using the multithreaded variant of the Coroutines library? The official docs state that you should use this variant when working with Ktor. See here
After all the efforts and trying a lot of debugging skills I got to understand that my completion handler in the shared module is never called even if I receive the response the response from api.
The only solution I have achieved is creating the different HTTP Client using expect and actual mechanism. By making separate clients I have not encountered the issue yet.
If you have any other answers or solutions I would be happy to have a look at it.

How to deactivate on demand connect VPN from network extension?

I have configured an always on VPN with a NEOnDemandRuleConnect I retrieve some user data from a backend such as expiration date if the user has paid the subscription. If it expires I'd like to deactivate the VPN without opening the main app, doing it from the Network Extension. I retrieve the data from the backend using a daily timer and then check if the subscription has expired. Then I'd have a function that loads the VPN manager from the system settings app and then deactivate it and finally save it. If I don't deactivate the manager the device will be without connection as it's a VPN that has been configured to connect always with the NEOnDemandRule. The function will be more or less this one
func stopProtection(completion: #escaping (Result<Void>) -> Void) {
NSLog("Called stopProtection")
NETunnelProviderManager.loadAllFromPreferences { (managers, error) in
if let error = error {
NSLog("[SUBS] ERROR \(error)")
}
if let managers = managers {
if managers.count > 0 {
let index = managers.firstIndex(where: { $0.localizedDescription == Constants.vpnBundleId })
guard let index = index else {
completion(.error(ProtectionServiceError.noKidsVpnInstalled))
return
}
let myManager = managers[index]
myManager.loadFromPreferences(completionHandler: { (error) in
guard error == nil else {
completion(.error(ProtectionServiceError.errorStoppingTunnel))
return
}
// Deactivate the VPN and save it
myManager.isEnabled = false
myManager.saveToPreferences(completionHandler: { (error) in
guard error == nil else {
completion(.error(ProtectionServiceError.errorStoppingTunnel))
return
}
completion(.success(()))
})
})
} else {
completion(.error(ProtectionServiceError.errorStoppingTunnel))
}
}
}
}
All this code and logic is being performed in the extension with all the limitations it supposes. Using the previous function I'd only get the first NSLog saying Called stopProtection but it doesn't load any manager. Calling this from the main target it'd work. I don't know if I can load and modify the manager from the extension or it's another way to do it.
Okay, I have debugged the network extension by attaching to the process and looking into the device Console and this error pops up,
NETunnelProviderManager objects cannot be instantiated from NEProvider processes
So nope, there's the answer!

How to set AWS Appsync request timeout limit || AWSAppSync Client not giving callback

I'm using AWS Appsync for the current App I'm developing and facing a serious issue that is Whenever I fire queries in Appsync client, when there is slow internet connection the request never end with a callback. I checked over internet there is limited source of information on this topic and also found this issue that is still open.
This is the code I used to get the response
func getAllApi(completion:#escaping DataCallback){
guard isInternetAvailabele() else {
completion(nil)
return
}
// AppSyncManager.Client() is AWSAppSyncClient Object
AppSyncManager.Client().fetch(query: GetlAllPostQuery(input: allInputs), cachePolicy:.fetchIgnoringCacheData) {
(result, error) in
var haveError:Bool = error != nil
if let _ = result?.data?.getAllPostings?.responseCode {haveError = false} else {haveError = true}
if haveError {
print(error?.localizedDescription ?? "")
completion(nil)
return
}
if result != nil{
completion(result)
}else{
completion(nil)
}
}
}
The code works fine with internet connection and I have already checked at the top if there is no internet but when there is slow internet connection or the wifi is connected to a hotspot that I created with my mobile with internet data disabled the request doesn't return any callback it should give failed alert like we get in other apis when the request time out.
Is there any support for request for request time out or did I miss something?
Note : I recieved these logs in Terminal
Task <06E9BBF4-5731-471B-9B7D-19E5E504E57F>.<45> HTTP load failed (error code: -1001 [1:60])
Task <D91CA952-DBB5-4DBD-9A90-98E2069DBE2D>.<46> HTTP load failed (error code: -1001 [1:60])
Task <06E9BBF4-5731-471B-9B7D-19E5E504E57F>.<45> finished with error - code: -1001
Task <D91CA952-DBB5-4DBD-9A90-98E2069DBE2D>.<46> finished with error - code: -1001
Actually there could be two possible ways to fix the issue,
1) While configuring AWSAppSyncClientConfiguration, provide a custom URLSessionConfiguration and set the request timeout to your needs,
extension URLSessionConfiguration {
/// A `URLSessionConfiguration` to have a request timeout of 1 minutes.
static let customDelayed: URLSessionConfiguration = {
let secondsInOneMinute = 60
let numberOfMinutesForTimeout = 1
let timoutInterval = TimeInterval(numberOfMinutesForTimeout * secondsInOneMinute)
let configuration = URLSessionConfiguration.default
configuration.timeoutIntervalForRequest = timoutInterval
configuration.timeoutIntervalForResource = timoutInterval
return configuration
}()
}
And pass this session configuration i.e URLSessionConfiguration.customDelayed when initializing AWSAppSyncClientConfiguration as it accepts the URLSessionConfiguration in the below constructor,
public convenience init(url: URL,
serviceRegion: AWSRegionType,
credentialsProvider: AWSCredentialsProvider,
urlSessionConfiguration: URLSessionConfiguration = URLSessionConfiguration.default,
databaseURL: URL? = nil,
connectionStateChangeHandler: ConnectionStateChangeHandler? = nil,
s3ObjectManager: AWSS3ObjectManager? = nil,
presignedURLClient: AWSS3ObjectPresignedURLGenerator? = nil) throws {
2) If the first doesn't work then you have another option to edit/unlock the pod files directly. There is a class AWSAppSyncRetryHandler where you can change the logic for retrying request. If you are able to fix the issue then you can fork the original repo, clone your repo, make changes in your repo and in pods file point this pod to use your repository. This should be done as changing the pod files directly is absolutely wrong until you are really stuck and want to find some solution.
Update: This issue has been fixed with AppSync SDK 2.7.0

SFSpeechRecognizer (Siri Transcription) Timeout Error on iOS App

In my iOS app, I am trying to transcribe prerecorded audio using iOS 10's latest feature, the Speech API.
Multiple sources including the documentation have stated that the audio duration limit for the Speech API (more specifically SFSpeechRecognizer) is 1 minute.
In my code, I have found that any audio files with a length of about 15 seconds or more, will get the following error.
Error Domain=kAFAssistantErrorDomain Code=203 "SessionId=com.siri.cortex.ace.speech.session.event.SpeechSessionId#50a8e246, Message=Timeout waiting for command after 30000 ms" UserInfo={NSLocalizedDescription=SessionId=com.siri.cortex.ace.speech.session.event.SpeechSessionId#50a8e246, Message=Timeout waiting for command after 30000 ms, NSUnderlyingError=0x170248c40 {Error Domain=SiriSpeechErrorDomain Code=100 "(null)"}}
I have searched all over the internet and have not been able to find a solution to this. There also have been people with the same problem. Some people suspect that it's a problem with Nuance.
It is also worth noting that I do get partial results from the transcription process.
Here's the code from my iOS app.
` // Create a speech recognizer request object.
let srRequest = SFSpeechURLRecognitionRequest(url: location)
srRequest.shouldReportPartialResults = false
sr?.recognitionTask(with: srRequest) { (result, error) in
if let error = error {
// Something wrong happened
print(error.localizedDescription)
} else {
if let result = result {
print(4)
print(result.bestTranscription.formattedString)
if result.isFinal {
print(5)
transcript = result.bestTranscription.formattedString
print(result.bestTranscription.formattedString)
// Store the transcript into the database.
print("\nSiri-Transcript: " + transcript!)
// Store the audio transcript into Firebase Realtime Database
self.firebaseRef = FIRDatabase.database().reference()
let ud = UserDefaults.standard
if let uid = ud.string(forKey: "uid") {
print("Storing the transcript into the database.")
let path = "users" + "/" + uid + "/" + "siri_transcripts" + "/" + date_recorded + "/" + filename.components(separatedBy: ".")[0]
print("transcript database path: \(path)")
self.firebaseRef.child(path).setValue(transcript)
}
}
}
}
}`
Thank you for your help.
I haven't confirmed my answer aside from someone else running into the same problem but I believe it is an undocumented limit on prerecorded audio.
Remove the result.isFinal and do a null check for the result instead. Reference: https://github.com/mssodhi/Jarvis-ios/blob/master/Jarvis-ios/HomeCell%2Bspeech.swift
This is true, I extracted the audio file from the video, and if it exceeds 15 seconds, it will give the following error:
Domain = kAFAssistantErrorDomain Code = 203 "Timeout" UserInfo = {
NSLocalizedDescription = Timeout,
NSUnderlyingError = 0x1c0647950 {Error Domain=SiriSpeechErrorDomain Code=100 "(null)"}
}
The key issue is the audio file recognition after more than 15 seconds.
result.isFinal is always 0, which is very frustrating is that there is no accurate timestamp, although it is "Timeout", it has complete recognition content, which makes me feel weird.
If you print out the result traversal, you can see that there is some restriction, which is 15 seconds, but the reason is that the timestamp feedback of the audio file is limited to a limited number, such as 15 or 4 or 9, leading to the end. Timeout feedback is more unstable.
But in real-time speech recognition, you can break through 15 seconds, as described in the official documentation, within one minute.

Resources