お?いけるくさい?

iPhoneアプリエンジニアのたまごです。いっちょまえエンジニア目指してちいさな発見や学んだことを覚え書きしていきます!Objective-C/iOS/開発

Adhoc版でプッシュ通知が届かない問題を解決!!

 

まーたやってもうた。

毎回、テスト配布でAdhoc版のProvisioningを設定して

Releaseモードでアーカイブすると、

そのときに取得したAPNSのtokenと

ストアのリリース版からのAPNStokenがサーバー側で混在してしまって

プッシュが届かないという現象が。。。

これを今回限りでこの現象とはおさらばする!打破!\( ^ヮ゜)>ダハ!

 

 

▼まずはこちらを参考に

 

http://peter78.wordpress.com/2011/04/01/apple-push-notification-service-deployment-tips/

要点は以下。おさらいも兼ねて。

  1:Adhoc版=開発環境(≠本番環境)

  2:開発環境では本番環境のAPNSを取得することはできない。

  3:本番環境(Release版)で取得するAPNSは本番用のもの、

    なのでこの本番用APNS tokenが本番用サーバと紐づけられて使用されなきゃだめ。

  おまけ:テストで開発版をビルドした端末でストアからリリース落とす場合、

      一回アプリを削除してからインストールすること。

つまりは、やっぱり開発環境のAPNS tokenと本番環境のAPNS tokenは絶対混ぜたらあかんで

ってことらしい。

Adhoc版ってどちらかというと本番環境と同じだ(というか開発環境ではない)と思ってた....

(だってDistributionに紐づけられてるもんね(´・ω・`))

 

▼仮説

Adhoc版 Provisioningを設定してRelease版でArchiveしたテストアプリを入れた端末は、

AppleのAPNSサーバーに対して本番用のProvisioningでtokenを要求する。

するとAPNSサーバーは

その端末に向けて本番用のtokenを登録してしまう。

そいつは本当は開発環境であるAdhoc版なのに(悲劇)

そしていざ製品がリリースされて、プッシュ打ちます!

てなったときに、

本当の本番環境で作成されていない登録済みtokenを

端末の本番用tokenとして紐づけてしまうから、

本番サーバーから該当端末に届かなくなるって事なんかな?

 

でもリリース前テストは限りなく本番に近い環境で行いたいよね。

アーカイブしたもので配布したいよね。

 

▼解決策を考える

一番簡単そうなのは、

Edit SchemeでArchiveの設定を「Debug」に設定してしまう。

そうしたら登録要求をしてもそれは完全に開発環境版のtokenだから

問題ない気がしたんだよな。

でも、「本番環境になるべく近づけたい」という観点から、

このやり方は結局試すのやめた。

 

で、思った。

 

「Adhocモード」っていうのが存在して、

そのときにはAPNSに登録要求自体しない

っていう風にすればいいんじゃない?

 

例えばマクロ定義しちゃって、

#ifdef文とかでコード自体呼ばれなければいいんよね。

というわけで作戦を開始。

 

▼STEP1

ということで、以下の方法でまずはAdhocモードなるものを追加!

下のサイトを参考に。

http://qiita.com/uasi/items/79aecac40f1b2a5f929b

このときに、

「Duplicated "Debug" configuration/Duplicated "Release" configuration」

つまり、

「開発環境ベースに作るか本番環境ベースに作るか、どうする?」って聞かれるけど、

私は本番に近い環境にしたかったので本番環境ベースに作った。

「Release Copy」なるものが作られるので、名前を「Adhoc」にする。

f:id:simamikiii:20130712144637p:plain

 

 

 

で、作ったらPreprocessor Macroに「ADHOC=1(ADHOCですよー)」てマクロを定義する。

f:id:simamikiii:20130712144804p:plain

 

▼STEP2

ここまで出来たら、マクロで呼び出し制限をかける!

APNS tokenをAPNSに登録要求するコードはアプリ起動時とかに呼び出すと思うんやけど、

この文を#ifdef文で囲む。

今回は、「Adhoc版じゃなかったら呼んで欲しい」ので、

以下のように。

#ifndef ADHOC

    [[UIApplicationsharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeBadge

| UIRemoteNotificationTypeSound

| UIRemoteNotificationTypeAlert)];

#endif

 

f:id:simamikiii:20130712144650p:plain

▼STEP3

そして、Edit SchemeからArchive時の設定を「Adhoc」にする。

f:id:simamikiii:20130712144706p:plain

これでアーカイブするときにAdhoc版でコンパイルされる。

するとAdhoc版では上のコードがスルーされて呼ばれないので

APNSに向けて登録要求がされない=本番環境での混在は起こらない!はず!

ちなみにProvisioningの設定は、

Debug→Development

Adhoc→Adhoc(Distribution)

Release→Distribution

とします。

 

▼確認

とりあえず本当にマクロがスルーされるのか確認のために

ViewDidLoadでアラート表示のテストをしてみた。

本来ならばReleaseと比較してみたいところやけど無理なので、

Debug(Runでの設定)とAdhoc(Archive)で

BundleIDをかえてそれぞれ挙動をチェック。

f:id:simamikiii:20130712144546p:plain

 

これでビルドしてみると...

f:id:simamikiii:20130712155804p:plain こちらがDebugビルドf:id:simamikiii:20130712155816p:plain こちらがAdhocビルド

 

できてるう\(^o^)/

というわけでおそらく、これでDebug時とRelease時のみ

APNSの登録要求が呼ばれるはず!

 

▼注意 

今までだとArchive時のデフォルト設定は「Release」になっているけど

テスト配布時には「Adhoc」に変更しているので、

ストアにSubmitするときは必ずこの設定を「Release」に戻してArchiveすること!