如何通过PyAPNS在iOS推送通知Payload中添加图片附件?
I'm trying to add image attachments to iOS push notifications using PyAPNS. Currently, I can send notifications with title, subtitle, and body, but when I try to add attachments to the existing APNS Payload structure, it triggers an error. Here's the code for my ApplePushNotification class—how should I modify the Payload structure to support image attachments?
class ApplePushNotification(object): """ class to handle apple push notifications """ def __init__(self, account, user_id_token_mappings, project='testproject'): ''' constructor to initialize account and device info :param account: account id :param user_id_token_mappings: user id - device token mapping (dict) ''' self.account = account self.user_id_token_mappings = user_id_token_mappings self.cert_file = '' self.key_file = self.cert_file def send_apple_push_notification(self, message, alert=None, extra_payload={}): ''' sends push notification to iOS device :param message: push notification content :param alert: alert text :param extra_payload: extra notification content :return: None ''' if not self.user_id_token_mappings: return False apns_server = Apns(use_sandbox=USE_SANDBOX, cert_file=self.cert_file, key_file=self.key_file, enhanced=True) apns_server.gateway_server.register_response_listener(response_listener, self.account) payload_content = {'sound': "default", 'content_available': 1, 'custom': message} if alert: payload_content['alert'] = { 'title': title, 'subtitle': '', 'body': alert } if extra_payload: payload_content.update(extra_payload) payload = Payload(**payload_content) expiry = int(time.time() + 3600) invalid_tokens = [] for i, userid_apns_mapping in enumerate(self.user_id_token_mappings): identifier = get_identifier() try: apns_server.gateway_server.send_notification(userid_apns_mapping[1], payload, identifier=identifier, expiry=expiry) apns_server.gateway_server.set_identifier_token_mapping(identifier, userid_apns_mapping) except TypeError: # s = traceback.format_exc() # write_error_log(s) invalid_tokens.append(userid_apns_mapping) print('type error') continue
Got it, let's break down how to add image attachments to your APNS notifications using PyAPNS. The key thing to know here is that APNS doesn't let you send the image file directly in the payload. Instead, you'll use a combination of enabling mutable content in your payload and an iOS Notification Service Extension to download and attach the image to the notification before it's displayed to the user. Here's how to adjust your code:
Step 1: Enable Mutable Content in the Payload
First, add 'mutable-content': 1 to your payload—this tells iOS that the notification can be modified by an extension before showing up.
Step 2: Include the Image URL in a Custom Field
Add the public URL of your image to the payload (usually in your custom message field or a separate key) so the iOS extension can fetch it.
Step 3: Update Your Payload Construction Code
Here's the revised version of your send_apple_push_notification method with these changes, plus a fix for the undefined title variable:
def send_apple_push_notification(self, message, alert=None, title=None, extra_payload={}, image_url=None): ''' sends push notification to iOS device :param message: push notification content :param alert: alert body text :param title: alert title text :param extra_payload: extra notification content :param image_url: URL of the image to attach to the notification :return: None ''' if not self.user_id_token_mappings: return False apns_server = Apns(use_sandbox=USE_SANDBOX, cert_file=self.cert_file, key_file=self.key_file, enhanced=True) apns_server.gateway_server.register_response_listener(response_listener, self.account) payload_content = { 'sound': "default", 'content_available': 1, 'mutable-content': 1, # Critical: Allows iOS extension to modify the notification 'custom': message } if alert and title: payload_content['alert'] = { 'title': title, 'subtitle': '', 'body': alert } # Add image URL to custom data if provided if image_url: # You can add this directly to the custom message dict or as a top-level key payload_content['custom']['image_url'] = image_url if extra_payload: payload_content.update(extra_payload) payload = Payload(**payload_content) expiry = int(time.time() + 3600) invalid_tokens = [] for i, userid_apns_mapping in enumerate(self.user_id_token_mappings): identifier = get_identifier() try: apns_server.gateway_server.send_notification(userid_apns_mapping[1], payload, identifier=identifier, expiry=expiry) apns_server.gateway_server.set_identifier_token_mapping(identifier, userid_apns_mapping) except TypeError: # s = traceback.format_exc() # write_error_log(s) invalid_tokens.append(userid_apns_mapping) print('type error') continue
Critical Next Steps for iOS Side
You can't stop at just modifying the backend code—you need to add a Notification Service Extension to your iOS app:
- In Xcode, go to File > New > Target, select "Notification Service Extension".
- In the extension's
didReceive(_:withContentHandler:)method, add code to download the image fromimage_url, save it locally, and attach it to the notification content. - Make sure the extension is signed properly and included in your app bundle.
Quick Troubleshooting Tips
- If you're still getting errors, double-check that
mutable-contentis set to1(it's an integer, not a string). - Ensure the image URL is publicly accessible (or your extension handles authentication if the URL is protected).
- Verify that the image is in a format iOS supports (JPEG, PNG, GIF, etc.).
内容的提问来源于stack exchange,提问作者Sreehari S

