Closed Splash04 closed 5 months ago
Well, looks like SDK on findExistingInstallOrOpen take BranchOpenRequest with empty callback. And at the same time urlString is nil as well, so if and else cases just NOT save initSessionCallback and we lose it
@Splash04 Mind opening a support ticket for this? The upgrade scenario should work.
Now the status 200, is actually the http status which is ok. That's just informational and not an error. So I'm going to rename this ticket to correctly describe it as a potential upgrade issue.
Looking at the logs and screenshots, the behavior is as expected. So I think a deeper analysis is necessary.
The else block is to handle a very specific lifecycle situation. Most of the time we actually do NOT want to create a new request. The reason it exists is if we have two lifecycle events come in very rapidly and the second lifecycle has link data, we cannot ignore like we normally do. We must make an attempt to resolve that one as well.
I'm still have one phone with this issue. So I will try to provide some additional details that maybe help:
On App launch by some reason we load from file "BNCServerRequestQueue" just one BranchOpenRequest with empty fields:
Init branch single with this data:
Checking request [self.requestQueue findExistingInstallOrOpen] and not saving initSessionCallback:
Processing empty BranchOpenRequest:
Send open event to server:
on processResponse we don't have errors and callback is null, so just load data and [BranchOpenRequest releaseOpenResponseLock]
Callback null, so do nothing here:
processNextQueueItem
So no callback call here.
When I compare this flow with clear setup flow, I had seen that findExistingInstallOrOpen don't return anything. So we're creating BranchOpenRequest and saving initSessionCallback. And initSessionCallback call after the end.
For developers who faced with this issue. This actions should help.
@main
class AppDelegate: UIResponder, UIApplicationDelegate {
private var branchIOLaunchTimer: Timer?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// code
startBranchTimeoutTimer()
Branch.getInstance().initSession(launchOptions: launchOptions, automaticallyDisplayDeepLinkController: false, deepLinkHandler: handleDeepLink)
}
func handleDeepLink(params: [AnyHashable: Any]?, error: Error?) {
stopBranchTimeoutTimer()
// handle DeepLink
}
}
// ******************************* MARK: - Branch iOS workaround
extension AppDelegate {
@objc
private func onBranchTimerTimeout() {
logError("Branch IO app launch Timeout")
// Just additional safety (Queue should be already empty), basically do nothing for our issue
Branch.getInstance().clearNetworkQueue()
/*
The main issue, that file for serverRequestQueue cache contains invalid event
so we need to get path to this file and clear it
*/
/* persistImmediately will not clean up the file, because it contains checking count != 0
if let serverRequestQueue = (BranchSDK.BNCServerRequestQueue.getInstance() as? BranchSDK.BNCServerRequestQueue) {
print("serverRequestQueue: \(serverRequestQueue.queueDepth())")
serverRequestQueue.persistImmediately()
}
*/
// Load serverRequestQueue file path from ObjecitiveC code
if let fileUrl = ObjectiveCUtils.serverRequestQueueURL() {
logDebug("Remove cache file for branch serverRequestQueue", data: ["fileUrl" : fileUrl])
removeFile(fileUrl: fileUrl)
}
// Force start the app
handleDeepLink(params: [:], error: nil)
}
func removeFile(fileUrl: URL) {
if FileManager.default.fileExists(atPath: fileUrl.path) {
do {
try FileManager.default.removeItem(atPath: fileUrl.path)
print("File deleted: \(fileUrl)")
} catch {
print("Could not delete file, probably read-only filesystem")
}
} else {
print("File not exist")
}
}
fileprivate func startBranchTimeoutTimer() {
if let _ = self.branchIOLaunchTimer { return }
self.branchIOLaunchTimer = Timer.scheduledTimer(timeInterval: 10.0,
target: self,
selector: #selector(onBranchTimerTimeout),
userInfo: nil,
repeats: false)
}
private func stopBranchTimeoutTimer() {
self.branchIOLaunchTimer?.invalidate()
self.branchIOLaunchTimer = nil
}
}
The main problem here that serverRequestQueue cache file path is a private method in objectiveC class. So, we have to use Objective-C Runtime Utilities function to get selector by name (NSSelectorFromString). Please, check that function name is not changed:
How to get this path:
#import <Foundation/Foundation.h>
@interface ObjectiveCUtils : NSObject
@end
2. Accept to create -Bridging-Header.h when XCode asks you. It should contain just one line:
`#import "ObjectiveCUtils.h"`
3. Create ObjectiveCUtils.m
@implementation ObjectiveCUtils
(NSURL *) serverRequestQueueURL { SEL privateSelector = NSSelectorFromString(@"URLForQueueFile"); if ([BNCServerRequestQueue respondsToSelector: privateSelector]) { id url = [BNCServerRequestQueue performSelector: privateSelector];
if ([url isKindOfClass: [NSURL class]]) {
return url;
} else {
printf("Invalid class type for URLForQueueFile url\n");
return NULL;
}
} else { printf("Selector for URLForQueueFile is not found\n"); }
return NULL; }
@end
@Splash04 Thanks for the detailed logs and your workaround. Looking to see if I can reproduce this on my own test devices. Either way, I think an additional safety check for invalid events in storage is necessary in the next patch.
A error recovery safety check similar to the one described here was added in the latest release. https://github.com/BranchMetrics/ios-branch-deep-linking-attribution/releases/tag/3.4.1
Describe the bug
Faced with issue after updating SDK version. Old app contains SDK v3.0.0; new app version: v3.3.0.
The main issue: After app update, deepLinkHandler is never called. App restart not help. The only solution is to delete app and install from scratch. But such case is NOT acceptable for app users.
Network finish operation https://api3.branch.io/v1/open 0.944s. Status 200 error (null).
Expected result: deepLinkHandler call just after app launch.
Log file: Branch_io_log.txt
The same issue as users described here: https://github.com/BranchMetrics/ios-branch-deep-linking-attribution/issues/760#issuecomment-1640572758 https://github.com/BranchMetrics/ios-branch-deep-linking-attribution/issues/914#issue-434226742 https://github.com/BranchMetrics/react-native-branch-deep-linking-attribution/issues/532#issue-554558963 And a lot of threads at stackoverflow.
Steps to reproduce
1. 2. 3.
Expected behavior
deepLinkHandler call after app launch.
SDK Version
3.3.0
XCode Version
15.2
Device
iPhone 13 pro
OS
15.7.1
Additional Information/Context
No response