真面目なブログはこっち 👉 blog.s64.jp

Androidライブラリ開発でRuntimeInvisibleParameterAnnotationsとなりアプリがビルドできない時の対処法

明確な原因まではわからないものの、対処法までは見つかったのでとりあえず書く。ざっくり言うと、Jetifierのバグを踏んだらしい。

問題の再現手順

ライブラリプロジェクトとして、Android Support Libraryを用いたものを作成する。AndroidXではない。

api "com.android.support:support-annotations:28.0.0"

下記のようなEnumクラスを作成する。ポイントなのは、コンストラクタのパラメータにAnnotationが付けてあること。

public enum MyOriginalEnum {
  
  MyOriginalEnum(@Nullable Integer hoge) {
    // do something
  }
  
}

このクラスをライブラリとして参照するプロジェクトで、Jetifierを有効にする。gradle.propertiesにある。

android.useAndroidX=true
android.enableJetifier=true

このEnumをJavaコードから参照する。importだけでも再現する。Kotlinから参照する場合は関係ない。

Log.d("Hoge", MyOriginalEnum.values());

すると、下記のようなエラーになってコンパイルができない。

エラー: MyOriginalEnumにアクセスできません
クラス・ファイル/Users/****/.gradle/caches/transforms-2/files-2.1/****/jetified-****-api.jar(****/MyOriginalEnum.class)は不正です
RuntimeInvisibleParameterAnnotations属性が不正です: MyOriginalEnum(Integer)
削除するか、クラスパスの正しいサブディレクトリにあるかを確認してください。

対処方1

Enum側のパラメータに付与してあるAnnotationを外す。今回の場合は @Nullable を外すので、IDE補助がなくなる。

対処法2

Jetifierを使わない。どうもこの問題はJetifierによるバイトコードの変換で発生しているらしい。

対処法3

Kotlinコードからしか参照しない。試したところ、Kotlinからしか参照しない分には問題は発生しなかった。

2020年賀状を住所を知らないネットの友達に自作デザインで送る

2020年 (2019年末投函分) の場合、日本郵便のはがきデザインキット2020 Web版を使えばいける。
ハガキを用意しなくても、クレジットカードさえあれば印刷から投函までぜんぶやってくれるので便利。

1. ゆうびんIDでログイン

なければ作る。Webアプリ右上の「新規登録 / ログイン」からいける。

2. 全面写真レイアウトで作る

はがきを作るをクリックすると、レイアウトをテンプレートから選択する画面になる。
特段こだわりがないだとか、気に入ったデザインがあるのならここから選んでもよい。その場合、テキストメッセージ, スタンプ, 手書き文字, 写真アリの場合は画像の差し込みくらいなら可能。

今回はオリジナルのデザインにしたいので、上部バー内にある「写真あり」から「全面写真」を選ぶ。

f:id:S64:20191226115728p:plain

3. 用紙を選ぶ

フチ無しの場合は写真用紙、フチありの場合は写真用紙で作る。

4. 入稿データを作る

入稿データと言うけど、ただの画像ファイルでOK。jpg, png, gifに対応。1181x1748 (px) で作るとよい。
フチ有無問わず、四隅5mmが塗り足し(裁ち落とし)となることが利用ガイドで明記されているので注意。 なお、全面写真の場合はマージンなしで配置されるのので気にしなくて良いのだが、フチありの場合は後述するエディタでフチ分のマージンを入れた状態で配置されてしまう。px換算すると60px分になるようなので、その分を差し引いた形式にするとよいかもしれない。

5. エディタにアップロードする

写真を想定しているので、自動補正を掛けることもできる。掛けないこともできる。

6. メッセージ等追加要素を入れる

前述したメッセージやスタンプなどを追加できる。なお後述するとおり送る相手によってメッセージを追加で配置することも可能なので、相手により内容を変更したい場合はここでは何もしなくてよい。

7. 保存する

デザインを保存すれば後から追加注文などもできるので、一旦ここでは保存にしておく。

8. マイデザインから注文へ進む

右上メニューのマイデザインから保存済のデザインを呼び出し注文できる。

9. 配送相手を選ぶ

