Drowsy Dog's Diary

any note, any thought

2014年8月21日
by kazoo
0 comments

[ios][appstore] In-App Purchase プロダクトとアプリバージョンの紐付け

これもやるたびにミスって Developer Reject するので今さらだけどメモっておく。。

iTunesConnect に新規のアプリ内購入(IAP)アイテムを追加するときの順序について。

基本的にここでは Non-consumable プロダクトについて書いてます(これしかやったことない)。
間違い等ありましたらご指摘いただけると重畳。

現バージョンのアプリでそのまま購入できるアイテムを追加する場合

これは単純に、アプリ管理画面の “Manage In-App Purchase” から “Create New” ボタンで追加して submit すればよい。

ProductID や値段など、基本的な情報を登録して Save すれば、 Submit する前にテストアカウントで購入テストができるようになる。この時点でサムネイルはまだ無くてもOK。

テストアカウントは、iTunesConnect トップの “Manage Users” から登録できる。Android と違って「購入キャンセル」というものが(事実上)存在しないので、同じアカウントで同じアイテムの購入テストは一度しかできない。なのでメールアドレスがいくつも必要になったりするが、そんなときは「10分間だけ有効な」アドレスを生成してくれる 10 Minute mail がべんり。

http://10minutemail.com/

テスト用購入確認ダイアログには、[Environment: Sandbox] という表記が付いている。レビュー用のサムネイルにどのような画像を使うのが適切か定かではないが、kazoo はいつもこの購入ダイアログのキャプチャをサムネイルにしている。

アプリのバージョンアップと同時に課金アイテムを追加する場合

問題はこのケース。未確認だがたぶん新規アプリの場合も同じ。

アプリのバージョンアップで買えるようになる課金アイテムは、まず上と同様に “Manage In-App Purchase”から新規アイテムを追加し、サムネイルを登録して “Ready to submit” の状態までもっていく。Submit はしない

次に、”Add Version” ボタンからアプリの新規バージョンを用意して、更新情報を追加する。ここで注意するのは、“Ready to Upload” ボタンを押す前に、このバージョンに課金アイテムを紐づける必要があること。状態が “Waiting for Upload” になってしまうと、もうそのバージョンは一度リジェクトしない限り紐付けはできない。

状態としては “Prepare for Upload”(または Developer Rejected)のときに、アプリの Deteil を見ると、このときのみ In-App Purchase の編集ができるようになっているので、これをエディットして、先ほどのアイテムを紐づければよい。Submit はまとめて行われるので、”Manage In-App Purchase” での Submit は必要ない。

IAP

アイテムを “Ready to submit” にする → アプリが “Prepare for Upload” のときにそれを紐づける。

書き記すと大したことではないのだが、うっかり失敗すると、一度 XCode から Submit して Developer Reject して(しかも次に再アップロードする際にまったく同じバイナリでは受け付けてくれない)というのが大変めんどくさい。アップロードとキャンセルが同時に走るのを避けたいのだろうが、Waiting for Upload を一回押してしまうと絶対にキャンセルできないのどうなん??と毎回思う。。

ちなみに、アプリバージョンと課金アイテムバージョンに依存関係がないからといって、In-App Purchase が Waiting for Review のときに次のアプリバージョンを Submit したりすると、まだレビュー通ってないアイテムに対して「このバージョンでこれ買えないぞ」みたいな Reject をされることがある(ぽい)。
基本的に、アイテムとバージョンを完全に紐づけるか、アイテムがレビュー中のときにはアプリ本体は触らない方が良さそう。

参考:
In-App Purhcaseプログラミングガイド

2014年7月2日
by kazoo
0 comments

[android]ギャラリーから画像を縮小して読込む

BitmapFactory でそのまま読むとメモリ不足が起きるようなでかい画像の場合、BitmapFactory.Options の inJustDecodeBounds を true にして、メモリに展開せずにパラメータだけをデコードできるので、その後あらためてスケールサイズ(inSampleSize)を指定してデコードしてやればよい。

2014年7月2日
by kazoo
0 comments

[android] KitKat でギャラリーから画像取得

ギャラリーから写真を取得するとき、以前の Intent.ACTION_PICK が返す URI が、

content://media/external/images/media/3951

のように返っていたのに対し、
KitKat(API Level 19) では、MediaStore.Images.Media.DATA で ContentResolver にクエリした場合、

content://com.android.providers.media.documents/document/image:3951

といった URI が返ってくる。

Android Gallery on KitKat returns different Uri for Intent.ACTION_GET_CONTENT – Stack Overflow

