2012年4月14日土曜日

ssFlickerのデータ異常の対応

しばらく前にssFlickerのデータ異常に関する不具合を指摘された。
v0.8.3で一度対応はしたものの、それだと対応が不十分だった事に気付き、引き続き色々と修正した。
ちょっと今回はいつもと書き方を変えてみる。



DBの構成                                    

そもそも作りが悪い所がいくつかあった。
その1つがDB。
ssFlickerでは編集モードで設定した内容はDBに設定していて、pointer_tableとapp_tableの2つのテーブルを用意している。
ポインタには一意のpointerIdが付与され、アプリにはポインタ内で一意となるappIdが付与される。
なので、pointer_tableのpointerIdはPrimaryKeyとなっていたが、app_tableにはPrimaryKeyを設定していなかった。
本当はpointerIdとappIdの複合PrimaryKeyとしたかったんだけど、Androidでは複合PrimaryKeyが使えないと思っていた。
さらに言えば、app_tableのpointerIdは外部キーを設定するべきだった。


編集画面でのID設定                               

もう1つの悪い所が編集画面の作り。
編集画面では変数としてpointerIdとappIdを設定している。
これはクラス変数になっているため、画面内に1つずつしか設定できない。
で、この変数は編集画面のポインタやアプリ(設定済み/未設定に関わらず)に触れたタイミングで設定される。
アプリの追加→ウィジェットを選択すると、一覧が表示されるまでの間に他のアプリに触れる事ができてしまう。
するとそのタイミングでappIdが書き換えられてしまい、そのままウィジェットを設定すると目的外の場所にウィジェットが追加される事になる。
その場所に元々アプリが登録されていた場合、1つのIDに複数のデータが登録されることになってしまう。


結局                                      

普通のアプリであれば重複してしまっても重複した分が見えないだけなのであまり不都合はないのだが、ウィジェットの場合、画面上に表示されてしまうのでポインタ内に見つからないと非表示にもできないし、削除もできなくなってしまう。
アプリを削除すれば重複した分は全て削除されるのだけど、結局どれが重複しているのかは見た目では分からない。


v0.8.3での対応                                  

v0.8.3ではDBの複合PrimaryKeyを設定した。
ただ、既に重複したデータがある可能性があるし、DBバージョンのアップグレードでキー制約の変更のやり方も分からなかったので、新規インストール時のみ複合PrimaryKeyを設定するようにした。


v0.9.1での対応                                  

追加の対応をするつもりはなかったんだけど、v0.8.3の対応をしても新規インストールをしないと根本的な対応にはならないし、繰り返し発生する可能性があったので重複データ削除の機能を追加した。
これを実行すると、IDが重複しているアプリを全て削除する。


だけど                                     

実は問題はこれだけではなかった。
他にも、pointer_tableに登録されていないpointerIdがapp_tableに登録されてしまう可能性があった。
また、ウィジェットの登録以外にも編集や削除でも、ダイアログが表示されるまでの一瞬の間にIDを書き換える事ができ、同様の事象が発生する可能性があった。
そのため、さらなる対応が必要となった。


v0.9.2での対応                                  

やり方は色々考えたんだけど、結局編集画面を操作してからダイアログを表示するまではポインタやアプリに触れられないようにしてIDの書き換えを防ぐこととした。
合わせてv0.9.1で追加した重複データ削除を異常データ削除とし、pointer_tableに登録されていないpointerIdがapp_tableに登録されている場合、削除するようにした。
外部キー制約も付けたかったのだけど、Androidではちょっと特殊なことをしないと外部キーが生きないようであり、あまり複雑な事はしなかったので止めた。
アプリ登録時にpointer_tableにpointerIdがあることをチェックするようにSQL側で対応した。

少し話が変わってしまうけど、ウィジェットはAndroidOS側でappWidgetIdという一意なIDを付与しているのだけど、同じIDをapp_tableの中にも保持している。
また、Androidの設定から各アプリのデータ削除を行うと、DBのクリアがされる。
ssFlickerのデータ削除を行うと、Android側にはappWidgetIdが残ったまま、ssFlikerから削除されてしまい、その後Androidから削除ができなくなってしまう。
そのため、DB作成時にssFlickerから登録したウィジェットを全て削除するようにした。
ただし、DB作成はアプリの初回起動時に行われるので、データ削除をしてからssFlickerを起動するまではAndroid側にもウィジェット情報が残ることになる。


v0.9.3での対応                                  

これは単なる不具合対応。
v0.9.2の修正時にデグレが発生していた。
具体的には、編集画面からポインタを開き、ドックを操作し、ssFlickerの設定画面を開いて閉じたときに異常終了してしまう事象が発生していた。
さくっと修正。

0 件のコメント:

コメントを投稿