[Solved]My Android app crashes at exit (and screen rotation)

Whether you're a newbie or an experienced programmer, any questions, help, or just talk of any language will be welcomed here.

Moderator: Coders of Rage

Post Reply
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

[Solved]My Android app crashes at exit (and screen rotation)

Post by superLED »

Hi there!

I've struggled with this for some months now. I've just been ignoring it, because it hasn't been to much of a problem to me, but now I'm ready for release, and would like to fix it up.

The problem is that when I'm in the game, and click the Home button, the gameLoop thread (I guess) fucks up and then it pops up "Unfortunately, <app name> has stopped."
It also crashes when I rotate the screen (not too much of a problem, because I have fixed orientation, but would like to fix it for future projects)
I have very little experience with Java and Android development, so please keep that in mind.

I've made a very simple program where this problem occurs. All the program does is showing a number on the screen, and increasing it when you touch the screen.

Error message:

Code: Select all

FATAL EXEPTION: Thread-23207
java.lang.NullPointerExeption
at com.example.crashtest.GameView.onDraw(GameView.java:61)
at com.example.crashtest.GameLoopThread.run(GameLoopThread.java:34)
Here's the code:

MainActivity.java

Code: Select all

package com.example.crashtest;

import android.media.AudioManager;
import android.os.Bundle;
import android.app.Activity;
import android.content.Context;
import android.content.res.Configuration;
import android.view.KeyEvent;
import android.view.Window;

public class MainActivity extends Activity {
	private AudioManager am;
	
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        setContentView(new GameView(this));
        
        am = (AudioManager) getSystemService(Context.AUDIO_SERVICE);
    }
    
    @Override
    public void onConfigurationChanged(Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
    }
    
    @Override
    public boolean onKeyDown(int keyCode, KeyEvent event) {
        switch (keyCode) {
	        case KeyEvent.KEYCODE_BACK:
	        	return true;
	        	
	        case KeyEvent.KEYCODE_MENU:
	        	return true;
	        	
	        case KeyEvent.KEYCODE_VOLUME_UP:
	        	am.adjustStreamVolume(AudioManager.STREAM_MUSIC,
	                    AudioManager.ADJUST_RAISE, AudioManager.FLAG_SHOW_UI);
	            return true;
	            
	        case KeyEvent.KEYCODE_VOLUME_DOWN:
	        	am.adjustStreamVolume(AudioManager.STREAM_MUSIC,
	                    AudioManager.ADJUST_LOWER, AudioManager.FLAG_SHOW_UI);
	            return true;
	            
	        default:
	            return false;
        }
    }
}
GameView.java

Code: Select all

package com.example.crashtest;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameView extends SurfaceView {	
	private SurfaceHolder holder;
	private GameLoopThread gameLoopThread;
    
	private int num = 0;
	
	public GameView(final Context context) {
		super(context);
		
		holder = getHolder();
		holder.addCallback(new SurfaceHolder.Callback() {
			
			@Override
            public void surfaceDestroyed(SurfaceHolder holder) {
					
                   boolean retry = true;
                   gameLoopThread.setRunning(false);
                   while (retry) {
                          try {
                                gameLoopThread.join();
                                retry = false;
                          } catch (InterruptedException e) {}
                   }
            }
			
			@Override
			public void surfaceCreated(SurfaceHolder holder) {
				
				makeThread();
				gameLoopThread.start();
				gameLoopThread.setRunning(true);
			}
			
			@Override
			public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
				
			}
		});
	}
	
	private void makeThread() {
		gameLoopThread = new GameLoopThread(this);
	}
	
	@SuppressLint({ "WrongCall", "DrawAllocation" })
	@Override
	protected void onDraw(Canvas canvas) {
		// Draw black background - Write variable 'num' on the screen
		canvas.drawColor(Color.BLACK);
		
		Paint paint = new Paint();
		paint.setARGB(255, 0, 255, 0);
		paint.setTextSize(50);
		paint.setTextAlign(Align.CENTER);
		
		canvas.drawText(Integer.toString(num), getWidth() / 2, getHeight() / 2, paint);
	}
	
	public boolean onTouchEvent(MotionEvent event) {
		if(event.getAction() == MotionEvent.ACTION_DOWN) {
			// Increase 'num' with 1 every touch
			num++;
		}
		
		return super.onTouchEvent(event);
	}
}
GameLoopThread.java

