How to integrate app with iOS Contacts app?

2.5k Views Asked by At

I'm trying to get a messaging app integrated with the iOS Contacts app, so that users can initiate messages via the app directly from Contacts. This was covered in WWDC 2016 session 240 but apparently some details were omitted.

Following the WWDC example, I have:

  • Added the activity type to the app's Info.plist:

    <key>NSUserActivityTypes</key>
    <array>
            <string>INSendMessageIntent</string>
    </array>
    
  • Implemented application(_:continue:restorationHandler:) in my app delegate.

  • Created and donated an interaction

    let activity = NSUserActivity(activityType: "com.example.message")  
    activity.title = "Send CB Test Message"  
    activity.expirationDate = Date.distantFuture  
    
    let recipient = INPerson( /* recipient with an email address in my Contacts database */ )  
    let sender = INPerson( /* me */ )        
    
    let intent = INSendMessageIntent(recipients: [recipient], content: nil, groupName: nil, serviceName: "CB Test Chat", sender: sender)  
    
    let response = INSendMessageIntentResponse(code: .success, userActivity: activity)
    let interaction = INInteraction(intent: intent, response: response)  
    interaction.direction = .outgoing  
    interaction.donate { (error) in  
        print("Donated")  
        if let error = error {  
            print("Donate error: \(error)")  
        }  
    }  
    

This sort of works. The app shows up as an option on the one recipient's card in Contacts. Tapping it in Contacts launches my app with an NSUserActivity. That's good but it's not enough.

The WWDC session used WhatsApp as an example. WhatsApp shows up as an option on all of my contacts, even those without WhatsApp accounts. I thought maybe WhatsApp had created and donated interactions for everyone. But if I create a new contact while WhatsApp isn't running, it's immediately an option on that contact. I experimented a little, setting the recipient argument to nil or to an empty array, but that had no effect.

So what am I missing here? I'm close, maybe? But it seems like donating interactions might not be what I actually need.

Update, in response to @Mark: Clarified the use of activity. I've tried this using response (which uses activity) and with a nil value for response but neither worked.

2

There are 2 best solutions below

0
On BEST ANSWER

I asked about this at WWDC 2019 and was told that this kind of mass donation only works for VOIP apps, not for messaging apps. The code in this question would in theory work for VOIP-- maybe or maybe not exactly as presented. I haven't tried because I don't work on the right kind of app.

1
On

Simply use UIActivityViewController. You can instantiate it with text or any object. You can also exclude all types besides messaging if that's all you want.

let objectsToShare = [textToShare, otherObject] as [Any]
let activityVC = UIActivityViewController(activityItems: objectsToShare, applicationActivities: nil)
        
//New Excluded Activities Code
activityVC.excludedActivityTypes = [UIActivityType.addToReadingList]
activityVC.popoverPresentationController?.sourceView = sender as? UIView
present(activityVC, animated: true, completion: nil)