eaglesakuraの技術ブログ

技術的な話題とか、メモとか。

開発リソースがないなら、Google Playのリリースは取り下げておけ、という経験則

こんな状況は危ない

  • 昔は自社でアプリ開発してたけど、もうメンテしなくなって久しい
  • とりあえずアップしておいて、使う人がいるならソレでいいや

何が起きるか

  • Google Playは年1〜2回くらいはConsoleのアップデートがある
  • アップデートにより、一部のアプリは修正が必須となる場合がある
    • アプリ内容だけでなく、プライバシーポリシーとかが必須となったり

放置すると何が起きるか

  • アプリがBANされる
  • BANされるとメールが飛んでくるが、見逃しがち

BANされたものは復帰できるか

  • 開発リソースがあるのなら、BAN理由に対して対応を行う
  • 基本的にノーコストでBAN解除はしてもらえない
  • Google is GOD.

開発リソースがないとどうなるか

  • とりあえず放置しがち

BANが増えていくとどうなるか(都市伝説)

  • これは都市伝説だが、3BANでGoogle アカウントBANとなる
  • 都市伝説だが。

対応コストが高すぎる、サービス終了してアップデートの予定もない

  • 仕方ない、 アプリは提供終了しました というTextViewだけ表示するアプリに上書きアップロードしよう

最悪のパターン

  • 署名鍵を紛失し、Cloud Signしてない場合は詰む

そうなる前に

  • アプリの継続的アップデートができないと判断したら、さっさとアプリは非公開にしたほうが精神的に良い
    • あとから公開に戻せるから
    • いままでDLした人は継続的にDLできるから
  • もしくは、開発用・個人用のアカウントとGoogle Play Consoleに使うアカウントは完全に別にする

最後に

  • グーメン

やっぱ時刻でIDとってるようなのはダメだな

何が起きたか

  • 時刻ベース(ナノ秒)でUnique IDを割り振っていた

速度を向上させた

  • UnitTestの実行速度が向上した
    • みんなも使おうRyzen TR
    • 人類皆RAM 64GB
  • 何故かテストが落ちまくる
    • ランダムで落ちまくる
    • ランダムで成功する
    • 1時間位頭抱えてた

問題点を見つめ直す

  • FirestoreのIndexが貼られるまで時間かかるせいか?とか考えた
    • Sleep適当に入れてもダメなものはダメ
  • 仕方ないのでラブライブBlu-Rayを再生した

何が起きていたか

  • Unique IDの割り振り部分が早くなりすぎて、同じIDが複数発生してしまっていた

どうやって解決したか

  • UnitTestのUID割り振りをatomic intでインクリメントさせるようにした

反省点

  • やっぱ時刻でIDとってるようなのはダメだな
  • やはりラブライブ!のライブblu-rayを再生しているとバグが取れる

Flutterのプロジェクトが始まったらまずやること

XCodeと仲良くScheme設定

  • だいたいProductionとDevelop環境別れてるんだからSchemeを作成する
  • SchemeとDebug/Releaseの組み合わせに合わせてConfigurationファイルを作成する
  • 何をする用事がなくても、pre buildスクリプトSchemeごとに設定しておく
    • どうせGoogleServices系のJSONを置き換えたりするんだよ
    • XCode、お前だよお前

build.gradleと仲良くFlavor設定

  • まあFlavorわけるよな
  • デフォルトで「適当にapplication id設定しとくか」ってやって、本番用に書き換えようとしたら「あのファイルとこのファイルとあのファイルが古いままだよ」ってなるから
  • 早めに設定してスッキリしておこう
    • まあ、ケツを叩いてさっさと決めてもらおうな、Application ID

.gitignore整理

  • お前なんでそんなにすぐ差分発生するんだよ
  • XCode お前だよお前

わかる範囲で入れそうなpubspec.yamlに突っ込んでおく

  • お前らどうせプラグイン同士で干渉するんだよ、わかってるぞ?
  • ほら、patchあててやるから、こっちにおいで

Flutterは

GAE/Go 1.12は認証ヘッダが重複しているとGoogle Frontendが自動的に400を返却する

どういう問題か

  • GAE/Go 1.12にバージョンアップをした
  • サーバー側のUnitTestは通過していた
  • クライアント側のテストを行うと、特定APIがすべて400を返却していた
  • ログが残っていない。少なくともGAEアプリコードに到達していない。

原因

  • クライアント側で Authorization ヘッダを複数回付与してしまっていた
  • GAE/Go 1.9までのGoogle Frontendを通過してGAE/Goのコードに到達していた
  • 少なくともGAE/Go 1.12では Authorization ヘッダを複数受信した時点でGoogle Frontendが400を返却してコードに到達しない
  • 重複していたヘッダを削除したら問題が解決した

