課金をAIDLからBilling Libraryに変更した話

以下を参考に実装した。

バージョンとコード

implementation ‘com.android.billingclient:billing:1.2’

感想

AIDLファイルを残したままにすると、デバッグビルドは通るがリリースビルドでのみこけるのに多少ハマったけど、それ以外はすごく使いやすくなっている。developerPayloadがなくなっているので使う前提のサービスだと変更はできないが、developerPayloadはdeprecatedにまではなっていないが、将来的に消えるらしいのでdeveloperPayloadに依存しないアプリを作ったほうが良い。

また、1.1から1.2へのアップデートでBillingFlowParamsのsetSku / setTypeがdeprecatedになっており、setSkuDetailsを使うことが推奨されている。引数として使用されるSkuDetailsのconstructorはjsonSkuDetailsのStringを設定する口しかなくBuilderも存在しないため自力で作ることが困難な作りになっている。GoogleとしてはquerySkuDetailsAsyncでSkuDetailsを取得したものを使用して課金処理を実行してほしいのだろう。SkuDetailsにはストアで設定したタイトルや詳細が取得できるので、これを使用してUIを作り保持しているSkuDetailsを使用してそのまま課金処理に移ってほしいという流れなのだろうと想像している。PlayStoreでの課金アイテムを変更するだけでアプリをアップデートすることなく課金アイテムを変更できるという利点もあるわけだが、タイトルにアプリ名が含まれているしストアで設定した文言がそのまま表示されるわけではないのであまり使い勝手は良くない印象を受けた。アップグレード、ダウングレードもsetOldSkuを設定するだけで対応できるのは非常にありがたい。

サービスで使用する場合はstartConnectionのエラー時に再接続処理を走らせたり、課金アイテムの消費タイミングを変更したり、課金完了時にレシート情報をサーバに送信しサーバ側で有効なレシートかチェックしたりと色々やる必要はあるが、クライアント側の処理は非常に簡潔になりすごくよい。AIDLで消費する前にBillingLibraryを使用したほうがなにかと捗りそうだ。

firebase + express + typescript で立ち上げ

メモ

firebase-toolsをインストール

  • npm install -g firebase-tools

firebaseの初期化

  • firebase init
  • hosting と functions を選択
  • 適当に選択
  • javascript or typescript が出てきたときに typescriptを選択

expressをインストール

  • cd functions
  • npm install –save express

expressでルーティング

  • ./functions/src/index.ts にルーティング処理を記載
  • exports.app = functions.https.onRequest(app); // app = express()

rewrites処理を記載

  • ./firebase.json にrewritesを追加
  • “hosting” に “rewrites”: [{“source”: “**”, “function”: “app”}] を追加
  • appはexportsしたものと同じ名前

localサーバを起動

  • firebase serve
  • ※ firebase serve –only hosting,functions で起動しろと書いてあるが、そうすると動的コンテンツのほうが動かなかった。。。

錯覚資産という極論 – 人生は、運よりも実力よりも「勘違いさせる力」で決まっている

読んだ。

この本を読んだ理由としては「分裂勘違い君劇場」というブログの作者はどういうことを書くのだろうという興味だ。このブログは過激なことを論理建てて書いていることが多く、極論でありながらも面白くまとめる自頭の良さを感じる文章であり、その作者が本を書いたと聞けば読まずに入れなかった。読んだ感想としては、ブログ同様読ませる力が強く論理的だが極論だなと感じた。

書いていることをものすごく要約すると、誰かに優秀だと錯覚させることでその人からの評価は優秀だというバイアスが掛かるので、この錯覚をうまくさせる様にすることで人生がうまく回るというものだ。筆者はこのバイアスを「錯覚資産」と言っており、この錯覚資産をうまく運用することで成長するチャンスも増え、自らが成長することでさらなる錯覚資産を得ることができ加速度的に成長できると書いている。これは僕の実体験としても当てはまり頷ける。僕は前から優秀な人が良いポジションにつくというより、良いポジションについたことにより優秀な人になるという考えを持っていた。これは筆者が言う「錯覚資産」によるものでもあるのだろう。優秀な人間は最初から優秀なわけではなく良いポジションに付き他の人間と比べて優遇された教育と優秀な周りの人間に支えられ更に優秀になっていくものだと思う。