Code: Select all

package com.example.crashtest;

import android.annotation.SuppressLint;
import android.graphics.Canvas;

public class GameLoopThread extends Thread {
	  static final long FPS = 10;
       private GameView view;
       public boolean running = false;
       public boolean pause = false;
       
       public GameLoopThread(GameView view) {
             this.view = view;
       }
       
       public void setRunning(boolean run) {
             running = run;
       }
       
       @SuppressLint("WrongCall")
       @Override
       public void run() {
    	   long ticksPS = 1000 / FPS;
           long startTime = 0;
           long sleepTime = 0;
           
             while (running) {
                    Canvas c = null;
                    startTime = System.currentTimeMillis();
                    
                    try {
                           c = view.getHolder().lockCanvas();
                           synchronized (view.getHolder()) {
                        	   view.onDraw(c);
                           }
                    } finally {
                           if (c != null) {
                                  view.getHolder().unlockCanvasAndPost(c);
                           }
                    }
                    
                    sleepTime = ticksPS-(System.currentTimeMillis() - startTime);
                    try {
                           if (sleepTime > 0)
                                  sleep(sleepTime);
                           else
                                  sleep(10);
                    } catch (Exception e) {}
             }
       }
}
Last edited by superLED on Sun Feb 02, 2014 6:17 pm, edited 1 time in total.
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re: My Android app crashes at exit (and screen rotation)

Post by superLED »

I posted the same question at stackoverflow.com, and got an answer pretty quick. Here's the answer that solved my problem:

Look what you need when you close the Activity you need to stop your thread from my code implemented before see it :

Code: Select all

GameView gameView ;
 @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        requestWindowFeature(Window.FEATURE_NO_TITLE);
        gameView = new GameView(this); 
        setContentView(gameView);
    }

 @Override
protected void onPause() {
    // TODO Auto-generated method stub
    super.onPause();
    gameView.StopView();

}
and you need to implement method called StopView() in your GameView like this

Code: Select all

 public void StopView() {

    if (gameLoopThread != null) {
        gameLoopThread.setRunning(false);

    }
}
the problem because you still call the run method in thread after you try to block the thread and so you need to stop it before to block it using join.
User avatar
0x0000000
Chaos Rift Newbie
Chaos Rift Newbie
Posts: 42
Joined: Mon Feb 11, 2013 11:46 pm
Current Project: Pokemans
Favorite Gaming Platforms: PC, Gameboy Advance SP, Mac, Xbox360
Programming Language of Choice: C/++
Location: Memory Address 0x0000000 (in UTF-9 notation)
Contact:

Re: [Solved]My Android app crashes at exit (and screen rotat

Post by 0x0000000 »

Good to hear you solved it!

Looking forward to this game of yours.
Send me a link so I can check it out, thanks!
Don't ask me about my username.
> viewtopic.php?f=4&t=8520&start=999999#p85581
User avatar
superLED
Chaos Rift Junior
Chaos Rift Junior
Posts: 303
Joined: Sun Nov 21, 2010 10:56 am
Current Project: Engine
Favorite Gaming Platforms: N64
Programming Language of Choice: C++, PHP
Location: Norway

Re: [Solved]My Android app crashes at exit (and screen rotat

Post by superLED »

0x0000000 wrote:Good to hear you solved it!

Looking forward to this game of yours.
Send me a link so I can check it out, thanks!
Check out This post to download, and read further about this project of mine :D
I would be really grateful if you'd give it a try ^^
Post Reply