<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>ほげぐらまの別館 &#187; APNS</title>
	<atom:link href="http://lain.heavy.jp/lain/tag/apns/feed" rel="self" type="application/rss+xml" />
	<link>http://lain.heavy.jp/lain</link>
	<description>プログラムに限らずてきとーに、ね？</description>
	<lastBuildDate>Sat, 29 Aug 2015 14:47:38 +0000</lastBuildDate>
	<language>ja</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>https://wordpress.org/?v=3.7.41</generator>
	<item>
		<title>iOSプッシュ通知でハマった事</title>
		<link>http://lain.heavy.jp/lain/2012/04/09/548</link>
		<comments>http://lain.heavy.jp/lain/2012/04/09/548#comments</comments>
		<pubDate>Sun, 08 Apr 2012 15:12:58 +0000</pubDate>
		<dc:creator><![CDATA[st.lain]]></dc:creator>
				<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[コンピュータ]]></category>
		<category><![CDATA[プログラム]]></category>
		<category><![CDATA[APNS]]></category>
		<category><![CDATA[ios]]></category>

		<guid isPermaLink="false">http://lain.heavy.jp/lain/2012/04/09/548</guid>
		<description><![CDATA[以前の記事、「プッシュ通知(APNs)の初期確認ダイアログについて」の続き。今になってはじめて気がついたというか、前々から変だと思っていたけど端末のせいにして自分は悪くない！と思っていた自分が一番馬鹿だった、というもので [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>以前の記事、「<a href="http://lain.heavy.jp/lain/2012/01/28/473" target="_blank">プッシュ通知(APNs)の初期確認ダイアログについて</a>」の続き。今になってはじめて気がついたというか、前々から変だと思っていたけど端末のせいにして自分は悪くない！と思っていた自分が一番馬鹿だった、というものです。</p>
<p>&nbsp;</p>
<p>プッシュ通知の確認ダイアログ自体は書いたとおり一度しか表示されない、というのは変わらないのです。が、特定の再通知条件を満たさない間に再インストールするとデバイストークンが取得できないというものです。特殊なパターンなので具体的な例で言えば、</p>
<ol>
<li>enabledRemoteNotificationTypesをコールして現在のプッシュ通知が有効かどうかを調べる</li>
<li><strong><font color="#ff0000">有効なtypeがない場合に</font></strong>registerForRemoteNotificationTypesをコールして通知ダイアログを表示する</li>
<li>アプリケーションを再インストールする</li>
<li>enabledRemoteNotificationTypesの値は正常なのにデバイストークンの値が取れない</li>
</ol>
<p>というパターン。確認する限りは、再インストールの場合は既に[設定]上にプッシュ通知が有効になっているものの再度enabledRemoteNotificationTypesをコールしないとdidRegisterForRemoteNotificationsWithDeviceTokenがコールされないようで、これがデバイストークンの値を取得できない要因となっていたようです。なので、解決策としては2.で既に有効になっていてもregisterForRemoteNotificationTypesをコールする、ってのが手っ取り早い模様。</p>
<p>何も考えずにそれをコールしていればこんなにハマることはなかったのでしょうが、何かを変えるということはそれだけリスクを伴う場合があるってことですね。いい勉強になりました。</p>
]]></content:encoded>
			<wfw:commentRss>http://lain.heavy.jp/lain/2012/04/09/548/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>プッシュ通知(APNs)の初期確認ダイアログについて</title>
		<link>http://lain.heavy.jp/lain/2012/01/28/473</link>
		<comments>http://lain.heavy.jp/lain/2012/01/28/473#comments</comments>
		<pubDate>Sat, 28 Jan 2012 08:53:02 +0000</pubDate>
		<dc:creator><![CDATA[st.lain]]></dc:creator>
				<category><![CDATA[Objective-C]]></category>
		<category><![CDATA[コンピュータ]]></category>
		<category><![CDATA[APNS]]></category>

		<guid isPermaLink="false">http://lain.heavy.jp/lain/2012/01/28/473</guid>
		<description><![CDATA[iOS環境ではプッシュ通知が重要だよ、的な周り口で1セッションの通信において複数デバイスにプッシュ通知を行うという記事を投稿しました(因みに自分ではまだやってないのですけどね、同僚が私の作ったモジュールを使って動いている [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>iOS環境ではプッシュ通知が重要だよ、的な周り口で1セッションの通信において<a href="http://lain.heavy.jp/lain/2011/11/14/312">複数デバイスにプッシュ通知を行う</a>という記事を投稿しました(因みに自分ではまだやってないのですけどね、同僚が私の作ったモジュールを使って動いているよ～って言ってるから動いているのでしょう)。</p>
<p>プッシュ通知は重要ながらもチュートリアル的な実装をそのままコピペで実装してしまうと優れた機能も非常に残念なことになります。というのも、例えばよくあるパターンではゲームに対してプッシュ通知が実装されている場合、タイトル画面といった起動した瞬間に「○○はプッシュ通知を送信します。よろしいですか？」と出現するパターン(<strong>画像はあくまでサンプル画面です</strong>が、実際に私が指摘する最悪なパターンを再現してくれたものです)。</p>
<p><a href="http://lain.heavy.jp/lain/wp-content/uploads/apns_dialog.jpg"><img style="background-image: none; border-bottom: 0px; border-left: 0px; padding-left: 0px; padding-right: 0px; display: block; float: none; margin-left: auto; border-top: 0px; margin-right: auto; border-right: 0px; padding-top: 0px" title="apns_dialog" border="0" alt="apns_dialog" src="http://lain.heavy.jp/lain/wp-content/uploads/apns_dialog_thumb.jpg" width="324" height="484"/></a></p>
<p>少しはユーザのことを考えればわかることですが、これって開発側からのエゴの何物でもないですよね。だって、リアルな環境に置き換えるならば、試供品を受け取った段階で</p>
<p align="center"><font color="#ff0000" size="4"><strong>とりあえずDM(ダイレクトメール)送りたいんだけど受け取りますか？</strong></font></p>
<p>と言われているに近しいものだと思うのです。</p>
<p>因みに私はこのパターンは絶対にプッシュ通知を許可しません。だってウザったいかもしれない通知が来るかもしれないのにそれを許可する理由なんてないですから。</p>
<p>&nbsp;</p>
<p>ってことで、長々とウンチクを垂れましたが、端的に言えばプッシュ通知をすべき場所を今一度見直して、細かく制御しましょうよ、と。プッシュ通知はUIAPplicationのインスタンスメソッドとして定義されていて以下の3つがあります。</p>
<ul>
<li><strong>registerForRemoteNotificationTypes</strong>…プッシュ通知を有効にしようとします。ユーザにダイアログでプッシュ通知の確認が求められます  </li>
<li><strong>unregisterForRemoteNotifications</strong>…登録されたプッシュ通知を破棄します  </li>
<li><strong>enabledRemoteNotificationTypes</strong>…(どのような種類の)プッシュ通知が有効かどうかを取得します</li>
</ul>
<p>なので、チュートリアル通りにapplication:didFinishLaunchingWithOptions:でregisterForRemoteNotificationTypesをコールするのではなくて、<strong>どのような目的でプッシュ通知を行いたいかを述べたうえで初めてregisterForRemoteNotificationTypesをコールしましょう</strong>、と。これをやっているのがGameloftの”レッツ！ゴルフ3”ですね。</p>
<p><em></em>&nbsp;</p>
<p>・・・・、と<strong>ここまでが前置き</strong>。そしてようやくタイトルの話になります。上述の通りにプッシュ通知のダイアログが出るタイミングというのは非常に貴重なもので、本当にこのタイミングでよいのかどうかを試験したい場合がありますが、一度この確認でどちらかを選択してしまうと開発中でも中々出てくれません。で、かるーくググってみると大好きなStackoverflowでこんな投稿がありました。</p>
<ul>
<li><a href="http://stackoverflow.com/questions/2438400/reset-push-notification-settings-for-app"><font size="3">Reset push notification settings for app</font></a><font size="3"> (Stackoverflow)</font></li>
</ul>
<p>相変わらずの精度が低いほげ脳内翻訳によれば</p>
<blockquote><p>アプリケーションが初回にプッシュ通知を有効にしようとするならば、iOSはユーザにアプリケーションから通知を受け取るか否かを確認します。一度でもその警告(プッシュ通知の同意ダイアログ)に応答した場合は、デバイスをリストアするか、若しくはアンインストールを行ったうえで少なくとも1日以上経過する必要があるでしょう。</p>
<p>もしあなたが初回のプッシュ通知をシミュレートしたいとするならばアンインストールを行ったうえで1日経過させる必要があります。但し、<em><font color="#ff0000">システムクロックを1日以上経過させたうえで一度デバイスをシャットダウンし、再度デバイスを起動することで後者(=アンインストール後に1日以上経過するという条件)を満たすことができるでしょう</font>。</em></p>
</blockquote>
<p>と書いた本人ですが、実際に試していないのであしからず。</p>
<p>&nbsp;</p>
<p>今回の記事をまとめるとこんな感じ</p>
<ul>
<li>プッシュ通知はアプリケーションが非アクティブ状態でもアプリ提供者側からユーザに情報通知が可能な数少ない手段です。</li>
<li>ダイアログを表示することでプッシュ通知の同意を求める貴重なアプローチは1回のみです。もし本当にプッシュ通知を利用して欲しいのであればこのアプローチを行う前にユーザにプッシュ通知を行う利便性を説くべきでしょう。</li>
<li>プッシュ通知は登録(登録要求)・解除・状態取得の3つのメソッドがあります。</li>
<li>プッシュ通知の初回のアプローチはstackoverflowに書かれているような方法で再度確認を行うことができる(はず)です。アプリの提出前に本当にユーザが望ましい形でそのアプローチが行われているか確認しましょう。</li>
</ul>
]]></content:encoded>
			<wfw:commentRss>http://lain.heavy.jp/lain/2012/01/28/473/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>APNSの複数クライアント送信</title>
		<link>http://lain.heavy.jp/lain/2011/11/14/312</link>
		<comments>http://lain.heavy.jp/lain/2011/11/14/312#comments</comments>
		<pubDate>Mon, 14 Nov 2011 13:00:00 +0000</pubDate>
		<dc:creator><![CDATA[st.lain]]></dc:creator>
				<category><![CDATA[PHP]]></category>
		<category><![CDATA[コンピュータ]]></category>
		<category><![CDATA[プログラム]]></category>
		<category><![CDATA[APNS]]></category>
		<category><![CDATA[ios]]></category>
		<category><![CDATA[複数デバイス送信]]></category>

		<guid isPermaLink="false">https://lain.heavy.jp/lain/2011/11/14/312</guid>
		<description><![CDATA[APNS(Apple Push Notification Services)は書くまでもないと思いますが「プッシュ通知」によりアプリケーション提供側から任意のクライアントにショートメッセージなどでユーザに通知を行う機能で [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>APNS(Apple Push Notification Services)は書くまでもないと思いますが「プッシュ通知」によりアプリケーション提供側から任意のクライアントにショートメッセージなどでユーザに通知を行う機能です。この機能を使えばアプリ提供者側からの通知はもちろん、ユーザ間のやり取りなど幅広く用いることができます。で、既にこの機能自体がiOS3.0以降で組み込まれているので別段新しい機能、という訳でもないのです。が、一方で多くのユーザにお知らせとしてAPNSを送ろうとすると意外に時間がかかるという・・・・。</p>
<p>あまり知られてはいないようなのですが、APNSを1回のSSLコネクションを通じて複数のユーザ・クライアントに飛ばすことが可能です。APNSで使用されるプロトコルは非常に有名なチュートリアルサイト  </p>
<p><a href="http://blog.boxedice.com/2009/07/10/how-to-build-an-apple-push-notification-provider-server-tutorial/">How to build an Apple Push Notification provider server (tutorial)</a>で案内されている通りです。複数に送信する場合は、単純にこのメッセージ部を繰り返せばいいようです。プログラム的には以下の感じ。 </p>
<pre><pre class="brush: php; title: ; notranslate">

$devices = (array)$devices;
foreach ($devices as $device) {
  $apnsMessage = chr(0) . 

    // token length
    pack('n', 32) . 

    // device token
    pack('H*', str_replace(' ', '', $deviceToken)) . 

    // payload length
    chr(0) . chr(strlen($payload)) . 

    // payload
    $payload;

  // send apns message
  fwrite($apns, $apnsMessage);
}

</pre>
<p>但し、注意ごととしては以下の通り。</p>
<ul>
<li>(複数クライアント送信に限ったことではないですが)Payloadが256Byteを超えてはならない</li>
<li>1回の通信で全パケットが約7000Byteを超えるとサーバから切断される、らしい (←どこかで見た・・・)</li>
</ul>
<p>なので、1メッセージが以下のような最長だとすると・・・・？</p>
<ul>
<li>1byte &#8211; コマンド (token)</li>
<li>4byte &#8211; デバイストークン長</li>
<li>32byte &#8211; デバイストークン</li>
<li>1byte &#8211; コマンド (payload)</li>
<li>1byte &#8211; ペイロード長</li>
<li>256byte – ペイロード</li>
</ul>
<p>295byteとなり、仮にサーバ切断となる7000byteまで達するには20人程なら余裕で許容できる範囲となるはずです。多分、10人程度なら超余裕ではないのかな、と。</p>
<p>APNSに関しては<a href="http://lain.heavy.jp/lain/2011/09/14/190">GameCenterやInApp-Purchaseの不具合</a>とは異なってSandboxでも非常に安定をして動きます。なので、リリース(Distribution)前にしっかりと確認を行うことができるのでパフォーマンス調整を行ってみると良いかもしれません。</p>
]]></content:encoded>
			<wfw:commentRss>http://lain.heavy.jp/lain/2011/11/14/312/feed</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
	</channel>
</rss>