しかし、勘違いしてはいけないのは良いポジションにつくということは諸刃の牙であるということだ。錯覚資産によってその人間が持っている能力は他の人に比べてベースが上がっているにしても、その人間の能力が著しく低かった場合は周りは騙されない。錯覚資産という幻想はもろくも崩れ去り、負の錯覚資産が発生し場所を変える以外に再起は不能になることも考えられる。日本という国は今の所歯医者に厳しい。大きな成功を繰り返すよりも、一度も失敗しないということのほうが遥かに重要だったりする。このような状況でチャンスを当て得られ続けるそれに答え続ける力がなければ、失敗の烙印を押され惨めな人生を送ることになるのだろう。1億の負債を出せればそれはそれで評価されるという話があるが、あれは社外の話であり社内では失敗は失敗として淡々と処理されている可能性も高い。

筆者は途中で書いているのだが、「分裂勘違い君劇場」というブログは極論を話すだけで良いのであれば、どのような話でも説得力がある話になるということを実験するための場所だったと書いている。ブログタイトルが表しているように「西にいけ!」と主張していた人間が、次の日には「東にいけ!」と主張したりするような精神が分裂しているような文章を書いていたのだという。極論は非常に甘美でわかりやすく受け入れやすい。この文章は「錯覚資産」という甘美でわかりやすい極論を主張しているのではないかと疑ってしまう。書いている内容としては頷ける点も多いわけだが、それも「ふろむだ」という人間を僕が知っていたが故の錯覚資産に騙されている可能性はある。それを考慮したとしてもわかりやすく心理学のTipsを散りばめながら自分の主張を補強していく様は面白い。

読んでみて損はしない本だと思う。

DataBindingでSpannableStringを使いたい

TextViewの装飾でSpannableStringを使っているのに、ObservableField()を使って値を設定すると装飾が消える。

ObservableFiled()を使って設定すれば装飾が残るのでこっちを使おう。

RealmにEnumを保存したい

RealmはEnumを保存できない。なので、nameを保存してそれを使ってenumが引ける口を作ると簡単だと思う。

WorkerManager#beginUniqueWork で複数登録する場合はDelayを入れたほうが良い

WorkerManagerのbeginUniqueWorkでWorkerを大量に突っ込むと3つ目で以下のエラーを吐いて落ちる

E/WorkerWrapper: Status for aa9f2b0d-d327-4a9f-bac1-5f3e6799603a is ENQUEUED; not doing any work

以下のようにちょっとだけDelayをいれると動いた。

うまいことWorkerをまとめる術があるのなら他にやったほうが良さそうだが、beginUniqueWorkでまとめる場合はDelayをいれたほうが無難だと思われる。

子育てのプロなんて存在しない

子育ては迷うことが非常に多い。通説もいろいろ変わる。抱っこしすぎるのは良くないって言われていたけど、そんなことはないということがわかったり、英語は小さい頃から聞かせておくと英語脳ができると言われていたけど、小さいときに英語を教えるとエセバイリンガルになってあまり良くないと言われていたりもする。学説でさえいろいろ変わっているのだから、親として子供にどう接すればいいのかは非常に悩む。

子育てのプロと呼ばれる人間は世の中に存在する。保育士だったり学校の先生だったり、多くの子供と接しどのように接すればどのような返答が帰ってくるのかをだいたいわかっている人間のことだ。しかし、我が子となると子育てのプロであってもうろたえる。子育てのプロが知っているのはいろいろな子供の平均値であり、しかもそれはある特定の場所にいる子供の平均値でしかない。我が家で親子として接している子供の姿の多くを知っているプロは少なく、自分の子供が平均的に動くことも稀であり、すべての人は子育ての初心者として子育てを始めることになる。