KitKat では、Intent に ACTION_OPEN_DOCUMENT を設定し、takePersistableUriPermission(android.net.Uri, int) を呼んでやる必要があるとのこと。

2014年2月4日
by kazoo
0 comments

[rails]アセットパイプラインのためのApache最適化設定

アセットパイプライン

「アセット」とは Web サーバ上の静的コンテンツのこと。具体的には、画像、CSS、Javascript などのファイル。

アセットパイプラインはバージョン3.1以降の Rails に備わっている機能で、主な役目はアセットを圧縮・結合すること、そしてファイルのフィンガープリントをファイル名に組込むこと。この2つの操作を「コンパイル」と呼んでいる。

は、アセットをコンパイルするコマンド。
app/assets/images/
app/assets/stylesheets/
app/assets/javascripts/
app/assets/fonts/

などにあるファイルが「プリコンパイル」される。

コンパイルによって、 app/assets/images/ 以下の画像ファイルには MD5 ハッシュをファイル名に付加して /public/assets/ にコピー。また CSS/JS は、それぞれの拡張子(.scss, .erb, .coffee など)に応じた方法でファイルが変換され、CSS や JS ごとの結合が行われた後、Minification(空白、改行、コメントの除去等)された後に gzip 圧縮される。

このようにすることで、アセットの通信量を最小化しつつ、ファイルの中身の変化に応じてファイル名自体が変わるので、ブラウザやプロキシサーバにキャッシュされていても古いファイルが替わらないという問題を避けられる。むしろ /assets/ 以下の URI へのアクセスに関しては、出来る限りキャッシュを推奨するのが望ましい。そのための HTTP リクエスト/レスポンスのヘッダ設定が以下のようになる。

キャッシュ設定

ここでは CentOS 想定。設定ファイルパス、URI は適当に読み替えてください。

/etc/httpd/sites-available/my_site

それぞれの意味はこんな感じ。

  • ExpiresActive… On にすると Expires および Cache-Control ヘッダを生成する
  • ExpiresDefault… Expires に設定するデフォルトの値。ここではアクセス日時+30日間
  • Header set Cache-Control… HTTP ヘッダの Cache-Control の値を上書きする。”public” は、ブラウザだけでなく Web プロクシにもキャッシュを許可する
  • Header unset Etag… HTTP ヘッダの ETag を削除する(レスポンスが ETag ヘッダを持たないようにする

圧縮設定

アセットパイプラインにおける CSS ファイルなどは圧縮・結合された上で /public/assets/ に配置される。そのとき、*.css, *.css.gz の2つのファイルが生成される。ミニフィケーションと結合だけが行われたものと、それをさらに gzip したもの。

現在多くの Web ブラウザでは、gzip形式で圧縮されたコンテンツをサーバから受け取って、それを展開してからレンダリングする機能を持っている。そういったブラウザは、Accept-Encoding リクエストヘッダに gzip あるいは x-gzip という文字を含む値をセットする。これを受け取った Apache や Nginx といった Web サーバは、その場でコンテンツを圧縮して送り返す。

しかし、アセットパイプラインを利用している場合はすでに圧縮されたファイルが存在しているので、この圧縮は CPU の無駄となる。なので、すでに圧縮済みのファイルを利用するような設定が以下となる。

/etc/httpd/sites-available/my_site

  • AddEncoding… 拡張子 .gz のファイルのエンコーディングが x-zip だと指定する。
  • Header set Vary Accept-Encodig… Vary ヘッダは、リクエストのヘッダによってレスポンスが変化することと、その基準となるリクエストヘッダを Web プロクシに教える。これによってたとえば gzip 圧縮に対応しているブラウザとしていないブラウザが同一のプロクシにアクセスしても問題が出ないようにできる
  • RewriteEngine on/RewriteCond… Accept-Encodingヘッダに gzip/x-gzip という文字を含むリクエストで、かつ末尾に .gz を加えた URI に対応するファイルが存在する場合、それを返す
  • <FilesMatch>…. 拡張子 .css.gz および .js.gz の MIME タイプを ForceType ディレクティブによって指定する

2014年2月4日
by kazoo
0 comments

[css] WebViewで長押し等を禁止

ハイブリッドアプリ中の WebView で、ネイティヴっぽさを削いでしまう機能やメニューを排除するためのCSSメモ。

また、上記の選択不可の設定をしてしまうと、input要素に入力などもできなくなるので、

といった書き方もできる。

参考:
http://stainless-note.tumblr.com/post/47653591131/css-css
http://www.slideshare.net/hagino_3000/ioswebviewapp