マルチタップのエラーについて教えてください。

2,874 views
Skip to first unread message

sekuta

unread,
Mar 8, 2012, 8:05:23 PM3/8/12
to android-...@googlegroups.com
お世話になっております。sekutaと申します。

現在、マルチタップを検出して画像の拡大縮小のアプリを作成しているのですが、稀に発生する例外について悩んでいます。
例外発生時のログは下記になります。

03-09 09:37:45.190: E/AndroidRuntime(1378): FATAL EXCEPTION: main
03-09 09:37:45.190: E/AndroidRuntime(1378): java.lang.IllegalArgumentException: pointerIndex out of range
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.MotionEvent.nativeGetPointerId(Native Method)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.MotionEvent.getPointerId(MotionEvent.java:1927)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ScaleGestureDetector.onTouchEvent(ScaleGestureDetector.java:224)
03-09 09:37:45.190: E/AndroidRuntime(1378): at MainActivity.onTouch(MainActivity.java:869)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.View.dispatchTouchEvent(View.java:5481)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1953)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1714)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTransformedTouchEvent(ViewGroup.java:1959)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewGroup.dispatchTouchEvent(ViewGroup.java:1728)
03-09 09:37:45.190: E/AndroidRuntime(1378): at com.android.internal.policy.impl.PhoneWindow$DecorView.superDispatchTouchEvent(PhoneWindow.java:1892)
03-09 09:37:45.190: E/AndroidRuntime(1378): at com.android.internal.policy.impl.PhoneWindow.superDispatchTouchEvent(PhoneWindow.java:1371)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.app.Activity.dispatchTouchEvent(Activity.java:2364)
03-09 09:37:45.190: E/AndroidRuntime(1378): at com.android.internal.policy.impl.PhoneWindow$DecorView.dispatchTouchEvent(PhoneWindow.java:1840)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.View.dispatchPointerEvent(View.java:5662)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewRootImpl.deliverPointerEvent(ViewRootImpl.java:2863)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.view.ViewRootImpl.handleMessage(ViewRootImpl.java:2442)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.os.Handler.dispatchMessage(Handler.java:99)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.os.Looper.loop(Looper.java:137)
03-09 09:37:45.190: E/AndroidRuntime(1378): at android.app.ActivityThread.main(ActivityThread.java:4340)
03-09 09:37:45.190: E/AndroidRuntime(1378): at java.lang.reflect.Method.invokeNative(Native Method)
03-09 09:37:45.190: E/AndroidRuntime(1378): at java.lang.reflect.Method.invoke(Method.java:511)
03-09 09:37:45.190: E/AndroidRuntime(1378): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
03-09 09:37:45.190: E/AndroidRuntime(1378): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
03-09 09:37:45.190: E/AndroidRuntime(1378): at dalvik.system.NativeStart.main(Native Method)

とLogCatには表示され、MainActivityの869行目というのは、onTouchの中のこの部分になります。

866 if(event.getPointerCount() >= 2)
867 {
868 //マルチタップ時の処理
869 gesDetect.onTouchEvent(event);
870 }

拡大縮小を繰り返していると、なにかのタイミングで発生する例外で、そのタイミングもわからず困っています。
なにか似たような経験をされた方いらっしゃいましたら、なんでも良いのでご教授ください。
よろしくお願い致します。


Keiji Ariyama

unread,
Mar 9, 2012, 10:54:13 PM3/9/12
to android-...@googlegroups.com
有山です。

 結論から言えば、ScaleGestureDetectorの不具合だと考えます。

http://tools.oesf.biz/android-4.0.3_r1.0/xref/frameworks/base/core/java/android/view/ScaleGestureDetector.java

 エラーは224行目 "event.getPointerId(index0);" で発生しています。
 この引数のindex0が 0未満である、またはevent.getPointerCount();の値より
大きいと、"pointerIndex out of range"が発生するのです。

 index0の値に値を代入しているのは直前のfindNewActiveIndexメソッドです。
このメソッドは-1を返す可能性があるとコメントに記載されています。
 従って、その直後で index0の値が0以上であるか、チェックする必要がある
はずです。
 事実、他のfindNewActiveIndexの直後ではその値チェックをしていますが、
224行目と後一箇所、チェックをしていない箇所がありました。
 この2箇所については、今回のようなエラーが発生する可能性があります。

 もともとこの経路は、異常なマルチタッチイベントの為に作られているので
("Probably someone sending us a broken event stream.")、顕在化しにくかっ
たのだと思います。

 問題に対応するため、まずはAOSPにパッチを提出しておきました。

https://android-review.googlesource.com/#/c/33990/

 ただ、コード自体が正しいかは確信が持てないのでレビュー待ちです。皆さん
ご意見ください。


(2012年03月09日 10:05), sekuta wrote:
> お世話になっております。sekutaと申します。
>
> 現在、マルチタップを検出して画像の拡大縮小のアプリを作成しているのです

> --
> このメールは Google グループのグループ「Android-SDK-Japan」の登録者に送
> られています。
> このディスカッションをウェブ上で閲覧するには、https://groups.google.com
> /d/msg/android-sdk-japan/-/Nd3f1bfIwIcJ にアクセスしてください。
> このグループに投稿するには、android-...@googlegroups.com にメール
> を送信してください。
> このグループから退会するには、android-sdk-
> japan+un...@googlegroups.com にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-sdk-japan?hl=ja
> からこのグループにアクセスしてください。

--
Keiji,
ml_an...@c-lis.co.jp

sekuta

unread,
Mar 11, 2012, 9:34:14 PM3/11/12
to android-...@googlegroups.com
有山さん、返信ありがとうございます!
丁寧に解説していただき、とてもわかりやすく勉強になりました!

AOSPに提出されたパッチも拝見しました。
まずはパッチを使用して、検証しようと考えています。

2012年3月10日土曜日12時54分13秒 UTC+9 C-LIS Keiji Ariyama:

> このグループに投稿するには、android-sdk-ja...@googlegroups.com にメール
> を送信してください。
> このグループから退会するには、android-sdk-
> japan+unsubscribe@googlegroups.com にメールを送信してください。
> 詳細については、http://groups.google.com/group/android-sdk-japan?hl=ja
> からこのグループにアクセスしてください。

--
Keiji,
ml_an...@c-lis.co.jp

Message has been deleted

sekuta

unread,
Mar 27, 2012, 2:10:45 AM3/27/12
to android-...@googlegroups.com
sekutaです。
マルチタップを別の方法で検出できないかと、模索していたところ、MotionEventでも同様の?エラーが発生したので報告します。
MotionEventだと、ポインターIDを指定することで指ごとの座標を取得できるみたいなので、それを応用しようと考えたのですが、pointerIndex out of range が発生しました。

発生した場所は、

private float getLength(MotionEvent e) {
float xx = e.getX(1) - e.getX(0);
float yy = e.getY(1) - e.getY(0);
return FloatMath.sqrt(xx * xx + yy * yy);
}

ここでした。getX(pointerId)などで指ごとの座標をとるみたいですが、
コードの流れを追うと、結局有山さんがおっしゃっていた「event.getPointerCount();」が呼ばれているみたいなのでここで-1が入ってきているのだと思います。
こちらを使用すると、ScaleGestureDetectorの時以上に落ちやすいような気がします。
マルチタップの検出は、パッチが適用されるのを待つしかないのでしょうか?

ほかの方法で実現できている方いましたら、なんでもよいのでご教授ください。
よろしくお願い致します。


2012年3月12日月曜日10時34分14秒 UTC+9 sekuta:
Reply all
Reply to author
Forward
0 new messages