ボート釣りナビ コンパス表示、画面文字が表示されない不具合の原因 | kagoturiのブログ

kagoturiのブログ

自作androidアプリの使い方や更新情報を掲載していきます。

Regza Phoneでコンパスが回転しない、ドコモF-12C画面表示文字やコンパスが表示されないという不具合に対して、実機のRegza Phoneを入手したらすぐに原因の特定ができました。

androidで各種センサーの処理をする場合には、

getSystemServiceでセンサ・マネージャのインスタンスを取得、

registerListenerでセンサ・マネージャのインスタンスにイベントリスナーを登録

SensorEventListenerのonSensorChangedでイベントを受け取る

という流れになります。

onSensorChangedではSensorEventが引数として渡されて、センサーからのデータを取得するのですが、SensorEventにはセンサーからの取得情報の信頼度を格納したaccuracyというメンバがあります。

http://developer.android.com/intl/ja/reference/android/hardware/SensorEvent.html#accuracy

accuracyの値は、以下のいずれかを返すようになっているみたいです。

SENSOR_STATUS_UNRELIABLE 0
SENSOR_STATUS_ACCURACY_LOW 1
SENSOR_STATUS_ACCURACY_MEDIUM 2
SENSOR_STATUS_ACCURACY_HIGH 3


そして不具合の原因はonSensorChangedの最初で
if (event.accuracy == SensorManager.SENSOR_STATUS_UNRELIABLE) return;
としていた部分

SENSOR_STATUS_UNRELIABLEの時は、信頼性が低い値なので処理しないようにする為の処理でWeb上に公開されているソースにも結構書かれています。
しかし、入手したRegza Phoneをデバッグモードで動かしたら、常にaccuracyがSENSOR_STATUS_UNRELIABLEになっています。

これが原因でセンサーの値を取得して表示する前にreturnしていたことが原因だったようです。
コンパスとステータスの文字はセンサーの値が一回も取れないと画面に描画しないようにしていたので、画面表示が出ないということでした。

但し、それだと表示は出るのにコンパスが動かないという不具合の理由が分かりません。

そこで、androidの設定でコンパスのキャリブレーションを行ってみたら、10回に一回ぐらいはaccuracyがSENSOR_STATUS_ACCURACY_HIGHになるイベントが入るようになりました。
しかし、SENSOR_STATUS_ACCURACY_HIGHの時は常に角度0はになっています。
逆にSENSOR_STATUS_UNRELIABLEの時の値がまともな値のようです。
表示は出るのにコンパスが回転しないというのはこれが原因だということが特定出来ました。

原因は分かったものの、accuracyの値を使わないと、他の端末の動作に影響する可能性もありそうなので気になります。
android developersのリファレンスでもSENSOR_STATUS_UNRELIABLEの状態では値が信用出来ないので、キャリブレーションが必要か読み取りを許可しないと書いてあります。
"The values returned by this sensor cannot be trusted, calibration is needed or the environment doesn't allow readings"



駄猫の備忘録: 久々にセンサーを使ってみた
http://3a3k.blogspot.com/2011/07/blog-post.html


Androidで地磁気センサーの値が取れない問題
http://blog.loadlimits.info/2011/10/android%E3%81%A7%E5%9C%B0%E7%A3%81%E6%B0%97%E3%82%BB%E3%83%B3%E3%82%B5%E3%83%BC%E3%81%AE%E5%80%A4%E3%81%8C%E5%8F%96%E3%82%8C%E3%81%AA%E3%81%84%E5%95%8F%E9%A1%8C/


どうやら端末によって色々のようです。
自分の持っている端末で念の為確認してみると

Softbank 003SH android 2.3 SENSOR_STATUS_ACCURACY_HIGHを返す。

au IS01 android1.6 -1を返す。
-1って定義無いんですが、SENSOR_STATUS_UNRELIABLEではないので偶然?にも動作していた模様。

でした。

わざわざSensorEventのメンバとして定義されて、onSensorChangedで返す値なので、普通に考えたら値を読む前にaccuracyをチェックした方が良いと思うのですが、かなりの機種でまともな値を返していないようなので、accuracyの値は無視することにしました。

今回は、二種類の自分が持っていた端末では発生しないことから、原因特定に時間がかかってしまいました。
Regza Phoneを入手してデバッグモードで動かしたら数分で原因が特定できたので、やはり実機確認は早いですね。

andoroidの機種依存は結構話題になっていますが、個人開発レベルで複数機種を確認するのはかなり負担がかかります。
今回のaccuracyの値が機種によっておかしい問題は、各端末メーカーがこの値をあまり気にして作っていないからなのか分かりませんが、わざわざAPIで用意されている値が、機種によって違う値が入ってきたり、信用できない値になっているというのは厳しいです。
こちらのコーディングの方法や設定が悪いのかもしれませんが、英語も含めてWeb上の情報を見ると結構困っている人は居るようです。

androidはiphoneに比べてアプリの質でもいろいろと信用が落ちているので、もうちょっと機種による違いの情報が入手しやすくしてもらえると助かりますね。