omz:forum

    • Register
    • Login
    • Search
    • Recent
    • Popular

    Welcome!

    This is the community forum for my apps Pythonista and Editorial.

    For individual support questions, you can also send an email. If you have a very short question or just want to say hello — I'm @olemoritz on Twitter.


    Contacts module: Access profile picture

    Pythonista
    contacts objcutil
    3
    5
    4321
    Loading More Posts
    • Oldest to Newest
    • Newest to Oldest
    • Most Votes
    Reply
    • Reply as topic
    Log in to reply
    This topic has been deleted. Only users with topic management privileges can see it.
    • lukaskollmer
      lukaskollmer last edited by

      Hi,

      Is there a way to use the contacts module to get and edit profile pictures for iOS contacts?

      I'm sure I'd be able to do that with objc_util, but before I'd like to try if it can be done using the built in contacts module

      1 Reply Last reply Reply Quote 0
      • Webmaster4o
        Webmaster4o last edited by

        I'm not sure you'd be able to with objc_util. I don't know if apps are allowed to have this kind of write access to contacts.

        1 Reply Last reply Reply Quote 0
        • omz
          omz last edited by

          The contacts module currently doesn't expose that functionality (still on my todo list).

          It's definitely possible to do this with objc_util/ctypes, but I don't think it would be possible to mix and match this approach with the contacts module. You can't get at the pointers to the underlying data structures in contacts, so if you want to edit a profile picture of a person using objc_util, you also have to find the right person object using that, and can't use the simpler contacts interface.

          I'll see if I can come up with an example, not completely sure how much code is required right now.

          1 Reply Last reply Reply Quote 1
          • omz
            omz last edited by omz

            Okay, here's some sample code that shows how to use objc_util with the Contacts framework to:

            • Find a person by name
            • Access its picture, and convert it to a ui.Image to show it in the console
            • Set a new picture (picked from photos here, but you could of course also get this elsewhere)
            • Save the changes

            Before you run the example, set the CONTACT_NAME variable (near the top) to a name of someone in your contacts (or create a contact named "John Doe").

            from objc_util import *
            from ctypes import string_at
            import contacts
            import ui
            import photos
            
            # CHANGE THIS:
            CONTACT_NAME = 'John Doe'
            
            # Easier to do the authorization with the contacts module (this also authorizes the Contacts.framework):
            if not contacts.is_authorized():
            	# This implicitly shows the permission dialog, if necessary:
            	contacts.get_all_groups()
            
            # Load classes we need from Contacts.framework:
            NSBundle.bundleWithPath_('/System/Library/Frameworks/Contacts.framework').load()
            CNContactStore = ObjCClass('CNContactStore')
            CNContact = ObjCClass('CNContact')
            CNSaveRequest = ObjCClass('CNSaveRequest')
            
            def main():
            	store = CNContactStore.alloc().init().autorelease()
            	# Find the first contact that matches the name.
            	pred = CNContact.predicateForContactsMatchingName_(CONTACT_NAME)
            	fetch_keys = ['imageDataAvailable', 'imageData']
            	people = store.unifiedContactsMatchingPredicate_keysToFetch_error_(pred, fetch_keys, None)
            	if not people:
            		print 'No person found with the name "%s"' % (CONTACT_NAME,)
            		return
            	p = people[0]
            	has_image = p.imageDataAvailable()
            	if has_image:
            		# Show the existing picture of the contact:
            		img_data = p.imageData()
            		img_data_str = string_at(img_data.bytes(), img_data.length())
            		img = ui.Image.from_data(img_data_str)
            		img.show()
            	# Pick a new image from photos:
            	new_img_data = photos.pick_image(raw_data=True)
            	if new_img_data:
            		# Note: objc_util automatically converts bytearray to NSData
            		new_img_bytes = bytearray(new_img_data)
            		# Create a mutable copy of the fetched contact...
            		mutable_contact = p.mutableCopy().autorelease()
            		# Assign new image data...
            		mutable_contact.imageData = new_img_bytes
            		# Create a save request for he contact, and execute it...
            		save_req = CNSaveRequest.new().autorelease()
            		save_req.updateContact_(mutable_contact)
            		store.executeSaveRequest_error_(save_req, None)
            
            if __name__ == '__main__':
            	main()
            
            1 Reply Last reply Reply Quote 2
            • lukaskollmer
              lukaskollmer last edited by

              Thank you @omz, the code you shared is working perfectly

              1 Reply Last reply Reply Quote 0
              • First post
                Last post
              Powered by NodeBB Forums | Contributors