boto自体使うのが初めてだったので、おかしい所があるかもしれないが動作はした。APNsのSSL証明書作成等は毎度の事なので省略。Application ARNはAWS Consoleから既に作成してあるとする。
デバイス指定でメッセージ送信する
# -*- coding: utf-8 -*- import boto.sns AWS_ACCESS_KEY = 'xxxx' AWS_SECRET_ACCESS_KEY = 'yyyyyyyy' APPLICATION_ARN = \ 'arn:aws:sns:ap-northeast-1:0000:app/APNS_SANDBOX/aaaa' # SNSに接続 sns_connection = boto.sns.connect_to_region('ap-northeast-1', aws_access_key_id=AWS_ACCESS_KEY, aws_secret_access_key=AWS_SECRET_ACCESS_KEY) # 送信先デバイスを指定してendpointを作成 res = sns_connection.create_platform_endpoint( platform_application_arn=APPLICATION_ARN, token='xxxxxxxx') endpoint = res.get('CreatePlatformEndpointResponse')\ .get('CreatePlatformEndpointResult').get('EndpointArn') # endpointに送信 sns_connection.publish(target_arn=endpoint, message=u"Hello World")endpointは一度作成したら、保存しておけば再度 create_platform_endpoint する必要は無い。
Topic経由でメッセージ送信する
Topicをsubscribeしているデバイスに一斉送信するパターン、Topicをsubscribeする際の第二引数はbotoのソースを読んでもわからなかったが、AWSコンソールのTopic管理画面から推測すると "application" を指定したら良い気がする。そして実際に動作する。# -*- coding: utf-8 -*- import boto.sns AWS_ACCESS_KEY = 'xxxx' AWS_SECRET_ACCESS_KEY = 'yyyyyyyy' APPLICATION_ARN = \ 'arn:aws:sns:ap-northeast-1:0000:app/APNS_SANDBOX/aaaa' # SNSに接続 sns_connection = boto.sns.connect_to_region('ap-northeast-1', aws_access_key_id=AWS_ACCESS_KEY, aws_secret_access_key=AWS_SECRET_ACCESS_KEY) # 送信先デバイスを指定してEndpointを作成 res = sns_connection.create_platform_endpoint( platform_application_arn=APPLICATION_ARN, token='xxxxxxxx') endpoint = res.get('CreatePlatformEndpointResponse')\ .get('CreatePlatformEndpointResult').get('EndpointArn') # Topicを作成 res = sns_connection.create_topic('test_topic') topic = res.get('CreateTopicResponse')\ .get('CreateTopicResult').get('TopicArn') # TopicをSubscribe sns_connection.subscribe(topic, 'application', endpoint) # Topicに送信 sns_connection.publish(topic=topic, message=u"Hello World for Topic subscriber")Topicにぶらさげるデバイスの数は1万が上限との事なので、アプリのユーザー全員に送信するといった場合にはTopicを分けるか、全てのEndpointに送信するかどちらかになる。あまり楽させてはくれない様だ。Endpointを削除した場合、Topicから勝手にunsubscribeされると思いきやそうでもなかった。
JSON形式でbadgeやalertを送る
# Payloadの中身 message = json.dumps({ "aps": { "alert": { "body": "Hey Hey", "action-loc-key": None }, "badge": 100 } }) # Payloadの長さチェック if len(message) > 255: raise "APNs payload over 255 bytes!!!!" # 送信先プラットフォームの指定、本番であればAPNS # Android向けのPushもここで同時に指定できる data = json.dumps({"APNS_SANDBOX": message}) # message_structure='json'を指定してPublish try: sns_con.publish( target_arn=endpoint, message=data, message_structure='json') except BotoServerError, e: logger.warn( "BotoServerError status:%s %s %s", e.status, e.reason, e.error_message)Payloadを一度作った後、文字列にして再度JSONにつっこむという面倒な事が必要。