Galaxy S4のWebviewで、非同期処理の中でのCanvasの描画がバグってる

追記(2014-01-10): 解決方法書きました!http://d.hatena.ne.jp/koba04/20140110/1389344763


ネイティブの中で使うWebViewの話で、標準ブラウザとChromeでは発生しない現象です


Android 4.2なGalaxy S4のWebViewの中でCanvasの表示が豪快に壊れている現象に遭遇したのでメモ。
アップデートしたGalaxyNexusでは発生しなくて、他に4.2が最初からインストールされた端末がなかったので、4.2の問題なのかGalaxy S4固有の問題なのかは不明です。

状態

  • fillRectやdrawImageをした時に、0,0の位置にある1ピクセルCanvas全体が描画されるような状態になる。

発生する条件

非同期処理のコールバックの中
  • img.onloadの中
    • 画像がキャッシュされていたりして即実行されるときは発生しないことがありました。
img.onload = function() {
  ctx.drawImage(img, 0, 0, 100, 100);
};
  • setTimeout, setInterval
    • 30ms以下を指定すると非同期に処理されない?のか発生しないこともあります。10msくらいにすると確実に発生しなくて、50msくらいにすると絶対発生する
setTimeout(function() {
  ctx.drawImage(img, 0, 0, 100, 100);
}, 20)
// 実際はライブラリ使ってるのでこの書き方では試していませんが..
xhr.onreadystatechange = function() {
  if (xhr.readyState == 4) {
    if (xhr.status == 200) {
      ctx.drawImage(img, 0, 0, 100, 100);
    }
  }
}

試したこと

対策

  • 見つかりませんでした。。というわけでcanvasを諦め、DOMで書くことに...
    • Java側でWebView作る時の設定などで解決出来るかと思ったりもしたけど、それもよくわからず...。

同じ現象に遭遇した人のためにわかってることをまとめてみました