よくわからないところ

  • Androidバイスでokhttp3を使って再現する
  • JVMのUnit Test(Robolectric)でokhttp3を使うと再現しない
    • Android Frameworkとhttp通信の内部実装が異なるからだろうか?

対策

  • Authorization ヘッダは、いつもひとつ!

日本でデジタル母子手帳を運用するとしたら?

この記事はなに?

  • ちょっとした頭の体操である
  • つらつら思ったことを書くだけ

デジタル母子手帳

  • そのまま、いま子育て世代が(基本的に全員受け取っているハズの)母子手帳スマホで見たり管理したりできるようになる
  • 検索すると、色々ニュースやプレスリリースが出てる

個人的な見解

  • 本当に必要な状態を満たして、普及すればとても良いことだと思う
  • しかし
  • ここは2019年の日本
  • あの マイナンバー を作り出した国やぞ

最低限必要な要件を考える

現状

  • 公的・民間問わず、複数の母子手帳サービスがリリースされている

www.mchh.jp www.boshi-techo.com

各種記録機能

  • 予防接種などの記録を保持する
  • 必要な記録(1語、2語の発話時期とか)を書き込める
  • その時の状況、単語内容などのメタデータ(コメントデータ)を書き込める

アクセス権限の付与

  • 母子手帳は、「母」「子」だけが使うものではない
  • 必要に応じて家族や医療従事者・関係者(医師、父、祖父母、保育園の先生、etc...)がアクセスできなければならない
    • 現代のスマホはプライバシーの塊であるため、あまりユーザーの目のつかない場所に移動されるリスクは避けなければならない
    • そもそも最短1分以内でロックが掛かってしまう

リテラシーとセキュリティの問題

  • 母子手帳は「スマホを無くした」程度で復元できなくなたら困る
  • 「機種変更は引き継ぎコードが必要です」「スマホを無くしたら諦めてください」では使用を継続できなくなる
  • アカウントのような仕組みに落ち着くと思われる
  • アカウントに登録したメールアドレスにアクセスできなくなる未来がある
    • キャリアメール、お前はダメだ
  • 複数のサービスがあるということは、病院関係者はサービスごとに母子手帳にアクセスできなければならない
    • 病院がサポートしてない場合、「自分で操作してね」となって予防接種の記録を書いた紙を渡されるだろう
    • それをどのように入力する?
    • スマホで写真撮影 -> 取り込みだろうか
    • 画像のママじゃないと辛い
    • フォーマットが画一的じゃないので、多分正常に読み込める紙面はほとんどない
    • じゃあ「検索性」はどうなる?
    • でぃーぷらーにんぐってやつでなんとかして!!
  • 母子手帳のアカウントオーナーは誰なのか?
    • 最初のオーナーは母親となる可能性が高いが、オーナーは変更できなければならない
    • 「母子」手帳であるが、母親に親権があるとは限らない
    • 裁判所命令によって「オーナー情報の変更」をサポートできるのか?
    • 自分自身の母子手帳へのアクセス権は、認められるのか?
      • 親と折り合いが悪い、親が不慮の事故で亡くなった場合、自分自身の情報へアクセスできなくなる可能性がある

適切なエクスポート

  • 民間サービスは、かんたんに終了する
    • サービスの運営・開発はタダじゃない
    • 新しいOSバージョンへの対応もタダじゃない
    • ソフトウェア開発者は(多くの人々・先人の努力により)平均より高い賃金ベースとなり、人件費が想像以上に高い
    • 娘が生まれたときに産院と提携していたサービスはサービス終了によりアクセス不可、写真のみエクスポートできた
  • サービス終了時、エクスポートできなければならない
    • 最終的に人間が判読可能な状態が望ましい
    • 製本のようなサービスになるだろうか?
    • 物理メディアが絡むとまた維持費が上がる
  • 他のサービスの相互運用は?
    • 難しい
    • 民間サービスは「独自性」や「他よりも優れている点」を推しだしてシェア拡大を図る
    • 互換性が完全に取れない仕様がある可能性が高い
      • 特許や実用新案といった形で自社を保護するしね

公的な機関がやってくれるのか?

  • 厚生労働省主導になるか?
  • すでに母子手帳を持っている人たちの引き継ぎはどうするか?
  • 将来、Webに変わる新しい仕組みが出来る可能性
  • 50年後の未来、一般的なデータベース(MySQL、その他色々)が存続できているか
    • その時時で技術的負債を取り払えるか
    • まあ、大きな予算を獲得するのは難しいやろうなぁ
    • だって「いま動いている」から
    • ひたすら延命措置を続けるのだろう

