Native Mac app fails to Handoff to Native iOS app

342 Views Asked by At

I'm adopting Handoff in my iOS and Mac apps. iOS -> iOS and iOS -> Mac are working flawlessly! It's great. However, Mac -> iOS never works. I've tested on both El Capitan and Sierra, in different machines. If I add a webpageURL as fallback, Safari in iOS does pickup the activity, but the native iOS app won't show up. I'm using this piece of code in the Mac app

class ViewController: NSViewController {  
    override func viewDidAppear() {  
        super.viewDidAppear()      
        self.startUserActivity()  
    }    
    func startUserActivity() {  
        let userActivity = NSUserActivity(activityType: "net.myapp.myactivitytype")  
        userActivity.isEligibleForHandoff = true  
        userActivity.isEligibleForSearch = false  
        userActivity.isEligibleForPublicIndexing = false  
        userActivity.title = "Handoff test"  
        userActivity.userInfo = ["key": "value"]  
        userActivity.requiredUserInfoKeys = Set<String>(arrayLiteral: "key")  
        userActivity.webpageURL = URL(string: "https://myapp.net/myurl") // I can pick this up in mobile safari  
        self.userActivity = userActivity  
    }    
    override func updateUserActivityState(_ userActivity: NSUserActivity) {  
        userActivity.addUserInfoEntries(from: ["key":"Updated value"])  
        super.updateUserActivityState(userActivity)  
    }  
} 

In iOS side, I already handle universal links with applinks:myapp.net , and tried adding activitycontinuation:myapp.net as well (along with the proper configuration on apple-app-site-association file. This made my Native app pickup a corresponding url from Mac's Safari, but Native Mac app still isn't able to Handoff to Native iOS app. I'm out of ideas, anyone have insights as why this can be happening ? On iOS I'm using 10.2. Btw I couldn't make Handoff work at all on iOS 9.

Best regards Rafael

2

There are 2 best solutions below

6
On BEST ANSWER

In my situation, the issue was caused by a missing entitlement when code signing the Mac app. When running codesign -d --entitlements - /Applications/MyApp.app, it was missing an entry related to the team identifier. This is the key for iOS to connect the Mac Handoff to its native counterpart (and not some other rogue app that tries to use the same Handoff identifier)

<key>com.apple.developer.team-identifier</key>
<string>MY_TEAM_ID</string>

To add this entitlement, create a Provisioning Profile in Dev Center for your app, download it and import it in Xcode's manual signing. It did not work for me either in automatic, or manual without a provisioning profile (which Xcode states as optional)

1
On

I finally solved it. The answer had nothing to do with signing profiles like the accepted answer suggests.

I reported a bug report to Apple explaining the whole situation, and Apple told me that my iOS app's info.plist doesn't declare NSUserActivityTypes at all, and my Mac app's info.plist correctly declares NSUserActivityTypes, resulting in handoff only working from iOS to Mac and never Mac to iOS.

This issue is due to the iOS version of the app not claiming the activity type in the info.plist, resulting in the iOS device not knowing what app to give the handoff to.

In my Xcode project in the left navigation panel, I opened info.plist and NSUserActivityTypes was indeed there already. But I then realized that there are multiple info.plist files in my project when I search it using Finder in the project folder. Then I physically went into my project folder with Finder and tried to locate this info.plist file, but when I located one inside projectName/projectName it opened a different info.plist file that I couldn't initially access via Xcode project navigator. The different info.plist file did not have NSUserActivityTypes, and so I added it, and woala~ handoff finally worked from Mac to iOS! It is very odd there were fake multiple info.plist in my project. My real info plist was hidden from Xcode...