I tried writing code for multitouch but used images instead. Unfortunately, it won't start. The code is correct: it has no errors. However, the log cat produces too many errors. Here are those errors. Thank you!
07-30 11:12:15.930: E/AndroidRuntime(642): FATAL EXCEPTION: main
07-30 11:12:15.930: E/AndroidRuntime(642): java.lang.RuntimeException: Unable to start activity ComponentInfo{sample.app.touchsample/sample.app.touchsample.TouchsampleActivity}: android.util.AndroidRuntimeException: requestFeature() must be called before adding content
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.ActivityThread.access$600(ActivityThread.java:130)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.os.Handler.dispatchMessage(Handler.java:99)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.os.Looper.loop(Looper.java:137)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.ActivityThread.main(ActivityThread.java:4745)
07-30 11:12:15.930: E/AndroidRuntime(642): at java.lang.reflect.Method.invokeNative(Native Method)
07-30 11:12:15.930: E/AndroidRuntime(642): at java.lang.reflect.Method.invoke(Method.java:511)
07-30 11:12:15.930: E/AndroidRuntime(642): at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
07-30 11:12:15.930: E/AndroidRuntime(642): at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
07-30 11:12:15.930: E/AndroidRuntime(642): at dalvik.system.NativeStart.main(Native Method)
07-30 11:12:15.930: E/AndroidRuntime(642): Caused by: android.util.AndroidRuntimeException: requestFeature() must be called before adding content
07-30 11:12:15.930: E/AndroidRuntime(642): at com.android.internal.policy.impl.PhoneWindow.requestFeature(PhoneWindow.java:215)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.Activity.requestWindowFeature(Activity.java:3225)
07-30 11:12:15.930: E/AndroidRuntime(642): at sample.app.touchsample.TouchsampleActivity.onCreate(TouchsampleActivity.java:190)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.Activity.performCreate(Activity.java:5008)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
07-30 11:12:15.930: E/AndroidRuntime(642): at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
07-30 11:12:15.930: E/AndroidRuntime(642): ... 11 more
package sample.app.touchsample;
import java.util.ArrayList;
import java.util.HashMap;
import android.app.Activity;
import android.content.Context;
import android.graphics.Path;
import android.media.AudioManager;
import android.media.MediaPlayer;
import android.media.SoundPool;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MotionEvent;
import android.view.View;
import android.view.ViewConfiguration;
import android.view.ViewGroup;
import android.view.Window;
import android.view.WindowManager;
import android.view.View.OnTouchListener;
//import android.widget.FrameLayout;
import android.widget.ImageView;
//import sample.app.touchsample.TouchsampleActivity.secondDrum.thirdDrum;
import android.widget.LinearLayout;
public class TouchsampleActivity extends Activity implements OnTouchListener
{
MediaPlayer mp;
SoundPool fx;
HashMap <Integer, Integer> fxMap;
int sfxId=1;
int sfxId2=2;
int sfxId3=3;
int sfxId4=4;
private Path path = new Path();
private View parent;
private final ArrayList[] recentTouchedViewsIndex = new ArrayList[10];
private final ArrayList[] downTouchedViewsIndex = new ArrayList[10];
private final ArrayList<View> moveOutsideEnabledViews = new ArrayList<View>();
private final ArrayList<View> multiTouchViews = new ArrayList<View>();
private int mTouchSlop = 24;
private static final String TAG = "Touch";
//private ImageView imageView1, imageView2 ;
public void addMoveOutsideEnabledViews(final View view) {
moveOutsideEnabledViews.add(view);
}
private void dealEvent(final int actionPointerIndex,
final MotionEvent event, final View eventView,
final int actionResolved) {
int rawX, rawY;
final int location[] = { 0, 0 };
eventView.getLocationOnScreen(location);
// Log.v("tag", location + "");
rawX = (int) event.getX(actionPointerIndex) + location[0];
rawY = (int) event.getY(actionPointerIndex) + location[1];
final int actionPointerID = event.getPointerId(actionPointerIndex);
ArrayList<View> hoverViews = getTouchedViews(rawX, rawY);
if (actionResolved == MotionEvent.ACTION_DOWN) {
downTouchedViewsIndex[actionPointerID] = (ArrayList<View>) hoverViews
.clone();
}
// deletes all views which where not clicked on ActionDown
if (downTouchedViewsIndex[actionPointerID] != null) {
final ArrayList<View> tempViews = (ArrayList<View>) hoverViews
.clone();
tempViews.removeAll(downTouchedViewsIndex[actionPointerID]);
hoverViews.removeAll(tempViews);
}
if (recentTouchedViewsIndex[actionPointerID] != null) {
final ArrayList<View> recentTouchedViews = recentTouchedViewsIndex[actionPointerID];
final ArrayList<View> shouldTouchViews = (ArrayList<View>) hoverViews
.clone();
if (!shouldTouchViews.containsAll(recentTouchedViews)) {
shouldTouchViews.removeAll(recentTouchedViews);
shouldTouchViews.addAll(recentTouchedViews);
final ArrayList<View> outsideTouchedViews = (ArrayList<View>) shouldTouchViews
.clone();
outsideTouchedViews.removeAll(hoverViews);
}
recentTouchedViewsIndex[actionPointerID] = hoverViews;
hoverViews = shouldTouchViews;
} else {
recentTouchedViewsIndex[actionPointerID] = hoverViews;
}
if (actionResolved == MotionEvent.ACTION_UP) {
recentTouchedViewsIndex[actionPointerID] = null;
downTouchedViewsIndex[actionPointerID] = null;
}
dumpEvent(event);
for (final View view : hoverViews) {
int x, y;
view.getLocationOnScreen(location);
x = rawX - location[0];
y = rawY - location[1];
// View does not recognize that the Pointer is
// outside if the Pointer is not far away (>mTouchSlop)
if (recentTouchedViewsIndex[actionPointerID] != null) {
if (pointInView(x, y, mTouchSlop, view.getWidth(),
view.getHeight())) {
// Log.v("tag", "added because < mTouchSlop");
if (!recentTouchedViewsIndex[actionPointerID]
.contains(view)) {
recentTouchedViewsIndex[actionPointerID].add(view);
}
} else if (moveOutsideEnabledViews.contains(view)) {
Log.v("tag", "outside but gets event");
recentTouchedViewsIndex[actionPointerID].add(view);
}
}
final MotionEvent me = MotionEvent.obtain(event.getDownTime(),
event.getEventTime(), actionResolved, x, y,
event.getPressure(actionPointerIndex),
event.getPressure(actionPointerIndex),
event.getMetaState(), event.getXPrecision(),
event.getYPrecision(), event.getDeviceId(),
event.getEdgeFlags());
me.setLocation(x, y);
if (!me.equals(event)) {
// deals the Event
view.onTouchEvent(me);
}
// debug
if (actionResolved == MotionEvent.ACTION_MOVE) {
Log.v("tag",
"#" + actionPointerIndex + " Rawx:" + rawX + " rawy:"
+ rawY + " x:" + x + " y:" + y + " "
+ view.toString());
}
}
}
// @Override
// public boolean onCreateOptionsMenu(Menu menu)
// {
// getMenuInflater().inflate(R.menu.touchsample, menu);
// return true;
// }
public class secondDrum implements OnTouchListener
{
public boolean onTouch(View v, MotionEvent event)
{
dumpEvent(event);
AudioManager bongos2 = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
float curVolume2 = bongos2.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume2 = bongos2.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float leftvolume2 = curVolume2/maxVolume2;
float rightVolume2 = curVolume2/maxVolume2;
int priority2 = 1;
int no_loop2 = 0;
float normal_playback_rate2=1.0f;
fx.play(sfxId2, leftvolume2, rightVolume2, priority2, no_loop2, normal_playback_rate2);
return false;
}
}
public class thirdDrum implements OnTouchListener
{
public boolean onTouch(View v, MotionEvent event)
{
dumpEvent(event);
AudioManager bongos3 = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
float curVolume = bongos3.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume = bongos3.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float leftVolume = curVolume/maxVolume;
float rightVolume = curVolume/maxVolume;
int priority = 1;
int no_loop = 0;
float normal_playback_rate = 2.0f;
fx.play(sfxId3, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
return false;
}
}
public class forthDrum implements OnTouchListener
{
public boolean onTouch(View v, MotionEvent event)
{
dumpEvent(event);
AudioManager bongos4 = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
float curVolume = bongos4.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume = bongos4.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float leftVolume = curVolume/maxVolume;
float rightVolume = curVolume/maxVolume;
int priority = 1;
int no_loop = 0;
float normal_playback_rate = 2.0f;
fx.play(sfxId4, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
return false;
}
}
public boolean onTouch(View view, MotionEvent event)
{
dumpEvent(event);
AudioManager bongos = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
float curVolume = bongos.getStreamVolume(AudioManager.STREAM_MUSIC);
float maxVolume = bongos.getStreamMaxVolume(AudioManager.STREAM_MUSIC);
float leftVolume = curVolume/maxVolume;
float rightVolume = curVolume/maxVolume;
int priority = 1;
int no_loop = 0;
float normal_playback_rate = 1.0f;
fx.play(sfxId, leftVolume, rightVolume, priority, no_loop, normal_playback_rate);
//return false;
// index of the pointer which starts this Event
final int actionPointerIndex = event.getActionIndex();
// resolve the action as a basic type (up, down or move)
int actionResolved = event.getAction() & MotionEvent.ACTION_MASK;
if (actionResolved < 7 && actionResolved > 4) {
actionResolved = actionResolved - 5;
}
if (actionResolved == MotionEvent.ACTION_MOVE) {
for (int ptrIndex = 0; ptrIndex < event.getPointerCount(); ptrIndex++) {
// only one event for all move events.
dealEvent(ptrIndex, event, view, actionResolved);
Log.v("tag", "move" + ptrIndex);
}
} else {
dealEvent(actionPointerIndex, event, view, actionResolved);
}
return true;
}
private void dumpEvent(MotionEvent event)
{
final String names[] = { "DOWN", "UP", "MOVE", "CANCEL", "OUTSIDE", "POINTER_DOWN", "POINTER_UP", "7?", "8?", "9?" };
final StringBuilder sb = new StringBuilder();
final int action = event.getAction();
final int actionCode = action & MotionEvent.ACTION_MASK;
sb.append("event ACTION_").append(names[actionCode]);
if(actionCode == MotionEvent.ACTION_POINTER_DOWN || actionCode == MotionEvent.ACTION_POINTER_UP)
{
sb.append("(pid " ).append(action >> MotionEvent.ACTION_POINTER_ID_SHIFT);
sb.append(")" );
}
sb.append("[");
for (int i = 0; i <event.getPointerCount(); i++)
{
sb.append("#").append(i);
sb.append("(pid ").append(event.getPointerId(i));
sb.append(")=").append((int) event.getX(i));
sb.append(",").append((int) event.getY(i));
if(i + 1 < event.getPointerCount())
sb.append(";");
}
sb.append("]");
Log.d(TAG, sb.toString());
}
private ArrayList<View> getChildViews(final View view) {
final ArrayList<View> views = new ArrayList<View>();
if (view instanceof ViewGroup) {
final ViewGroup v = ((ViewGroup) view);
if (v.getChildCount() > 0) {
for (int i = 0; i < v.getChildCount(); i++) {
views.add(v.getChildAt(i));
}
}
}
return views;
}
private ArrayList<View> getTouchedViews(final int x, final int y) {
View lastTouchedView = null;
//final ArrayList<View> touchedViews = new ArrayList<View>();
final ArrayList<View> possibleViews = new ArrayList<View>();
if (parent instanceof ViewGroup) {
possibleViews.add(parent);
for (int i = 0; i < possibleViews.size(); i++) {
final View view = possibleViews.get(i);
final int location[] = { 0, 0 };
view.getLocationOnScreen(location);
if (((view.getHeight() + location[1] >= y)
& (view.getWidth() + location[0] >= x)
& (view.getLeft() <= x) & (view.getTop() <= y))
|| view instanceof LinearLayout) {
if (this.multiTouchViews.contains(view)){
lastTouchedView = view;
}
possibleViews.addAll(getChildViews(view));
}
}
ArrayList<View> touchedViews = new ArrayList<View>();
if (lastTouchedView != null){
touchedViews.add(lastTouchedView);
}
return touchedViews;
}
return possibleViews;
}
//@Override
//public void onCreate(final Bundle instance) {
// super.onCreate(instance);
//public boolean onTouch(final View v, final MotionEvent event) {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.touchsample);
fx=new SoundPool(1100, AudioManager.STREAM_MUSIC, 1100);
fxMap=new HashMap<Integer, Integer>();
fxMap.put(sfxId, fx.load(this, R.raw.bongo_left, 1));
fxMap.put(sfxId2, fx.load(this, R.raw.bongo_right, 1));
fxMap.put(sfxId3, fx.load(this, R.raw.bongo_left, 1));
fxMap.put(sfxId4, fx.load(this, R.raw.bongo_right, 1));
ImageView view = (ImageView) findViewById(R.id.imageView1);
view.setOnTouchListener(this);
ImageView view2 = (ImageView) findViewById(R.id.imageView2);
view2.setOnTouchListener(new secondDrum());
ImageView view3 = (ImageView) findViewById(R.id.imageView3);
view3.setOnTouchListener(new thirdDrum());
ImageView view4 = (ImageView) findViewById(R.id.imageView4);
view4.setOnTouchListener(new forthDrum());
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().addFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN);
getWindow().clearFlags(
WindowManager.LayoutParams.FLAG_FORCE_NOT_FULLSCREEN);
parent = findViewById(android.R.id.content).getRootView();
parent.setOnTouchListener(this);
mTouchSlop = ViewConfiguration.get(getApplicationContext())
.getScaledTouchSlop();
}
private boolean pointInView(final float localX, final float localY,
final float slop, final float width, final float height) {
return localX >= -slop && localY >= -slop && localX < ((width) + slop)
&& localY < ((height) + slop);
}
}