他のサービスはどうなっているか?

  • 誰もが必要で、民間もやってる、そう、金融
  • めっちゃ莫大な金をかけて、ちょいちょい失敗する
  • 「国民全員、青い銀行の口座をメインにしろ」はちょっと心が辛い

20年後の未来

  • 自分の子供達が大人になるまでに、「紙の母子手帳」に変わるより便利で優れたものを作り出して上げるのが我々世代の役目だとは思う
  • 道は険しく、僕は今日もKotlinを打つ。
  • System.exit(1)

特定条件下でMotionLayout配下のViewが再描画されない問題のWorkaround

バージョン

"implementation"("androidx.constraintlayout:constraintlayout:2.0.0-beta2")

問題点

  • MotionLayout配下にFrameLayoutを配置し、動的にコンテンツを入れ替える
  • MotionLayoutはアニメーションで2つのレイアウト間を遷移させている
  • 特定条件下で、MotionLayoutの初期状態を 遷移後のレイアウト にしている
  • 処理としてはこんなの
if (/* 特殊な場合 */) {
    // 強制的に遷移状態にしておく
    motionLayout.progress = 1.0f
    motionLayout.transitionToEnd()
}
  • そしてActivityの再生成を行う
    • DeveloperオプションでActivity強制破棄 -> Recentして再度アプリに戻るとすぐに再現できる
  • コレをやると、MotionLayout自体はEnd位置になっていて想定通りだが、MotionLayoutの中にあるchildFragmentの中のコンテンツが正常に描画されない

ワークアラウンド

  • 強制的に再レイアウトと再描画を繰り返す
  • ずっとやるとマシンパワーを喰うので、1秒程度やれば再描画されてOK
launch(Dispatchers.Main) {
    val invalidateTimeout = (System.currentTimeMillis() + TimeUnit.SECONDS.toMillis(1))
    while (System.currentTimeMillis() < invalidateTimeout) {
        motionLayout.requestLayout()
        motionLayout.invalidate()
        delay(1000 / 60)
    }
}

何が問題だったのか?

  • よくわからないが、しばらく様子を見よう
  • betaだし

2019年壊れたものとその対応

Mac Book Pro 15inch late 2013

Pixel3

  • 購入直後に画像処理プロセッサが死んでいることが発覚
  • 良品交換
  • しようと思ったら多重決済をしてしまい、一時的に30万円が吹っ飛ぶ

Huawei P20 Pro

  • GPSを掴まなくなる
  • Wi-Fiアシストは効くので、都市部では使用可能、カーナビ使用不可能
    • カーナビとして使うまで、故障自体に気づかなかった
    • アシストって強いんだな
  • 修理代を考えると、別端末への買い替えも視野

PS4

  • Blu-Rayがejectできない(稀によく)
  • ゲームはDL版だけど、BD再生はやりにくくなってしまった

ミラーレス一眼(NEX-6)のバッテリー

  • 6年使ってるので、多分寿命だろう
  • 買い替え

ARCHISS Progrestouch

  • Enterキー、逝く
  • ッターンしすぎが原因の最有力候補
  • 同じものを2つ追加で買ったので、大丈夫

ゲーミングマウス G602

  • 左クリックが効かなくなる
  • OS側の問題と思ってたら、ハードウェアだった
  • トラックボールの SW-M570 に切り替えた

Logicoolトラックボールマウス

  • SW-M570 の有線仕様版
  • 右移動が効きにくくなる
  • 廃棄

寝室のクーラー

  • 一人暮らし時代から使ってた11年モノ
  • 廃棄して入替え

ダイソン V11掃除機

  • 吸引力の変わらない、ただ一つの掃除機
  • 掃除中に何も吸引しなくなり、死亡
  • 購入直後のため、無償交換
  • ただし返送の必要あるのでメンドウ

Nintendo Switchの充電器

  • 購入直後にHDMI端子死亡が発覚
  • 返金

身体

  • 3月まるまる風邪をひく
  • 7月前半も風邪をひく

追記1. 腰

嫁さん曰く

  • 「憑かれてるんじゃない?」
  • 憑かれてるんじゃない、疲れているだけだ、たぶん。

追記2.

トースター

  • Google Developer Expertからの結婚の贈り物
  • 購入してから7年間、最近は毎日毎日子どもたちのパンをこんがり焼いてくれたトースター
  • 煙を吹いて無事死亡
  • 買い替え

メイン機のWindows環境

  • ずっとWindows Updateブルースクリーンが出るようになってた
  • ドライバのアップデートも行えなくなった
  • 仕方ないので再インストール
    • 一番時間がかかったのがSteamのゲームインストール