相手の住所がわかっていれば、ここで「直接相手に届ける」をクリックし必要事項を入力すればよい。プリントから投函まで自動で行われる。
今回はネットの友達宛なのだが、ここで2通りの方法がある。
どちらの場合も自分には相手の氏名や住所が見えることはなく、相手側の個人情報が割れることはない。

相手にTwitterのDMが送れる場合

「Twitterの友達に送る」をクリックし、自分のTwitterアカウントと連携する。宛名登録画面になるため、左側の「友達を選択する」から相手を選ぶ。
このあとの手順を済ませ注文を確定すると、自分のTwitterアカウントから相手へ直接DMが飛ぶ。ここにある専用URLから相手に受領ないし拒否をしてもらい、住所を入力してもらう。

注文確定から数分後にDMが届くようなので、おそらくキューかなんかに溜まっている。

f:id:S64:20191226122857p:plain

相手のメールアドレスがわかる場合

「メールアドレスで送る」をクリックし、「送り先を登録する」から住所録に追加していく。
必須項目は「氏名」「メールアドレス」だが、どちらも受領されるまでしか利用されない。具体的には、受領依頼メール内での文言とその送信先としてしか使われない。そのため相手に見られてもよい限りは氏名には何を入力しても問題ない。

このあと手順を済ませ注文を確定すると、receive_m@design-kit.jpのFROMで相手にメールが届く。ここにある専用URLから相手に受領ないし拒否をしてもらい、住所を入力してもらう。

f:id:S64:20191226122038p:plain

※住所もTwitterもメールアドレスもわからないけど個別連絡が取れる場合

LINEだとかFacebook Messengerで送るメニューはないためアンオフィシャルな使い方になるが、下記の手順で正常に受領してもらえることを確認した。

  1. 「メールアドレスで送る」へ進む
  2. 自分が受け取れる形式でメールアドレスを指定する
  3. 受け取ったメール(の専用URL)をコピーする
  4. 相手へ個別メッセージで送る
    • 発行されるURLが個人専用なので、不特定多数が踏めてはいけない

f:id:S64:20191226122748p:plain

10. 差出人を登録する、またはしない

名前, 郵便番号, 住所 を入力し、宛名面に印刷する差出人名を設定できる。
ただし、郵便は差出人を書かなくても届けることができ、左側チェックボックスの「宛名面に印刷しない」を設定すればこのステップをスキップできる。もし相手に実名や住所を教えたくない場合は印刷を無効にすればよい。

f:id:S64:20191226123318p:plain

11. 必要なら、個別メッセージなどを挿入する

左側で相手を選ぶと、個別のデザインプレビューが出る。ここで「デザインを編集する」をクリックすることで、個別にメッセージやスタンプなどを挿入できる。

f:id:S64:20191226123555p:plain

12. 注文内容を確認し、購入手続きをする

10枚以上送るなら、一度の注文でまとめて手続をすると割引が効く。
相手が受け取るか否かが確定しないため、ここではクレジットカードのみ利用可能。決裁をすると、一度オーソリとしてカードに全ての受領があった場合の請求が走る。もし相手が受取拒否ないし期限までに受領しなかった場合、その分が返金処理される。

以上で手続は完了。

手続の期限

注文が確定され相手にメッセージが届いてから3日以内に手続が行われなかった場合、その分はキャンセル扱いになり、前述のとおり枚数分の返金処理が走る。
また、相手にはこの3日間ずっと催促メッセージが飛ぶので注意。

f:id:S64:20191226124436p:plain

法務省のソフトが何度やっても「ICカードリーダの初期化に失敗しました。ICカードがICカードリーダに差し込まれているか確認してください。」となるので手順を書き起こす

合同会社の設立に伴って法務省の「申請用総合ソフト」を使うときにマイナンバーカードを使って署名を付けたりするんだけど、何度やっても正しいであろう手順を踏んでも

ICカードリーダの初期化に失敗しました。ICカードがICカードリーダに差し込まれているか確認してください。

