[FirebaseAnalytics][I-ACS023001] Deep Link does not contain valid required params issue - flutter

[FirebaseAnalytics][I-ACS023001] Deep Link does not contain valid required params. URL params: {
"_cpb" = 1;
"_cpt" = cpit;
"_fpb" = "CIAHEJ4DGgVlbi1JTg==";
"_iumchkactval" = 1;
"_iumenbl" = 1;
"_osl" = "https://helpwise.page.link/TJBU";
"_plt" = 3322;
"_uit" = 1679;
apn = "com.saaslabs.helpwise";
cid = 3913316441535437959;
ibi = "com.saaslabs.helpwise";
isi = 1503985272;
link = "https://app.helpwise.io";
}
VERBOSE: application/scene didBecomeActive
DEBUG: Application Foregrounded started
DEBUG: cancelFocusCall of {
"NOT_ATTRIBUTED" = "<OSUnattributedFocusTimeProcessor: 0x28181f8e0>";
}
I am getting this error how to solve it
I tried the normal integration method from the firebase website but not able to solve this issue

This error happens if your link structure is not properly configured. You have to make sure that your link parameter is URL encoded.

After trying lots of methods I was final able to solve the issue.
The mistake that I made was in the app delegate I had overridden the function which intercepts those links in iOS due to which it was not able to get some information that was required commenting that line solved the issue.
those lines were:
override func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void) -> Bool {
print("app delegate=====\(userActivity.webpageURL?.absoluteString ?? "NO WEBPAGE URL")")
return true }

Related

AWS Amplify Flutter: how to create platform endpoint?

