iOS10にしたらPush通知で「Appの有効な“aps-environment”エンタイトルメント文字列が見つかりません」(TitaniumでiOSのAPNSプッシュ通知サンプル)
この記事はTitaniumでiOSのAPNSプッシュ通知を受けるためのnode.jsサーバーも使ったサンプルです。
iOS10のエラーについてはこちら(2016/9月更新 )
目次
TitaniumでAPNSプッシュ通知
iOSのリモートプッシュ通知(Apple Push Notification Service)は、サーバーを準備したりHTTPSの証明書が必要だったりとやや複雑な印象があります。
ここではnode.jsのapnsモジュールとTitaniumSDKを使ったプッシュ通知を行う最低限のコードと、証明書の登録の仕方を紹介します。
APNSへの登録と証明書の作成
1.AppleDeveloperのサイトでテスト用のAppIDを作ります。Explicit App IDを使う必要があります。この例ではcom.test.notificationtestとします。App ServicesでPush Notificationを選択しておきます。
2.出来たAppIDを開いてEdit。CreateCertificationで証明書を作ります。画面に従いMacのKeyChainAccessを使って要求証明書をつくりアップロードします。
3.証明書ができましたら同じところからDownload。出来たファイルをダブルクリックでKeyChainAccessに入ります。
4.MyCertificatesから該当の証明書をExportします。cert.p12とします。パスワードを設定した場合は覚えておきます。
5.出来たp12ファイルをmakecert.sh(下のソース)を使ってPEMファイルに変換します(例: ./makecert.sh cert.p12 cert.p12) Import用のパスワードは上記のものを、pemファイルとkey用のパスワードは2回聞かれるので同じものを入力します。)
6.これで準備完了です。apns-key-noenc.pemがkeyでapns-cert.pemが証明書です。
if [ $# != 2 ]
then
echo 'makecert.sh <cert.p12> <key.p12>'
else
openssl pkcs12 -clcerts -nokeys -out apns-cert.pem -in $1
openssl pkcs12 -nocerts -out apns-key.pem -in $2
openssl rsa -in apns-key.pem -out apns-key-noenc.pem
fi
Titaniumアプリ(Push通知を受ける最低限のコード)
下記のapp.jsを使ったTitaniumプロジェクトをつくりビルドしておきます。シミュレータではPush通知は受け取れないので実機でテストする必要があります。
ここで使うプロビジョニングプロファイルは必ず上のPushNotificationを有効にしたAppIDのものを使う必要があります。(「App の有効な "aps-environment" エンタイトルメント文字列が見つかりません」エラーになる)
Ti.App.iOS.registerUserNotificationSettings({
types: [
Ti.App.iOS.USER_NOTIFICATION_TYPE_ALERT,
Ti.App.iOS.USER_NOTIFICATION_TYPE_SOUND,
Ti.App.iOS.USER_NOTIFICATION_TYPE_BADGE
]
});
var registerForPush=function(){
Titanium.Network.registerForPushNotifications({
success:function(e){
var deviceToken = e.deviceToken;
Ti.API.info("DeviceToken:"+deviceToken);
},
error:function(e){
Ti.API.info("Error:"+e.error);
},
callback:function(e){
Ti.API.info(JSON.stringify(e))
var data=e.data
var message = e.data&&e.data.server&&e.data.server.message;
if(message){
alert(message);
}
}
});
Ti.App.iOS.removeEventListener('usernotificationsettings', registerForPush);
}
Ti.App.iOS.addEventListener('usernotificationsettings', registerForPush);
Ti.UI.createWindow().open();
上記Titaniumアプリを実機で起動するとログにDeviceIDが出力されますので、メモしておきます。
送信側Node.js(CoffeeScript)アプリ
下記のCoffeeScriptを実行します。DEVICEIDの所はは上記のものに書き換えます。
#!/usr/bin/env coffee
apns=require "apns"
options =
keyFile : "apns-key-noenc.pem"
certFile : "apns-cert.pem"
gateway : "gateway.sandbox.push.apple.com"
debug : true
connection=new apns.Connection(options)
notification=new apns.Notification()
notification.device = new apns.Device("DEVICEID")
notification.alert="Hello"
notification.payload=
server:
message:"World"
connection.sendNotification(notification)
注意とポイント
iOS8から通知の登録方法が変わっている為、この例はiOS8以前では対応していません。
デバイスIDは手動でコピーしましたが、実運用ではアプリ側からサーバー側にHTTP等で送信することになります。
iOS10にしたらPush通知で「Appの有効な“aps-environment”エンタイトルメント文字列が見つかりません」
全く同じアプリのバイナリなのにiOS10上で上記のエラーが発生する場合があります。その場合はプロジェクトのルートに以下のファイルを作って再ビルドしてください。
ファイル名:Entitlements.plist
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "h
ttp://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>aps-environment</key>
<string>production</string>
</dict>
</plist>
これはiOS10ではプロダクション(もしくはアドホック)パッケージのデバイストークン取得時に上記の設定値をチェックする様になったからです。(プロビジョニングプロファイルで判断されます)
Titaniumではなくネイティブでのビルドの場合はXCODE8の
Target -> Capabilities -> Push Notifications
で
Add the Push Notifications entitlement to your entitlements file
に対するFix操作をすることで(プロジェクト名).entitlementsファイルに上の値が追加されます。
Titaniumの場合はプロジェクトルートのEntitlements.plistがビルド時に上記entitlementsファイルにコピーされる仕組みです。
ちなみに下記によればデベロップメント時はstringをdevelopmentにするべきなのでしょうが、iOS10現在では開発時productionのままでも問題なさそうです。(しかもXCODE8では反対にプロダクション時でもdevelpment固定で出力している模様)