I have two activities: a menu, and a game. I have them both set up as surface views, and when I click the "start" button on the menu activity, it starts the game activity. Then I want it to save the score and return to the menu activity when the player crashes. Both activities have separate threads that start with the activity, so when I tried to re-launch the menu activity from the game, I was getting an exception that the thread was already started. So to avoid this, I had the game activity finish the menu activity when it started so that relaunching the menu activity would also restart the thread. Now I'm getting an exception that the canvas is already locked. Do I need to unlock the canvas before finishing the activity? And is there a better way for me to handle switching between activities?

MainActivity:

package com.mikey.******;import android.app.Activity;import android.os.Bundle;import android.view.Menu;import android.view.MenuItem;import android.view.Window;import android.view.WindowManager;public class MainActivity extends Activity {public static Activity activity;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);activity=this;requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);setContentView(new GamePanel(this));}}

GamePanel Layout:

package com.mikey.*****;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Point;import android.graphics.Rect;import android.graphics.RectF;import android.preference.PreferenceManager;import android.support.v4.app.NavUtils;import android.util.AttributeSet;import android.view.Display;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.WindowManager;import java.util.ArrayList;import java.util.Random;public class GamePanel extends SurfaceView implements SurfaceHolder.Callback {private static SharedPreferences prefs;public static int width;public static int height;public static int screenX, screenY;private Canvas c;private MainThread thread;private Background bg;private Scoreboard sb;public int moveSpeed=10;private Player player;private ArrayList<Smokepuff> smoke;private Plunger plunger;private Plunger plunger1;private long smokeStart;private long smokeTime;public int score=0;public boolean isPlaying;private Bitmap bgImg;private Bitmap b;private int scaleFactor=2;private long timer;private long timeStart;private Paint paint;private ArrayList<Coin> coin;private long coinTime;private int coinDelay;private Bitmap coinImg;public boolean playable;public int distance;private int plungerDelay;private int plungerReset;private long plungerTime;private int coinSet;private Menu endMenu;public GamePanel(Context context){super(context);prefs=PreferenceManager.getDefaultSharedPreferences(getContext());WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display=wm.getDefaultDisplay();Point size=new Point();display.getSize(size);screenX=size.x;screenY=size.y;getHolder().addCallback(this);thread=new MainThread(getHolder(), this);setFocusable(true);paint=new Paint();paint.setColor(Color.WHITE);paint.setStyle(Paint.Style.FILL);paint.setTextSize(40);}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height){}@Overridepublic void surfaceDestroyed(SurfaceHolder holder){boolean retry=true;int count=0;while(retry&&count<1000){try{thread.setRunning(false);thread.join();retry=false;}catch(InterruptedException e){}count++;}}@Overridepublic void surfaceCreated(SurfaceHolder holder){thread.setRunning(true);thread.start();//moveSpeed=-20;bgImg=BitmapFactory.decodeResource(getResources(), R.drawable.bg2);width=bgImg.getWidth();height=bgImg.getHeight();bg=new Background(bgImg);sb=new Scoreboard(getContext());plunger=new Plunger(BitmapFactory.decodeResource(getResources(), R.drawable.plunger));plunger1=new Plunger(BitmapFactory.decodeResource(getResources(),R.drawable.plunger));player=new Player(BitmapFactory.decodeResource(getResources(), R.drawable.potty));smoke=new ArrayList<Smokepuff>();coin=new ArrayList<Coin>();//Random r=new Random();coinImg=BitmapFactory.decodeResource(getResources(),R.drawable.coin2);coin.add(new Coin(coinImg));coinDelay=5;playable=true;}@Overridepublic boolean onTouchEvent(MotionEvent event){if(event.getAction()==MotionEvent.ACTION_DOWN){if(!isPlaying&&playable){isPlaying=true;smokeStart=System.nanoTime();timeStart=System.nanoTime();plungerReset=distance;plungerDelay=100;coinSet=distance;}player.setAccelerate(true);player.setUp(true);return true;}else if(event.getAction()==MotionEvent.ACTION_UP){player.setAccelerate(false);player.setUp(false);return true;}return super.onTouchEvent(event);}public void update(){if(isPlaying) {timer=(System.nanoTime() - timeStart) / 1000000;distance+=(timer*moveSpeed)/1000;if (timer > 50) {if(player.getAccelerate()&&!player.maxAlt) {moveSpeed +=1;}else if(!player.getAccelerate()&&!player.maxAlt){if(moveSpeed>0){if(distance<200){moveSpeed-=.05;}else {moveSpeed -=.18;}}}timeStart=System.nanoTime();}//moveSpeed +=score;smokeTime=(System.nanoTime()-smokeStart)/1000000;if(smokeTime>100){smoke.add(new Smokepuff(player.getX(),player.getY()+5));smokeStart=System.nanoTime();}if(distance>300&&plungerDelay+plungerReset<distance){plunger.setX(screenX);plunger1.setX(screenX+500);Random q=new Random();plungerDelay=q.nextInt(150)+100;plungerReset=distance;}if(distance-coinSet>coinDelay) {Random z=new Random();int num=z.nextInt(3) + 1;for (int i=0; i < num; i++) {coin.add(new Coin(coinImg));}Random r=new Random();coinDelay=r.nextInt(50) + 1;coinSet=distance;}plunger.update(moveSpeed);plunger1.update(moveSpeed);int dy=player.update();bg.update(moveSpeed, dy);for(int i=0;i<coin.size();i++){coin.get(i).update(moveSpeed);if(coin.get(i).getX()<-10){coin.remove(i);}else if (collision(coin.get(i), player)) {coin.remove(i);score+=10;}}if(collision(player,plunger)){plunger.setX(player.getX() + player.getWidth() - 1);plunger.setY(player.getY()+player.height/2);if(!plunger.attached){plungerTime=System.nanoTime();plunger.attached=true;}if(moveSpeed>10){moveSpeed--;}}if(plunger.getX()<-100){plunger.reset();}if(collision(player,plunger1)){plunger1.setX(player.getX() + player.getWidth()-1);plunger1.setY(player.getY()+player.height/2);if(!plunger1.attached) {plungerTime=System.nanoTime();plunger1.attached=true;}if(moveSpeed>10){moveSpeed--;}}if(plunger1.getX()<-100){plunger1.reset();}if((System.nanoTime()-plungerTime)/1000000>750){if(collision(plunger,player)){plunger.reset();plunger.attached=false;}if(collision(plunger1,player)){plunger1.reset();plunger1.attached=false;}}for(int i=0;i<smoke.size();i++){smoke.get(i).update(moveSpeed);if(smoke.get(i).getX()<-10||smoke.get(i).getY()<0){smoke.remove(i);}}sb.update(score, distance);if(2*player.getY()>screenY-300){SharedPreferences.Editor editor=prefs.edit();if(!prefs.contains("highscore")) {editor.putInt("highscore", score);//return;}else if(prefs.getInt("highscore",0)<score){editor.putInt("highscore",score);}editor.commit();isPlaying=false;playable=false;endGame();//NavUtils.navigateUpFromSameTask(MainActivity.activity);Intent intent=new Intent(getContext(),Menu.class);getContext().startActivity(intent);}}}public boolean collision(GameObject a, GameObject b){if(Rect.intersects(a.getRect(),b.getRect())){return true;}return false;}@Overridepublic void draw(Canvas canvas){final float scaleFactorX=(float) 2;final float scaleFactorY=(float) 2;if(canvas!=null){c=canvas;final int savedState=canvas.save();canvas.scale(scaleFactorX, scaleFactorY);bg.draw(canvas);for(Coin c:coin){c.draw(canvas);}plunger.draw(canvas);plunger1.draw(canvas);for(Smokepuff sp:smoke){sp.draw(canvas);}player.draw(canvas);if((isPlaying&&playable)||(!isPlaying&&!playable)) {sb.draw(canvas);}canvas.restoreToCount(savedState);canvas.drawText(Integer.toString(moveSpeed), screenX-100,40,paint);}//bg.draw(canvas);}public void endGame(){SharedPreferences.Editor editor=prefs.edit();if(!prefs.contains("highscore")) {editor.putInt("highscore", score);return;}else if(prefs.getInt("highscore",0)<score){editor.putInt("highscore",score);}editor.commit();Intent intent=new Intent(getContext(),Menu.class);getContext().startActivity(intent);}}

Menu Activity:

package com.mikey.*****;import android.app.Activity;import android.graphics.Bitmap;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.Paint;import android.graphics.Rect;import android.os.Bundle;import android.support.design.widget.FloatingActionButton;import android.support.design.widget.Snackbar;import android.support.v7.app.AppCompatActivity;import android.support.v7.widget.Toolbar;import android.view.View;import android.view.Window;import android.view.WindowManager;import android.widget.ImageButton;public class Menu extends Activity{//private ImageButton upgrade;private int screenY;private int screenX;@Overrideprotected void onCreate(Bundle savedInstanceState) {super.onCreate(savedInstanceState);requestWindowFeature(Window.FEATURE_NO_TITLE);getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN, WindowManager.LayoutParams.FLAG_FULLSCREEN);screenY=getWindow().getDecorView().getHeight();screenX=getWindow().getDecorView().getWidth();setContentView(new MenuLayout(this));/*upgrade=(ImageButton) findViewById(R.id.upgrade);upgrade.setX(-150);upgrade.setY(1080-130);upgrade.setScaleX(4);upgrade.setScaleY(4);*/}@Overrideprotected void onPause(){super.onPause();finish();}}

MenuLayout:

package com.mikey.*****;import android.content.Context;import android.content.Intent;import android.content.SharedPreferences;import android.graphics.Bitmap;import android.graphics.BitmapFactory;import android.graphics.BlurMaskFilter;import android.graphics.Canvas;import android.graphics.Color;import android.graphics.LinearGradient;import android.graphics.Matrix;import android.graphics.Paint;import android.graphics.Point;import android.graphics.PorterDuff;import android.graphics.RadialGradient;import android.graphics.RectF;import android.graphics.Shader;import android.preference.PreferenceManager;import android.view.Display;import android.view.MotionEvent;import android.view.SurfaceHolder;import android.view.SurfaceView;import android.view.WindowManager;import java.util.ArrayList;import java.util.Random;public class MenuLayout extends SurfaceView implements SurfaceHolder.Callback {private static SharedPreferences prefs;private MenuThread thread;private boolean played;private int screenX, screenY;private Bitmap upgrade;private Bitmap map;private Bitmap bg;private Bitmap launch;private Bitmap potty;private Bitmap cloudA;private Bitmap cloudB;private ArrayList<Cloud> cloud;private UpgradeBtn upgradeBtn;private MapBtn mapBtn;private LaunchBtn launchBtn;//private Paint bg;private Paint feature;private Paint border;private Paint featureRad;private Paint stick;private Paint text;private Paint shadow;private int x;private int y;private boolean upg;private boolean showmap;private boolean start;public MenuLayout(Context context){super(context);prefs=PreferenceManager.getDefaultSharedPreferences(getContext());WindowManager wm=(WindowManager) context.getSystemService(Context.WINDOW_SERVICE);Display display=wm.getDefaultDisplay();Point size=new Point();display.getSize(size);getHolder().addCallback(this);thread=new MenuThread(getHolder(),this);setFocusable(true);screenX=size.x;screenY=size.y;upgrade=BitmapFactory.decodeResource(getResources(),R.drawable.blueprint);map=BitmapFactory.decodeResource(getResources(),R.drawable.map);launch=BitmapFactory.decodeResource(getResources(),R.drawable.launch);bg=BitmapFactory.decodeResource(getResources(),R.drawable.menu_bg);potty=BitmapFactory.decodeResource(getResources(),R.drawable.potty1);cloudA=BitmapFactory.decodeResource(getResources(),R.drawable.cloud1);cloudB=BitmapFactory.decodeResource(getResources(),R.drawable.cloud2);upgradeBtn=new UpgradeBtn(upgrade,screenY);mapBtn=new MapBtn(map);launchBtn=new LaunchBtn(launch,screenX,screenY);cloud=new ArrayList<>();for(int i=0;i<4;i++){addCloud();}start=true;//bg=new Paint();//bg.setColor(Color.WHITE);shadow=new Paint();shadow.setAntiAlias(true);shadow.setColor(Color.WHITE);shadow.setTextSize(45.0f);shadow.setStrokeWidth(2.0f);shadow.setStyle(Paint.Style.STROKE);shadow.setShadowLayer(10.0f, 20.0f, -20.0f, Color.BLACK);Shader shader=new LinearGradient(0, 0, 0, 90, Color.LTGRAY, Color.DKGRAY, Shader.TileMode.CLAMP);feature=new Paint();feature.setShader(shader);border=new Paint();border.setColor(Color.BLACK);border.setStyle(Paint.Style.STROKE);border.setStrokeWidth(8);Shader shader1=new RadialGradient(screenX-60,60,150,Color.LTGRAY,Color.DKGRAY, Shader.TileMode.MIRROR);featureRad=new Paint();featureRad.setShader(shader1);stick=new Paint();stick.setColor(Color.BLACK);stick.setStrokeWidth(20);text=new Paint();text.setColor(Color.WHITE);text.setTextSize(50);}public void addCloud(){Bitmap img;Random r=new Random();Random p=new Random();Random q=new Random();int s=r.nextInt(10);if(s>5){Matrix m=new Matrix();float h=r.nextFloat()+1;m.setRectToRect(new RectF(0, 0, cloudA.getWidth(), cloudA.getHeight()),new RectF(0, 0, cloudA.getWidth()*h, cloudA.getHeight()*h), Matrix.ScaleToFit.CENTER);img=Bitmap.createBitmap(cloudA, 0, 0, cloudA.getWidth(), cloudA.getHeight(), m, true);}else{img=cloudB;}if(start){x=-img.getWidth();}else{x=p.nextInt(screenX);}cloud.add(new Cloud(img,x,p.nextInt(screenY-750)+100,q.nextInt(8)+1,screenX));}public Bitmap highlightImage(Bitmap src, int color,boolean x, boolean y) {int xMod;int yMod;if(x){xMod=4;}else{xMod=-1;}if(y){yMod=2;}else{yMod=-1;}// create new bitmap, which will be painted and becomes result imageBitmap bmOut=Bitmap.createBitmap(src.getWidth()*5/4+30, src.getHeight()*5/4+30, Bitmap.Config.ARGB_8888);// setup canvas for paintingCanvas canvas=new Canvas(bmOut);canvas.scale(1.25f,1.25f);// setup default colorcanvas.drawColor(0, PorterDuff.Mode.CLEAR);// create a blur paint for capturing alphaPaint ptBlur=new Paint();ptBlur.setMaskFilter(new BlurMaskFilter(15, BlurMaskFilter.Blur.NORMAL));int[] offsetXY=new int[2];// capture alpha into a bitmapBitmap bmAlpha=src.extractAlpha(ptBlur, offsetXY);// create a color paintPaint ptAlphaColor=new Paint();ptAlphaColor.setColor(color);// paint color for captured alpha region (bitmap)canvas.drawBitmap(bmAlpha, xMod*offsetXY[0]/2, yMod*offsetXY[1], ptAlphaColor);// free memorybmAlpha.recycle();// paint the image sourcecanvas.drawBitmap(src, 0, 0, null);// return out final imagereturn bmOut;}public void launchUpgrade(){upg=true;upgradeBtn.setImg(upgrade);}public void launchMap(){showmap=true;mapBtn.setImg(map);}public void launchProfile(){}public void startGame(){launchBtn.setImg(launch);Intent myIntent=new Intent(getContext(), MainActivity.class);//myIntent.putExtra("key", value); //Optional parametersgetContext().startActivity(myIntent);}@Overridepublic void surfaceCreated(SurfaceHolder holder) {if(!thread.getRunning()) {thread.setRunning(true);thread.start();}}@Overridepublic void surfaceChanged(SurfaceHolder holder, int format, int width, int height){}@Overridepublic void surfaceDestroyed(SurfaceHolder holder){boolean retry=true;int count=0;if(thread.getRunning()) {thread.interrupt();}/*while(retry&&count<1000){try{thread.setRunning(false);thread.join();retry=false;}catch(InterruptedException e){}count++;}*/}@Overridepublic boolean onTouchEvent(MotionEvent event) {x=(int) event.getX();y=(int) event.getY();if (x < 710 && y > 780) {upgradeBtn.setImg(highlightImage(upgrade,Color.BLUE,false,true));}else{upgradeBtn.setImg(upgrade);}if (x < 520 && y < 275) {mapBtn.setImg(highlightImage(map,Color.YELLOW,true,false));}else{mapBtn.setImg(map);}if(x>1500&&y>700){launchBtn.setImg(highlightImage(launch,Color.RED,true,true));}else{launchBtn.setImg(launch);}if(event.getAction()==MotionEvent.ACTION_UP) {if (x < 710 && y > 780) {launchUpgrade();return true;}if (x < 520 && y < 275) {launchMap();return true;}if(x>1700&&y<235){launchProfile();return true;}if(x>1500&&y>700){startGame();}}return true;}public void update(){for(int i=0;i<cloud.size();i++){cloud.get(i).update();if(cloud.get(i).getX()>screenX){cloud.remove(i);addCloud();}}}@Overridepublic void draw(Canvas canvas){if(canvas!=null) {canvas.drawBitmap(bg,-3,0,null);for(int i=0;i<cloud.size();i++){cloud.get(i).draw(canvas);}canvas.drawBitmap(potty, screenX / 2 - 190, screenY / 2 - 190, null);//canvas.drawBitmap(upgrade, -235, screenY - upgrade.getHeight() + 300, null);canvas.drawRoundRect(screenX - 550, 5, screenX - 150, 105, 15, 15, feature);canvas.drawRoundRect(screenX - 550, 5, screenX - 150, 105, 25, 25, border);canvas.drawCircle(screenX - 60, 60, 150, featureRad);canvas.drawCircle(screenX - 60, 60, 150, border);canvas.drawCircle(screenX / 2 + 230, screenY / 2 + 110, 50, stick);canvas.drawLine(screenX / 2 + 220, screenY / 2 + 110, screenX / 2 + 185, screenY / 2 + 340, stick);canvas.drawLine(screenX / 2 + 185, screenY / 2 + 340, screenX / 2 + 270, screenY/2+440,stick);canvas.drawLine(screenX/2+270,screenY/2+440,screenX/2+270,screenY,stick);canvas.drawLine(screenX/2+270,screenY/2+440,screenX/2+340,screenY,stick);canvas.drawLine(((screenX / 2 + 220)+(screenX / 2 + 185))/2,screenY/2+230,screenX/2+210,screenY/2+250,stick);canvas.drawLine(screenX/2+185,screenY/2+250,screenX/2+245,screenY/2+235,stick);canvas.drawLine(screenX / 2 + 235, screenY / 2 + 245, ((screenX / 2 + 220) + (screenX / 2 + 185)) / 2,screenY / 2 + 230, stick);canvas.drawText(Integer.toString(prefs.getInt("highscore", 0)), 1000, 50, text);upgradeBtn.draw(canvas);mapBtn.draw(canvas);launchBtn.draw(canvas);canvas.drawText(Integer.toString(x)+","+Integer.toString(y),50,50,text);/*if(upg){canvas.drawText("UPGRADE",540,400,text);canvas.drawBitmap(highlightImage(upgrade), -235, screenY - upgrade.getHeight() + 300,null);}*/if(showmap){canvas.drawText("MAP",540,500,text);}}}}

I'm sure there is a lot more wrong with my code than just the issue I'm having because I'm very new to this, so if you have any general suggestions to clean up my code, I'd love to hear those as well.

  • Please show your code for MenuActivity, Game Activity and Logcat,so that we can debug it.– LampardApr 26 '16 at 7:32
  • @CrazyAndroid I hope that is useful. The intents are in the GamePanel and MenuLayout code– MikeyApr 26 '16 at 23:48

Your Answer

 

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

Browse other questions tagged or ask your own question.