子育ての初心者としてちょっと手慣れてきたときに第二子、第三子と生まれたとしても、子育てはせいぜい7人ぐらいが限度となる。長い人生においてたった7人の子育てしか経験できないのだ。その子育ての平均値をみても母数が少なすぎて、この子にうまく行ったことが他の子でうまくいかないなんてことはよくあるはずだ。じゃあ、親を頼ってみたとしても、親は我が子を育てたことはあるが、我が孫を育てたことはない。子育てとは全てが初めてで、ほとんどのことがもう一度経験できないことの繰り返しなんだと思う。

なので、学説に頼っても学説はすぐに覆されるし、他人を頼っても他人はあくまで他人で他人が見た平均値の返答しかできない。我が子を我が子として認識できるのは自分と妻だけしか存在しないのだから、どうなってもしょうがないと開き直るしかない。我が子を可愛がりたいなら可愛がればいいし、我が子を厳しく育てたいなら厳しく育てればいい。我が子がおとなになったときに、あのときにもうちょっと別の育て方をすればと考えるときは誰にでもきっとくる。しかし、それは全てが過ぎ去ったからこそ判断できることであり、そのときにそのタイミングがもう一度訪れたとしても同じ決断はきっとできないのだ。

「道具」ではなく「文化」をもたらすサービスがいいよね

Instgramは「画像を上げてみんなで見れるサービス」だし、Twitterは「短い文しか上げることができないブログ」になる。どちらも作るのは非常に簡単で、主要な機能だけならすぐに作れるものだろう。単純なサービスは簡単に作ることができる。言い換えれば簡単に似たようなサービスを作ることができる。しかし、その中で流行るサービスと流行らないサービスに別れてしまう理由を前はサービスの利便性だとか機能だと思っていた。しかし、最近は「文化」のほうが重要なのではないかと思えてきた。

サービスの使いやすさや機能というのは地盤でしかない。最低限の機能が最低限使いやすくできていれば、それ以外の機能はオプションなので必須ではない。必須ではないものを詰め込んでいけば、使い勝手は良くなり裾野が広がり使う可能性がある人間は増えるだろう。しかし、それは「道具」として使えるようになったに過ぎない。「道具」はあくまでも「道具」で使いやすいものが出てくれば取って代わられる。使いやすいものというのを突き詰めて他のサービスを落とすという方法もあるのだろうが、それには多大な労力がかかり、巨人が同じようなサービスを出してくると潰される可能性がある。

しかし、「文化」は真似することができない。使い勝手は悪いけど、なんとなくこのサービス内の雰囲気がよいから使うというのは往々にしてあると思う。Instagramに写真を上げればなんとなくおしゃれになった気分になるし、Twitterには適当な文章を吐き出して良さそうな雰囲気がある。この「文化」が非常に大切で、最終的にどういった文化をそのサービス内で形成したいのか?から逆算してサービスをつくるというのは良いアプローチなのかもしれない。やりたいことを実現するためにアプリを作るのではなく、どういった人をあつめたいのかというアプローチから逆算してアプリを作ると面白いのかもしれない。

Google Sign-InでApiException: 12501がでて失敗する

以下のエラーがでて失敗する

> com.google.android.gms.common.api.ApiException 12501

手順は以下の通り

OAuth2のClientKeyが設定されてないのがだめというものを見つけたけど違った。

結局、 GoogleSignInOptions.DEFAULT_SIGN_IN を設定しないといけないところを GoogleSignInOptions.DEFAULT_GAMES_SIGN_IN を設定していたからエラーとなっていた。

うまくいったコード

バージョンは以下

> implementation “com.google.android.gms:play-services-auth:15.0.1”

FirabseのAuthUIで[Code: 10, message: 10]のエラーが出る

FirebaseのAuthUIを試してみたけど以下のエラーがでて動かない。

com.firebase.ui.auth.FirebaseUiException: Code: 10, message: 10:

よくよくみると以下のワーニングが出ていた

Developer error: this application is misconfigured. Check your SHA1 and package name in the Firebase console.

SH256のほうがいいだろうと256しか登録していなかったが、SHA1が登録していないとだめらしい。FirebaseConsoleの設定からSHA1を登録したところ問題なく動作した。