Short version of my question: I have a Flutter mobile app that uses AWS Amplify to handle user
sign-up and log-in. Now I need to add push notification capability (with AWS SNS, APN etc.)
to the app, and in particular I need to let the app itself to create the platform endpoint.
So now I have to call the CreatePlatformEndpoint function in an Amplify Flutter
mobile app, and I don't know how to do it correctly. Any idea?
Here's what I've done so far: Firstly, I configured AWS Cognito and added Amplify
to my app so that the user can sign up and log in. The relevant code looks something
like the following:
// Sign Up
var userAttributes = {
CognitoUserAttributeKey.email: email,
};
await Amplify.Auth.signUp(
username: email,
password: password,
options: CognitoSignUpOptions(
userAttributes: userAttributes,
),
);
// Log In
var res = await Amplify.Auth.signIn(
username: email,
password: password,
);
if (res.isSignedIn) {
....
} else {
....
}
This part is successful and the code works all right.
Secondly, I configured APN, AWS SNS, and the iOS module of the app, then modified
AppDelegate to something like the following:
override func application(
_ application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
GeneratedPluginRegistrant.register(with: self)
registerForNotifications()
return super.application(application, didFinishLaunchingWithOptions: launchOptions)
}
private func registerForNotifications() {
UNUserNotificationCenter.current().delegate = self
UNUserNotificationCenter.current().requestAuthorization(options: [.alert, .sound, .badge]) { [weak self] granted, _ in
guard granted else { return }
self?.getNotificationSettings()
}
}
private func getNotificationSettings() {
UNUserNotificationCenter.current().getNotificationSettings { settings in
guard settings.authorizationStatus == .authorized else { return }
DispatchQueue.main.async {
UIApplication.shared.registerForRemoteNotifications()
}
}
}
override func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken tokenData: Data
) {
let token = tokenData.map { String(format: "%02.2hhx", $0) }.joined()
print("token: \(token)")
}
override func userNotificationCenter(
_ center: UNUserNotificationCenter,
willPresent notification: UNNotification,
withCompletionHandler completionHandler: #escaping (UNNotificationPresentationOptions) -> Void
) {
completionHandler([.badge, .sound, .alert])
}
This part is also successful. The iPhone can obtain and print the device token,
and when I manually create the endpoint in AWS Management Console and send a notification
from there, the iPhone can receive and show the notification.
Finally, I tried to let the app automatically create the endpoint in SNS when it got
the device token. I referenced this article, and managed to modify the
didRegisterForRemoteNotificationsWithDeviceToken method to the following:
override func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken tokenData: Data
) {
let token = tokenData.map { String(format: "%02.2hhx", $0) }.joined()
print("token: \(token)")
let credentialsProvider = AWSCognitoCredentialsProvider(regionType: ......, identityPoolId: ".........")
let configuration = AWSServiceConfiguration(region: ......, credentialsProvider: credentialsProvider)
AWSServiceManager.default().defaultServiceConfiguration = configuration
let appArn = "arn:aws:sns:........"
let platformEndpointRequest = AWSSNSCreatePlatformEndpointInput()!
platformEndpointRequest.customUserData = "........."
platformEndpointRequest.token = token
platformEndpointRequest.platformApplicationArn = appArn
let sns = AWSSNS.default()
sns.createPlatformEndpoint(platformEndpointRequest) { response, error in
....
}
}
This part is only partially successful. The endpoint is indeed created in SNS,
and I can verify this in AWS Management Console. But there are serious problems:
the user is logged out after the above code is executed
when the user tries to log back in, the app crashes with an "unexpectedly found nil" exception
Here's the crash log:
AWSMobileClient/AWSMobileClient+SignIn.swift:66: Fatal error: Unexpectedly found nil while unwrapping an Optional value
AWSMobileClient/AWSMobileClient+SignIn.swift:66: Fatal error: Unexpectedly found nil while unwrapping an Optional value
* thread #4, queue = 'NSOperationQueue 0x107d22800 (QOS: UNSPECIFIED)', stop reason = Fatal error: Unexpectedly found nil while unwrapping an Optional value
frame #0: 0x000000019b861060 libswiftCore.dylib`_swift_runtime_on_report
libswiftCore.dylib`_swift_runtime_on_report:
-> 0x19b861060 : ret
libswiftCore.dylib`_swift_reportToDebugger:
0x19b861064 : b 0x19b861060 ; _swift_runtime_on_report
libswiftCore.dylib`_swift_shouldReportFatalErrorsToDebugger:
0x19b861068 : adrp x8, 324077
0x19b86106c : ldrb w0, [x8, #0x611]
Target 0: (Runner) stopped.
I think maybe the defaultServiceConfiguration = configuration thing conflicts
with Amplify, so I try removing that part and modify the code to:
override func application(
_ application: UIApplication,
didRegisterForRemoteNotificationsWithDeviceToken tokenData: Data
) {
let token = tokenData.map { String(format: "%02.2hhx", $0) }.joined()
print("token: \(token)")
let appArn = "arn:aws:sns:........"
let platformEndpointRequest = AWSSNSCreatePlatformEndpointInput()!
platformEndpointRequest.customUserData = "........."
platformEndpointRequest.token = token
platformEndpointRequest.platformApplicationArn = appArn
let sns = AWSSNS.default()
sns.createPlatformEndpoint(platformEndpointRequest) { response, error in
....
}
}
but then the code crashes at the createPlatformEndpoint call, and here's the crash log:
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'The service configuration is `nil`. You need to configure `awsconfiguration.json`, `Info.plist` or set `defaultServiceConfiguration` before using this method.'
*** First throw call stack:
(0x197c1f128 0x1ab932480 0x102d7fcf4 0x197857298 0x1977faf90 0x102d7fb5c 0x102c875a0 0x102c86e4c 0x102c872c0 0x19a4d8c34 0x1978562b0 0x197857298 0x197805ce4 0x197b9e170 0x197b985d0 0x197b976a8 0x1ae247570 0x19a4b5370 0x19a4ba8ec 0x102c88400 0x197876140)
libc++abi: terminating with uncaught exception of type NSException
* thread #1, queue = 'com.apple.main-thread', stop reason = signal SIGABRT
frame #0: 0x00000001c38b47b0 libsystem_kernel.dylib`__pthread_kill + 8
libsystem_kernel.dylib`__pthread_kill:
-> 0x1c38b47b0 : b.lo 0x1c38b47cc ;
0x1c38b47b4 : stp x29, x30, [sp, #-0x10]!
0x1c38b47b8 : mov x29, sp
0x1c38b47bc : bl 0x1c38911fc ; cerror_nocancel
Target 0: (Runner) stopped.
So what should I do? What's the correct way to create an endpoint in an Amplify Flutter app?
OK, I'll answer my own question. I asked the Amplify-Flutter people and learned that there was currently no way to do what I want. I was advised to create a feature request ticket in their repository. I decided to turn to another approach, i.e. creating a Lambda that did the job on the backend, and it worked fine.

Why is my Plaid Link Integration not opening the Link UI

I am attempting to integrate with Plaid, their documentation is a link confusing to follow and their support team informed me they are working on it. I also reached out to them to see if they could help me with my current integration but they informed me they are not able to look at my code because every integration is different.
Per the Plaid documentation I added my ngrok url to the redirect uri section in the dashboard (This works with the Plaid Link demo app: https://github.com/plaid/plaid-link-ios).
Also I added allow arbitrary load to the info plist.
I was able to get their Plaid Link-demo app up and running but when I try to place this code in my project I get the following error:
Thread 12: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)
// MARK: Start Plaid Link using a Link token
// For details please see https://plaid.com/docs/#create-link-token
func presentPlaidLinkUsingLinkToken() {
#warning("Replace <#GENERATED_LINK_TOKEN#> below with your link_token")
// In your production application replace the hardcoded linkToken below with code that fetches an link_token
// from your backend server which in turn retrieves it securely from Plaid, for details please refer to
// https://plaid.com/docs/#create-link-token
let linkToken = "TOKEN HERE"
// <!-- SMARTDOWN_PRESENT_LINKTOKEN -->
// With custom configuration using a link_token
var linkConfiguration = LinkTokenConfiguration(token: linkToken) { success in
print("public-token: \(success.publicToken) metadata: \(success.metadata)")
}
linkConfiguration.onExit = { exit in
if let error = exit.error {
print("exit with \(error)\n\(exit.metadata)")
} else {
print("exit with \(exit.metadata)")
}
}
let result = Plaid.create(linkConfiguration)
switch result {
case .failure(let error):
print("Unable to create Plaid handler due to: \(error)")
case .success(let handler):
// UI Update code here
handler.open(presentUsing: .viewController(self))
self.linkHandler = handler
}
// <!-- SMARTDOWN_PRESENT_LINKTOKEN -->
}
#IBAction func refreshButtonAction(_ sender: Any) {
// UI Update code here
self.presentPlaidLinkUsingLinkToken()
}
I tried to place the self.presentPlaidLinkUsingLinkToken() into the following snippet:
DispatchQueue.main.async {
self.presentPlaidLinkUsingLinkToken()
}
Also per the Plaid documentation I added the following method within my App delegate swift file:
// MARK: Continue Plaid Link for iOS to complete an OAuth authentication flow
// <!-- SMARTDOWN_OAUTH_SUPPORT -->
func application(_ application: UIApplication,
continue userActivity: NSUserActivity,
restorationHandler: #escaping ([UIUserActivityRestoring]?) -> Void
) -> Bool {
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb, let webpageURL = userActivity.webpageURL else {
return false
}
// Check that the userActivity.webpageURL is the oauthRedirectUri
// configured in the Plaid dashboard.
guard let linkOAuthHandler = window?.rootViewController as? LinkOAuthHandling,
let handler = linkOAuthHandler.linkHandler,
webpageURL.host == linkOAuthHandler.oauthRedirectUri?.host &&
webpageURL.path == linkOAuthHandler.oauthRedirectUri?.path
else {
return false
}
// Continue the Link flow
if let error = handler.continueFrom(redirectUri: webpageURL) {
print("Unable to continue from redirect due to: \(error)")
}
return true
}
// <!-- SMARTDOWN_OAUTH_SUPPORT -->
But the same error occurs. Any suggestions will be appreciated.
In case anyone is having issues with this, I was able to figure it out. It is something incorrect in their cocoapod. Once, I downloaded and dragged the LinkKit Framework everything worked as expected. Also Plaid does not use their own cocoapod in their demo project, they do the manual install. Maybe they are working on this issue.
It's hard to tell without seeing the code in your application calling presentPlaidUsingLinkToken(), but your application is crashing on Thread 12. UIKit is not multi-threaded, so if you are presenting a view controller on a background thread you can expect crashes.
I see you tried a DispatchQueue.main.async, however I suspect you may have another threading issue going on.
Just putting this out there since this is one of few results for this issue: My issue was that I wasn't retaining the Handler object. As a result, the Plaid UI would never appear and no events would fire, leaving me with an endless spinner. Simply maintaining the reference in the class did the trick (as shown in the sample project and mentioned in passing in the documentation).
Kona Farry's solution above works. From Plaid docs:
Create a Handler - A Handler is a one-time use object used to open a Link session. The Handler must be retained for the duration of the Plaid SDK flow.

Can I convert a String into a SINCall?

Im working with sinch and using firebase as my database and using its cloud functions to send notifications. Sending notifications are working fine but the shouldSendPushNotifications function but it never gets called so i can't add the sinch payload to the notification data and I couldn't find anything on the internet of a solid working example so I gave up on that and decided to send the SINcall object to the database and the callee will retrieve it and answer that.
But the problem is that firebase only stores strings so when I retrieve the SINCall I stored i get an error Could not cast value of type '__NSCFString' (0x102096998) to '__ObjC.SINCall' (0x10209ab08). So is there a way to convert this to a SINCall so I can answer, decline, etc with it?
EDIT:
this is where i have my code in AppDelegate.swift
func application(_ application: UIApplication, didReceiveRemoteNotification userInfo: [AnyHashable : Any], fetchCompletionHandler completionHandler: #escaping (UIBackgroundFetchResult) -> Void) {
print("USERINFO: \(userInfo["sin"]!)") <-- prints call: <SINCallImpl: 0x1c00f2600>
let incomingCall = userInfo["sin"]!
SINClientManager.shared.call = incomingCall as! SINCall <-- Error occurs
...
}
You need to send the data to the sinch client to set up the call, you cant convert a string to a call.
NSString* payload = [remotePush objectForKey:#"SIN"];
// Get previously initiated Sinch client
id<SINClient> client = [self sinchClient];
id<SINNotificationResult> result = [client relayRemotePushNotificationPayload:payload];
if (result.isCall && result.callResult.isTimedOut) {
// Present alert notifying about missed call
} else if (!result.isValid) {
// Handle error
}

Determine login type using AWS Cognito during resume session (Swift)

I'm having a hard time trying to figure out how to determine the login type during a resume session using AWS Cognito. My code is based upon the MobileHub sample (below).
I've integrated a name/password mode for user pools (account creation and login) as well as as a Facebook login button which all works perfectly.
I have some logic in my application that needs to behave differently depending on the login type but I can't figure out how to do it.
Anyone done this?
func didFinishLaunching(_ application: UIApplication, withOptions launchOptions: [AnyHashable: Any]?) -> Bool {
print("didFinishLaunching:")
// Register the sign in provider instances with their unique identifier
AWSSignInManager.sharedInstance().register(signInProvider: AWSFacebookSignInProvider.sharedInstance())
AWSIdentityProfileManager.sharedInstance().register(FacebookIdentityProfile.sharedInstance(), forProviderKey: AWSFacebookSignInProvider.sharedInstance().identityProviderName)
AWSSignInManager.sharedInstance().register(signInProvider: AWSCognitoUserPoolsSignInProvider.sharedInstance())
AWSIdentityProfileManager.sharedInstance().register(UserPoolsIdentityProfile.sharedInstance(), forProviderKey: AWSCognitoUserPoolsSignInProvider.sharedInstance().identityProviderName)
setupAPIGateway()
setupS3()
let didFinishLaunching: Bool = AWSSignInManager.sharedInstance().interceptApplication(application, didFinishLaunchingWithOptions: launchOptions)
if (!isInitialized) {
AWSSignInManager.sharedInstance().resumeSession(completionHandler: { (result: Any?, authState: AWSIdentityManagerAuthState, error: Error?) in
print("didFinishLaunching Result: \(String(describing: result)) AuthState: \(authState) \n Error:\(String(describing: error))")
if authState == .authenticated {
// Facebook or Cognito???
AWSCognitoUserAuthHelper.getCurrentUserAttribute(name: "sub", completionHandler: { (userid) in
// we need to fetch the user
ObjectManager.instance.getUser(userid: userid, completionHandler: { (user) in
ObjectManager.instance.setCurrentUser(user: user)
})
})
}
}) // If you get an EXC_BAD_ACCESS here in iOS Simulator, then do Simulator -> "Reset Content and Settings..."
// This will clear bad auth tokens stored by other apps with the same bundle ID.
isInitialized = true
}
return didFinishLaunching
}
One solution I found was to cast to the different identity profile types such as the following:
let identityManager = AWSIdentityManager.default()
if let fbIdentityProfile = identityManager.identityProfile as? FacebookIdentityProfile {
print("didFinishLaunching - Facebook login")
} else if let upIdentityProfile = identityManager.identityProfile as? UserPoolsIdentityProfile {
print("didFinishLaunching - User Pools login")
}
I can model logic in my application around this. Not sure if there is a cleaner approach using the MobileHub helper classes or AWS APIs but this works.

Universal links doesn't work in iOS 10.2

I have serve apple-app-site-association in my HTTPS root (kumpul.co.id/apple-app-site-association) and the result is passed from https://branch.io/resources/aasa-validator/#resultsbox
I have configured it in my entitlements: applinks:kumpul.co.id
and i have put this function in my Appdelegate.swift:
func application(_ application: UIApplication, continue userActivity: NSUserActivity, restorationHandler: #escaping ([Any]?) -> Void) -> Bool {
NSLog("Check Universal Link")
// 1
guard userActivity.activityType == NSUserActivityTypeBrowsingWeb,
let url = userActivity.webpageURL,
let components = URLComponents(url: url, resolvingAgainstBaseURL: true) else {
return false
}
print("url: \(url)")
print("component: \(components)")
// 2
if let match = MatchHandler.sharedInstance.items.filter({ $0.path == components.path}).first {
self.presentMatch(match)
return true
}
//3
let webpageUrl = URL(string: "http://www.kumpul.co.id")!
application.openURL(webpageUrl)
return false
}
For the paths, i set "paths": [ "/match/*"] because the links would be kumpul.co.id/match/play_2.html for example
but when i click my link on WhatsApp or Line message, this function doesn't called at all, i can't see the logs when i click the link. What am i doing wrong here ?
Line is not compatible with Universal Links, so that test case is invalid. Your app won't open when a Universal Link is clicked in Line, even if everything is configured perfectly (you need to offer a web preview of the content with a call-to-action button, like this — the same problem exists on Facebook, by the way).
WhatsApp should be working. If your app is not even launching when the link is clicked, you have a configuration issue. You can try walking through some of the troubleshooting steps on this page. If your app is launching, then your configuration is correct and you should verify the logic inside continue userActivity