というエラーで失敗してしまう。
めちゃくちゃ数十回と再試行しまくって、やっと下記手順でやれば再現性のある形で署名ができることを確認した。

  1. 申請用総合ソフトを起動しておく
  2. ICカードリーダを接続する
  3. 「ツール」 ->「オプション」 を開く
  4. ICカード切り替え タブに切り替える
  5. 「使用するICカードライブラリを登録します。」の「登録」ボタンをクリックする
  6. 「使用するICカードライブラリを切り替えます。」で「個人番号カード」を選ぶ
  7. 「適用」をクリックする
  8. 「設定」をクリックする(ダイアログを閉じる)
  9. 目的の「署名付与」へ進む
  10. 「ICカードで署名...」をクリックする
  11. 「ICカード差し込み確認」というダイアログが出るので、このタイミングでマイナンバーカードを差し込み、次へ進める
  12. パスワードを入力し、次へ進める
  13. これで署名成功!

マイナンバーカードを挿入するタイミングやICカードリーダを接続しておくタイミングがけっこうシビアで、これをミスるとすぐエラーになる模様。

Android WebViewのUserAgentいくつか

端末 / 環境 API Level バージョン Implementation User Agent
Genymotion 16 4.1.1 n/a Mozilla/5.0 (Linux; U; Android 4.1.1; en-us; Custom Phone Build/JRO03S) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Emulator 16 4.1.2 n/a Mozilla/5.0 (Linux; U; Android 4.2.2; en-us; Android SDK built for x86 Build/JB_MR1.1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Emulator 17 4.2.2 n/a Mozilla/5.0 (Linux; U; Android 4.2.2; en-us; Android SDK built for x86 Build/JB_MR1.1) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Emulator 18 4.3.1 n/a Mozilla/5.0 (Linux; U; Android 4.3.1; en-us; Android SDK built for x86 Build/JB_MR2) AppleWebKit/534.30 (KHTML, like Gecko) Version/4.0 Mobile Safari/534.30
Emulator 19 4.4.2 n/a Mozilla/5.0 (Linux; Android 4.4.2; Android SDK built for x86 Build/KK) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/30.0.0.0 Mobile Safari/537.36
Genymotion 19 4.4.4 n/a Mozilla/5.0 (Linux; Android 4.4.4; Custom Phone Build/KTU84P) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/33.0.0.0 Mobile Safari/537.36
Emulator 21 5.0.2 n/a Mozilla/5.0 (Linux; Android 5.0.2; Android SDK built for x86_64 Build/LSY66K) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/37.0.0.0 Mobile Safari/537.36
Emulator 24 7.0 Chrome WebView Mozilla/5.0 (Linux; Android 7.0; Android SDK built for x86_64 Build/NYC; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.90 Mobile Safari/537.36
Emulator 24 7.0 Google WebView Mozilla/5.0 (Linux; Android 7.0; Android SDK built for x86_64 Build/NYC; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/53.0.2785.124 Mobile Safari/537.36
Genymotion 24 7.0 AOSP WebView Mozilla/5.0 (Linux; Android 7.0; Custom Phone Build/NRD90M; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/51.0.2704.91 Mobile Safari/537.36
Emulator 28 9 Chrome WebView Mozilla/5.0 (Linux; Android 9; Android SDK built for x86_64 Build/PSR1.180720.075; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 Mobile Safari/537.36
Emulator 28 9 Android System WebView (Google) Mozilla/5.0 (Linux; Android 9; Android SDK built for x86_64 Build/PSR1.180720.075; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/69.0.3497.100 Mobile Safari/537.36
Genymotion 28 9 Android System WebView (AOSP) Mozilla/5.0 (Linux; Android 9; Custom Phone Build/PD1A.180720.031; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/66.0.3359.158 Mobile Safari/537.36

Android 4.4.x (API 19) にはiframe内anchorに挙動差異のあるバージョンが混在している

Android 4.4.2(とそれ以下)のWebView内でiframeに含まれるWebページ内のAnchorクリックをしても、ページの遷移イベントを取れない時がある。
具体的には、通常WebViewでは画面遷移時に WebViewClient#shouldOverrideUrlLoading というコールバックが叩かれるのだが、これが動かないパターンがある。

いくらか確認してみたところ、これはtarget属性によって挙動が変わっている模様。たとえば

<a href="https://example.com" target="_blank">_blank</a>

というリンクの場合、WebView内のさらにiframen内で遷移してしまう。

対し下記の場合、

<a href="https://example.com" target="_top">_top</a>

ちゃんと期待どおり WebViewClient#shouldOverrideUrlLoading が呼ばれる。

この挙動チェックはGitHubにサンプルアプリを置いた。

github.com


(Android 4.4.3環境が手元にないので)Android 4.4.4で同じ挙動を確認すると、どちらのリンクも期待どおりWebViewClient#shouldOverrideUrlLoadingが呼ばれる様になっている。

4.4.3はわからないが、少なくとも 4.4.2 と 4.4.4 の間には挙動の差異が存在する。


なお、4.4.xにおけるWebViewの挙動差異は他にも存在して、たとえばPromiseが4.4.2までは存在しないのに対し、4.4.3からは利用できたりする。

h.s64.jp

上記記事に記したとおり、内部のChromiumバージョン変更が行われており挙動にいくつかの差異が発生しているのが実態のようだ。

Android 4.4.x系 (API 19) にはPromiseが使えるバージョンと使えないバージョンが混在している

Android Studioに付属しているAndroid Virtual Device (Android Emulator) では、API 19相当の端末としてAndroid 4.4.2のエミュレータが起動する。
このエミュレータ上のWebViewでPromiseを実行すると、下記のようなエラーを確認できる。

Uncaught ReferenceError: Promise is not defined

一方Android 4.4.4を搭載した実機(や仮想マシン)では正常に実行できる。つまりPromiseが定義されている。


Android 4.4.xと呼ばれるものは複数存在している:

  • Android 4.4: API19
  • Android 4.4.1: API19
  • Android 4.4.2: API19
  • Android 4.4.3: API19
  • Android 4.4.4: API19
  • (Android 4.4W: API20)

Android 4.4ではWebView実装のChromium置き換えが含まれていて、この時導入されたのはChromium 30である。

The WebView shipped with Android 4.4 (KitKat) is based on the same code as Chrome for Android version 30. This WebView does not have full feature parity with Chrome for Android and is given the version number 30.0.0.0.

https://developer.chrome.com/multidevice/webview/overview#what_version_of_chrome_is_it_based_on_

そして4.4.3ではこれがChromium 33にアップデートされている。

The updated WebView shipped with Android 4.4.3 has the version number 33.0.0.0.

https://developer.chrome.com/multidevice/webview/overview#what_version_of_chrome_is_it_based_on_

上記はChangelogを探ると実際にAndroid 4.4.3のリリースに含まれている。

ChromiumにPromiseが実装されたのはChromium 32のときなので、Android 4.4.2までのバージョンでは利用できないことになる。

結論

  • Promiseが使えるのはAndroid 4.4.3から
  • Android 4.4.2までは使えない
  • どれもAPI 19扱いなので注意

h.s64.jp

2019年末年始もGoogle Play Storeのアプリ審査は休止しない

Google Play Storeにおける新規アプリのリリース / 既存アプリのアップデートにおける審査制度が今年から始まったけど、そういえば年末年始はどういう計画になってるんだろうと思い問い合わせをした。

質問と回答

回答がきたのでここにメモしておく。

年末および年始には審査日程に変更はございますでしょうか

年末年始もおやすみはなく、新規・既存アプリ問わず通常と変わらずに審査が実施されます。 通常も土日祝日を含めて審査は対応しております。そのため年末年始でも随時審査が終わればPlay Storeに公開・反映されます。

審査が実施される国(祝日の制定されている地域)およびタイムゾーンをご教示いただけますでしょうか

審査を担当するチームは複数の国におりますため、どちらの国のチームが対応するかは明言致しかねます。

ホリデーシーズン(たとえば12月23日〜27日)も年末年始と同様に、審査の実施に変更はないということで認識に相違ございませんでしょうか

はい。ご認識の通り、ホリデーシーズンもおやすみ等なく審査が進められますのでご安心くださいませ。

まとめ

  • Google Play Storeの審査は年末年始も含め無休
  • タイムゾーンの明言はないため、審査が実施される時間帯の保証もない
  • たぶん大晦日に出しても数日以内にストアに出る