Edited at

ABC2013Spring: HTML5におけるAndroid端末間互換性

More than 5 years have passed since last update.

ABC2013Sprint の講演HTML5におけるAndroid端末間互換性のまとめです.

走り書きなので, 誤字脱字はあるかもしれないが, 指摘があり次第随時修正します.


Canvas vs CSS3


CSS3


  • わずかな記法でリッチな表現が可能

  • DOMの操作をベースとした記述が主体.

  • デザイナー向け.

  • Canvasに比べ, 仕様が極めて複雑かつ曖昧, iPhone/Android間に互換性が少ない.

  • 同じOS同士のレガシーブラウザでも端末間で挙動が大きく違う.


Canvas


  • わずかな表現に相当の記述が必要.

  • ピクセル単位の操作が主体.

  • プログラマー向け.

  • 構文の解釈の違いによる互換性の問題は少ない. アンチエイリアシングの有無程度.

  • 問題になるのは, レガシーブラウザ自体のバグ/端末特有のバグ/チップセット特有のバグ(GPU, コア, etc. Intelチップ端末)


よくあるトラブル集


getImageData/putImageData


  • Canvasのピクセル情報を直接操作するAPI

  • 透明ピクセル(半透明ピクセル)があった場合に破綻する. getImageDetaで取得するデータは正しいが, putImageDataでα値をセットすると描画が破綻する.

  • セットする場合には, 乗算済みαを設定する必要がある.


Canvas#clip


  • 一部の領域だけをマスクして, その部分に描画するAPI.

  • クリッピング指定しているが, クリッピングされない. たまにクリッピングされることもある. ブラウザのバグ.

  • 描画の前後にCanvas#save()/canvas#restore()を無意味に指定すると解決する.


描画する際になぜか画面がclearRectされる.


  • Android3.0系列の某端末で発生

  • setTimeoutを利用して描画しようとすると, なぜか今までCanvasに買い得てあった秒がを全部消してしまう.

  • 描画前にCanvas#getPixelDataを無駄に呼ぶ.

  • ctx.getPixelData(0, 0, 1, 1)


画像のonloadが呼ばれない


  • Android2.2系列の某端末で発生

  • onloadする直前にsetTimeoutを無駄に呼ぶ

  • setTimeout(function(){}, 0);

  • デバッガを起動すると正しく動くのでデバッグできない.


Canvas#drawImage 画像を描画しようとすると空白になる


  • Androidの様々な端末で発生

  • たまに発生する. 負荷が高まったときなど.

  • メモリ不足が原因のはずが多いのでメモリ管理をしっかりする.

  • adb shell 'dumpsys meminfo _package-name_'


本体温度があがると描画が乱れる


  • Android4.x系の某端末で発生

  • 本体温度があがるとまれに描画が破綻する. 描画されるべき命令がスキップされ, されるべき描画がまれにされなくなる.

  • CPUに負荷がかかりすぎないように負荷を調整.


問題に対する解決方法


発見方法


  • たいていの問題は実際の端末で動かすまでは分からない. 人海戦術, サポートからの問い合わせで対応.

  • 発生した問題に対して, 似たような端末での動作を疑う. メーカー/シリーズ, Androidバージョン, メモリ搭載量, CPU(シングルコアか否か), GPU.


解決方法


  • 一般的な方法(デバッガーで1行ずつ追って見る, 頭の中での想像など)はAndroidのバグの解決方法には適していない.

  • 問題が発生する最小サンプルを作成したあと, 回避するコードをひたすら試す.

  • 基本的な動作を疑う.


  • ctx.clip(), ctx.transform() あたりをコメントアウトして確認する.


  • ctx.save(), ctx.restore() で全体を括ってみる.


  • ctx.drawImage() の再現に失敗する場合はメモリを消費させる.


回避コード

回避コードは, 全てのANdroidで動作するものが望ましい.


  • UserAgentを確認して分岐させる方法は最低のアイディア. 将来のブラウザにも対応するのが望ましい.

  • ほとんどコストを発生させずに解決するのが望ましい.

  • 回避コードには, 詳しくコメントを書く.


可能であれば

ブラウザのソースコードを一度読んでみるとよい.


  • 端末ごとの問題はソースコードが公開されていないので, ソースコードから問題の特定は不可能.

  • display object.

  • WebKit系でなくても, Mozillaでもかまわない. 特にレンダリング周りのコードがよい.

エンジニアが互換性に文句を言うのは大切だが, ユーザに快適にサービスを使ってもらう方がより大切