canvas - Android SurfaceView onTouchEvent not getting called -


i'm developing game using surfaceview listens touch events. ontouchevent method in surfaceview works fine many of devices, in devices, doesn't called (moto x style one) , app stops responding.

i guess might due overloading of main thread due ontouchevent starving.

could android experts on here give me tips reduce load on main thread if it's getting overloaded, or there might other reason may cause this

the code quite complex still i'm posting if want go through it

gameloopthread

public class gameloopthread extends thread{     private gameview view;     // desired fps     private final static int    max_fps = 120;     // maximum number of frames skipped     private final static int    max_frame_skips = 5;     // frame period     private final static int    frame_period = 1000 / max_fps;      private boolean running = false;      public gameloopthread(gameview view){         this.view = view;     }      public void setrunning(boolean running){         this.running = running;     }      public boolean isrunning() {         return running;     }     @override     public void run() {         canvas canvas;         long begintime;     // time when cycle begun         long timediff;      // time took cycle execute         int sleeptime;      // ms sleep (<0 if we're behind)         int framesskipped;  // number of frames being skipped          while (running) {             canvas = null;             // try locking canvas exclusive pixel editing             // in surface             try {                 canvas = view.getholder().lockcanvas();                 synchronized (view.getholder()) {                     begintime = system.nanotime();                     framesskipped = 0;  // resetting frames skipped                     // update game state                     // render state screen                     // draws canvas on panel                     this.view.draw(canvas);                     // calculate how long did cycle take                     timediff = system.nanotime() - begintime;                     // calculate sleep time                     sleeptime = (int)(frame_period - timediff/1000000);                      if (sleeptime > 0) {                         // if sleeptime > 0 we're ok                         try {                             // send thread sleep short period                             // useful battery saving                             thread.sleep(sleeptime);                         } catch (interruptedexception e) {}                     }                      while (sleeptime < 0 && framesskipped < max_frame_skips) {                         // update without rendering                         // add frame period check if in next frame                         sleeptime += frame_period;                         framesskipped++;                     }                 }             }             {                 // in case of exception surface not left in                 // inconsistent state                 view.getholder().unlockcanvasandpost(canvas);             }   // end         }     } } 

gameview

public class gameview extends surfaceview {     arraylist<bitmap> circles = new arraylist<>();     int color;     public static boolean isgameover;      public gameloopthread gameloopthread;     circle circle;      // code circle class provided below      public static int score = 0;     public static int stars = 0;      final handler handler = new handler();      int remainingtime;      boolean onetimeflag;      bitmap replay;     bitmap home;     bitmap star;      int highscore;     boolean isleaving;      public gameview(context context, arraylist<bitmap> circles, int color) {         super(context);         this.circles = circles;         this.color = color;          onetimeflag = true;         gameloopthread = new gameloopthread(gameview.this);          getholder().addcallback(new surfaceholder.callback() {             @override             public void surfacecreated(surfaceholder holder) {                 if (!gameloopthread.isrunning()) {                     gameloopthread.setrunning(true);                     gameloopthread.start();                 }             }              @override             public void surfacechanged(surfaceholder holder, int format, int width, int height) {              }              @override             public void surfacedestroyed(surfaceholder holder) {                 gameloopthread.setrunning(false);                 gameloopthread = new gameloopthread(gameview.this);             }         });          initializecircles();         if(!gameloopthread.isrunning()) {             gameloopthread.setrunning(true);             gameloopthread.start();         }     }      public void initializecircles() {         arraylist<string> numbers = new arraylist<>();         for(int i=0;i<10;i++)             numbers.add(i+"");          random random = new random();         int position = random.nextint(4);         numbers.remove(color + "");          int p1 = position;          int r1 = integer.valueof(numbers.get(random.nextint(9)));         numbers.remove(r1+"");          int r2 = integer.valueof(numbers.get(random.nextint(8)));         numbers.remove(r2 + "");          int r3 = integer.valueof(numbers.get(random.nextint(7)));          arraylist<bitmap> bitmaps = new arraylist<>();          if(position == 0) {             bitmaps.add(circles.get(color));             bitmaps.add(circles.get(r1));             bitmaps.add(circles.get(r2));             bitmaps.add(circles.get(r3));         }         else if(position == 1) {             bitmaps.add(circles.get(r1));             bitmaps.add(circles.get(color));             bitmaps.add(circles.get(r2));             bitmaps.add(circles.get(r3));         }         else if(position == 2) {             bitmaps.add(circles.get(r1));             bitmaps.add(circles.get(r2));             bitmaps.add(circles.get(color));             bitmaps.add(circles.get(r3));         }         else {             bitmaps.add(circles.get(r1));             bitmaps.add(circles.get(r2));             bitmaps.add(circles.get(r3));             bitmaps.add(circles.get(color));         }          numbers = new arraylist<>();         for(int i=0;i<10;i++)             numbers.add(i+"");          position = random.nextint(4);         numbers.remove(color + "");          r1 = integer.valueof(numbers.get(random.nextint(9)));         numbers.remove(r1 + "");          r2 = integer.valueof(numbers.get(random.nextint(8)));         numbers.remove(r2 + "");          r3 = integer.valueof(numbers.get(random.nextint(7)));          if(position == 0) {             bitmaps.add(circles.get(color));             bitmaps.add(circles.get(r1));             bitmaps.add(circles.get(r2));             bitmaps.add(circles.get(r3));         }         else if(position == 1) {             bitmaps.add(circles.get(r1));             bitmaps.add(circles.get(color));             bitmaps.add(circles.get(r2));             bitmaps.add(circles.get(r3));         }         else if(position == 2) {             bitmaps.add(circles.get(r1));             bitmaps.add(circles.get(r2));             bitmaps.add(circles.get(color));             bitmaps.add(circles.get(r3));         }         else {             bitmaps.add(circles.get(r1));             bitmaps.add(circles.get(r2));             bitmaps.add(circles.get(r3));             bitmaps.add(circles.get(color));         }          circle = new circle(this, bitmaps, circles, p1, position, color, getcontext());     }      @override     public void draw(canvas canvas) {         if(canvas != null) {             super.draw(canvas);             canvas.drawcolor(color.white);              if(!isgameover && timer != null)                 stoptimertask();             try {                 circle.draw(canvas);             } catch (gameoverexception e) {                 isgameover = true;                 if(isleaving)                     gameover(canvas);                 else if(gameactivity.counter > 0) {                     gameover(canvas);                     gameactivity.counter++;                 } else {                     if (onetimeflag) {                         int size1 = 200 * gameactivity.screen_height / 1280;                         int size2 = 125 * gameactivity.screen_height / 1280;                         float ratio = (float) gameactivity.screen_height / 1280;                          replay = gameactivity.decodesampledbitmapfromresource(getresources(), r.drawable.replay, size1, size1);                         home = gameactivity.decodesampledbitmapfromresource(getresources(), r.drawable.home, size2, size2);                         continuebutton = gameactivity.decodesampledbitmapfromresource(getcontext().getresources(), r.drawable.button, (int) (540 * ratio), (int) (100 * ratio));                         star = gameactivity.decodesampledbitmapfromresource(getcontext().getresources(), r.drawable.star1, (int) (220 * ratio), (int) (220 * ratio));                          int w = (int) ((float) gameactivity.screen_width * 0.9);                         onetimeflag = false;                     }                      if (askpurchasescreen == 2) {                         gameover(canvas);                     } else {                         canvas.drawcolor(circle.endcolor);                     }                 }             }         }     }      @override     public boolean ontouchevent(motionevent event) {         float x = event.getx();         float y = event.gety();         circle.ontouch(x, y);         return true;     } } 

circle

public class circle {     int x;     int y1;     int y2;     public static float speedy1 = 12.5f*(float)gameactivity.screen_height/1280;     public static float speedy2 = 12.5f*(float)gameactivity.screen_height/1280;     arraylist<bitmap> bitmaps;     gameview gameview;     int p1;     // position of required circle in slot 1     int p2;     // position of required circle in slot 2     int color;     int tempcolor;     int width;     context context;      // centers of required circle     float centerx1;     float centerx2;     float centery1;     float centery2;      arraylist<bitmap> circles = new arraylist<>();     boolean touchedfirst;     boolean touchedsecond;     int count1 = 1;     // slot 1 circle radius animation     int count2 = 1;     // slot 2 circle radius animation      float tempspeedy1;     float tempspeedy2;     boolean stopy1;     boolean stopy2;     int barcounter = 1;     int loopcount = 0;      int endgamecount = 0;   // count move circle upwards     double limit;     float endradiusspeed;     int endslot;    // died     int endradiuscount = 0; // count increase circle radius     int barendcounter = 1;      final handler handler = new handler();     boolean exception;     public static int endcolor;      public circle(gameview gameview, arraylist<bitmap> bitmaps, arraylist<bitmap> circles, int p1, int p2, int color, context context) {         this.gameview = gameview;         this.bitmaps = bitmaps;         this.circles = circles;         this.p1 = p1;         this.p2 = p2;         this.color = color;         this.context = context;          width = gameactivity.screen_width / 4 - 10;         x = 10;         y1 = 0;         y2 = -(gameactivity.screen_height + width) / 2;          centerx1 = x + p1 * (10 + width) + width / 2;         centery1 = y1 + width / 2;          centerx2 = x + p2 * (10 + width) + width / 2;         centery2 = y2 + width / 2;     }      public void update() throws gameoverexception {         y1+= speedy1;         y2+= speedy2;          centery1+= speedy1;         centery2+= speedy2;          float ratio = (float)gameactivity.screen_height/1280;         limit = width/(20*ratio);          if(y1 >= gameview.getheight()) {             loopcount++;              if(touchedfirst)                 touchedfirst = false;             else {                 speedy1 = speedy2 = -(12.5f * ratio);                 endcolor = bitmaps.get(p1).getpixel(width/2, width/2);                  endgamecount += 1;                 endslot = 1;             }              if(endgamecount == 0) {                 if (stopy1) {                     tempspeedy1 = speedy1;                     speedy1 = 0;                     arraylist<integer> numbers = new arraylist<>();                     (int = 0; < 10; i++) {                         if (i != color)                             numbers.add(i);                     }                     tempcolor = numbers.get(new random().nextint(9));                 }                  y1 = -(gameview.getwidth() / 4 - 10);                 count1 = 1;                 setbitmaps(1);             }         }         else if(y2 >= gameview.getheight()) {             loopcount++;              if(touchedsecond)                 touchedsecond = false;             else {                 speedy1 = speedy2 = -(12.5f * ratio);                 endcolor = bitmaps.get(p2 + 4                 ).getpixel(width/2, width/2);                 endgamecount += 1;                 endslot = 2;             }              if(endgamecount == 0) {                 if (stopy2) {                     tempspeedy2 = speedy2;                     speedy2 = 0;                 }                  y2 = -(gameview.getwidth() / 4 - 10);                 count2 = 1;                 setbitmaps(2);             }         }     }      public void setbitmaps(int slot) {         arraylist<string> numbers = new arraylist<>();         for(int i=0;i<10;i++)             numbers.add(i+"");          random random = new random();         int position = random.nextint(4);         numbers.remove(color + "");          int r1 = integer.valueof(numbers.get(random.nextint(9)));         numbers.remove(r1+"");          int r2 = integer.valueof(numbers.get(random.nextint(8)));         numbers.remove(r2 + "");          int r3 = integer.valueof(numbers.get(random.nextint(7)));          if(position == 0) {             bitmaps.set((slot - 1)*4, circles.get(color));             bitmaps.set((slot - 1)*4 + 1, circles.get(r1));             bitmaps.set((slot - 1)*4 + 2, circles.get(r2));             bitmaps.set((slot - 1)*4 + 3, circles.get(r3));         }         else if(position == 1) {             bitmaps.set((slot - 1)*4, circles.get(r1));             bitmaps.set((slot - 1)*4 + 1, circles.get(color));             bitmaps.set((slot - 1)*4 + 2, circles.get(r2));             bitmaps.set((slot - 1)*4 + 3, circles.get(r3));         }         else if(position == 2) {             bitmaps.set((slot - 1)*4, circles.get(r1));             bitmaps.set((slot - 1)*4 + 1, circles.get(r2));             bitmaps.set((slot - 1)*4 + 2, circles.get(color));             bitmaps.set((slot - 1)*4 + 3, circles.get(r3));         } else {             bitmaps.set((slot - 1)*4,circles.get(r1));             bitmaps.set((slot - 1)*4 + 1,circles.get(r2));             bitmaps.set((slot - 1)*4 + 2,circles.get(r3));             bitmaps.set((slot - 1)*4 + 3,circles.get(color));         }         if(slot == 1) {             p1 = position;             centerx1 = x+position*(10 + width) + width/2;             centery1 = y1 + width/2;         }         else if(slot == 2) {             p2 = position;             centerx2 = x+position*(10 + width) + width/2;             centery2 = y2 + width/2;         }     }      public void ontouch(float x, float y) {         int radius = (gameview.getwidth() / 4 - 10) / 2;          if(endgamecount == 0) {             if ((x >= centerx1 - radius) && (x <= centerx1 + radius) && (y >= centery1 - radius) && (y <= centery1 + radius)) {                 gameview.score++;                 touchedfirst = true;                 centerx1 = centery1 = -1;                  if(p1 == (timercount - 1) && timer != null && starslot == 1) {                     gameview.stars++;                     starcollected = true;                     timercount = 0;                     stoptimertask(0);                 }             } else if ((x >= centerx2 - radius) && (x <= centerx2 + radius) && (y >= centery2 - radius) && (y <= centery2 + radius)) {                 gameview.score++;                 touchedsecond = true;                 centerx2 = centery2 = -1;                  if(p2 == (timercount - 1) && timer != null && starslot == 2) {                     gameview.stars++;                     starcollected = true;                     timercount = 0;                     stoptimertask(0);                 }             } else {                 endslot = 0;                 if ((y >= centery1 - radius) && (y <= centery1 + radius)) {                     endslot = 1;                     if (x >= 10 && x <= 10 + 2 * radius) {                         p1 = 0;                         centerx1 = 10 + radius;                     } else if (x >= 20 + 2 * radius && x <= 20 + 4 * radius) {                         p1 = 1;                         centerx1 = 20 + 3 * radius;                     } else if (x >= 30 + 4 * radius && x <= 30 + 6 * radius) {                         p1 = 2;                         centerx1 = 30 + 5 * radius;                     } else if (x >= 40 + 6 * radius && x <= 40 + 8 * radius) {                         p1 = 3;                         centerx1 = 40 + 2 * radius;                     } else                         endslot = 0;                 } else if ((y >= centery2 - radius) && (y <= centery2 + radius)) {                     endslot = 2;                     if (x >= 10 && x <= 10 + 2 * radius) {                         p2 = 0;                         centerx2 = 10 + radius;                     } else if (x >= 20 + 2 * radius && x <= 20 + 4 * radius) {                         p2 = 1;                         centerx2 = 20 + 3 * radius;                     } else if (x >= 30 + 4 * radius && x <= 30 + 6 * radius) {                         p2 = 2;                         centerx2 = 30 + 5 * radius;                     } else if (x >= 40 + 6 * radius && x <= 40 + 8 * radius) {                         p2 = 3;                         centerx2 = 40 + 2 * radius;                     } else                         endslot = 0;                 }                 if (endslot != 0) {                     speedy1 = speedy2 = 0;                     limit = endgamecount = 6;                      if (endslot == 1) {                         endcolor= bitmaps.get(p1).getpixel(width/2, width/2);                     } else {                         endcolor = bitmaps.get(p2 + 4).getpixel(width/2, width/2);                     }                 }             }              if (gameview.score % 5 == 0 && gameview.score <= 110 && barcounter == 1) {                 float ratio = (float)gameactivity.screen_height/1280;                 speedy1 += ratio*0.5;                 speedy2 += ratio*0.5;             }              if (gameview.score > 0 && gameview.score % 15 == 14) {                 if(isoddscore)                     stopy1 = true;                 else                     stopy2 = true;             }              if (gameview.score > 0 && gameview.score % 15 == 0 && barcounter == 1) {                 if(isoddscore)                     stopy2 = true;                 else                     stopy1 = true;             }              if (gameview.score % 15 == 1)                 barcounter = 1;         }     }     public void draw(canvas canvas) throws gameoverexception {         gameview.isgameover = false;         if(exception)             throw new gameoverexception(color);         update();          for(int i=0;i<bitmaps.size();i++) {             if(i<4) {                 rect rect = new rect(x+i*(10 + width),y1,(x+width)*(i+1),y1+width);                 if(endgamecount == math.ceil(limit) && endslot == 1) {                     if(i == p1) {                         endradiuscount += 1;                         if (endradiuscount > 23) {                             star.recycle();                             loopcount = loopcount%starinterval;                             cryptography.savefile((loopcount + "").getbytes(), context, "interval");                             endgamecount = 0;                             exception = true;                             throw new gameoverexception(color);                         }                          rect = new rect(x + * (10 + width) - endradiuscount*(int)math.ceil(endradiusspeed), y1 - endradiuscount*(int)math.ceil(endradiusspeed), (x + width) * (i + 1) + endradiuscount*(int)math.ceil(endradiusspeed), y1 + width + endradiuscount*(int)math.ceil(endradiusspeed));                         canvas.drawbitmap(bitmaps.get(i), null, rect, null);                     }                 }                  // touch animation : diminish circle                 else if(i==p1 && touchedfirst) {                     rect = new rect(x + * (10 + width) + 3*count1 + ((int)speedy1-15), y1 + 3*count1 + ((int)speedy1-15), (x + width) * (i + 1) - 3*count1 - ((int)speedy1-15), y1 + width - 3*count1 - ((int)speedy1-15));                     canvas.drawbitmap(bitmaps.get(i), null, rect, null);                     count1++;                 }                  else if(endslot != 2) {                     canvas.drawbitmap(bitmaps.get(i), null, rect, null);                     if(timercount > 0 && starslot == 1) {                         int size = width * 30 / 50;                         int difference = (width - size) / 2;                         rect starrect = new rect(x + (timercount - 1) * (10 + width) + difference, y1 + difference, (x + width) * (timercount) - difference, y1 + width - difference);                         canvas.drawbitmap(star, null, starrect, null);                     }                 }             }             if(i >= 4) {                 rect rect = new rect(x + (i % 4) * (10 + width), y2, (x + width) * ((i % 4) + 1), y2 + width);                 if(endgamecount == math.ceil(limit) && endslot == 2) {                     if((i%4)==p2) {                         endradiuscount += 1;                         if (endradiuscount > 23) {                             star.recycle();                             loopcount = loopcount%starinterval;                             cryptography.savefile((loopcount + "").getbytes(), context, "interval");                             endgamecount = 0;                             exception = true;                             throw new gameoverexception(color);                         }                          rect = new rect(x + (i % 4) * (10 + width) - endradiuscount*(int)math.ceil(endradiusspeed), y2 - endradiuscount*(int)math.ceil(endradiusspeed), (x + width) * ((i % 4) + 1) + endradiuscount*(int)math.ceil(endradiusspeed), y2 + width + endradiuscount*(int)math.ceil(endradiusspeed));                         canvas.drawbitmap(bitmaps.get(i), null, rect, null);                     }                 }                 else if((i%4)==p2 && touchedsecond) {                     rect = new rect(x + (i % 4) * (10 + width) + 3*count2 + ((int)speedy1-15), y2 + 3*count2 + ((int)speedy1-15), (x + width) * ((i % 4) + 1) - 3*count2 - ((int)speedy1-15), y2 + width - 3*count2 - ((int)speedy1-15));                     canvas.drawbitmap(bitmaps.get(i), null, rect, null);                     count2++;                 }                 else if(endslot != 1) {                     canvas.drawbitmap(bitmaps.get(i), null, rect, null);                     if(timercount > 0 && starslot == 2) {                         int size = width * 30 / 50;                         int difference = (width - size) / 2;                         rect starrect = new rect(x + (timercount - 1) * (10 + width) + difference, y2 + difference, (x + width) * (timercount) - difference, y2 + width - difference);                         canvas.drawbitmap(star, null, starrect, null);                     }                 }             }         }         rect src = new rect(circles.get(color).getwidth()/2 - 10,circles.get(color).getheight()/2 - 10,circles.get(color).getwidth()/2 + 10,circles.get(color).getheight()/2 + 10);         rect dst;          paint paint = new paint();         paint.setcolor(color.white);         paint.settextalign(paint.align.right);         paint.settypeface(typeface.sans_serif);         paint.settextsize(72 * ratio);         canvas.drawtext(gameview.score + " ", gameactivity.screen_width, width / 2, paint);          dst = new rect(5,5, (int) (120 * ratio - 5), (int) (120 * ratio - 5));         canvas.drawbitmap(star,null,dst,null);         paint.settextalign(paint.align.left);         canvas.drawtext("" + gameview.stars, 120 * ratio, width/2, paint);     } } 

don't override draw(). that's used render view, not surface, , shouldn't override method if you're creating custom view:

when implementing view, implement ondraw(android.graphics.canvas) instead of overriding method.

surfaceviews have 2 parts, surface , view. view part handled other view, transparent "hole" in layout. surface separate layer that, default, sits behind view layer. whatever draw on surface "shows through" transparent hole.

by overriding draw() you're drawing on view whenever view ui invalidated. you're calling draw() render thread, you're drawing on surface, default z-ordering can't see because view contents opaque. reduce impact on ui thread not drawing in 2 different layers.

unless you're deliberately drawing on view, it's best avoid subclassing surfaceview entirely, , use member.

because draw code synchronized, 2 draw passes not execute concurrently. means view layer draw call block waiting surface layer rendering complete. canvas rendering on surface not hardware-accelerated, if you're touching lot of pixels can slow, , ui thread have wait run. wouldn't bad, you're holding on mutex while you're sleeping, means opportunity main ui thread run comes during brief instant when loop wraps around. thread scheduler not guarantee fairness, it's entirely possible starve main ui thread way.

if change @override draw() mydraw() things should better. should move sleep call out of synchronized block on general principles, or work eliminate entirely. might want consider using custom view instead of surfaceview.

on unrelated note, should avoid doing every update:

random random = new random(); 

for reasons noted here.


Comments

Popular posts from this blog

javascript - How to get current YouTube IDs via iMacros? -

c# - Maintaining a program folder in program files out of date? -

emulation - Android map show my location didn't work -