我的Android应用程序在退出/第二次打开时崩溃

时间:2013-06-09 02:08:16

标签: java android crash

声明: 我2天前第一次开始为Android(手机)编程,所以我不是那么有经验。我对C ++相当不错,但我几次只触及Java。

问题: 当我在我的模拟器中运行我的游戏时,该应用程序正常工作。但是,当我按下Home按钮时,我的LogCat中通常会出现一些红线,并且在模拟器中,消息“Unfortunatly,[app name]已停止。”弹出。如果没有发生这种情况,那么当我尝试再次打开应用程序时,它就会出现。

可能有助于找到问题的一些信息: 我从这个教程开始: http://www.edu4java.com/androidgame.html 当我尝试使用onDraw函数时,我必须添加“@SuppressLint(”WrongCall“)”abow使用“onDraw”的函数。该教程没有说明任何内容,所以我有点困惑。

logcat的:

06-09 01:51:43.161: E/AndroidRuntime(23830): FATAL EXCEPTION: Thread-1173
06-09 01:51:43.161: E/AndroidRuntime(23830): java.lang.NullPointerException
06-09 01:51:43.161: E/AndroidRuntime(23830):    at com.example.braincollect.Background.onDraw(Background.java:24)
06-09 01:51:43.161: E/AndroidRuntime(23830):    at com.example.braincollect.GameView.onDraw(GameView.java:132)
06-09 01:51:43.161: E/AndroidRuntime(23830):    at com.example.braincollect.GameLoopThread.run(GameLoopThread.java:37)

Background.java代码:24:

canvas.drawBitmap(bmp, 0, 0, null);

GameView.java代码:117

introBackground.onDraw(canvas);

GameLoopThread.java代码:37:

view.getHolder().unlockCanvasAndPost(c);

我的项目中有7个java类: MainActivity(活动), GameView(视图), GameLoopThread(游戏循环), 背景图片), 脑(图像), 僵尸(图像), 计时器(只是一些数字handeling)

MainActivity.java:

package com.example.braincollect;

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:

package com.example.braincollect;

import android.annotation.SuppressLint;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Paint;
import android.media.MediaPlayer;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class GameView extends SurfaceView {

    private Bitmap bmp;
    private Bitmap bmp2;
    private Bitmap bmp3;
    private Bitmap bmp4;
    private SurfaceHolder holder;
    private GameLoopThread gameLoopThread;

    private Timer timer;

    public Background introBackground;
    public Background background;
    private Zombie zombie;
    private Brain brain;

    private int score = 0;  

    MediaPlayer mTheme;
    MediaPlayer mGameover;
    MediaPlayer mBrain;
    MediaPlayer mCollect;

    Context myContext;

    int pauseTimer;
    boolean intro = true;

    public GameView(Context context) {
        super(context);     

        myContext = context;
        gameLoopThread = new GameLoopThread(this);

        holder = getHolder();

        holder.addCallback(new SurfaceHolder.Callback() {

            @Override
            public void surfaceDestroyed(SurfaceHolder holder) {
               gameLoopThread.setRunning(false);

                mTheme.stop();

                while (gameLoopThread != null) {
                    try {
                        gameLoopThread.join();
                        gameLoopThread = null;
                    } catch (InterruptedException e) {

                    }
                }
            }

            @Override
            public void surfaceCreated(SurfaceHolder holder) {
                gameLoopThread.setRunning(true);
                gameLoopThread.start();
            }

            @Override
            public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {

            }
        });

        timer = new Timer(context);

        bmp = BitmapFactory.decodeResource(getResources(), R.drawable.zombie);
        zombie = new Zombie(this, bmp);

        bmp2 = BitmapFactory.decodeResource(getResources(), R.drawable.brain);
        brain = new Brain(this, bmp2);

        bmp3 = BitmapFactory.decodeResource(getResources(), R.drawable.background);
        background = new Background(this, bmp3);

        bmp4 = BitmapFactory.decodeResource(getResources(), R.drawable.intro);
        introBackground = new Background(this, bmp4);

        // Music
        mTheme = MediaPlayer.create(context, R.raw.theme);
        mTheme.setLooping(true);
        mTheme.setVolume(0.99f, 0.99f);

        mBrain = MediaPlayer.create(context, R.raw.brain);
        mBrain.setVolume(0.9f, 0.9f);

        mCollect = MediaPlayer.create(context, R.raw.getbrain);
        mCollect.setVolume(0.2f, 0.2f);

        mGameover = MediaPlayer.create(context, R.raw.gameover);
        mGameover.setVolume(0.2f, 0.2f);

        pauseTimer = 0;
    }

    @SuppressLint({ "WrongCall", "DrawAllocation" })
    @Override
    protected void onDraw(Canvas canvas) {
        if(intro == true) {
            introBackground.onDraw(canvas);

            Paint paint;
            paint = new Paint();
            paint.setARGB(200,  255,  0,  0);
            paint.setTextSize(30);

            if(pauseTimer >= 20) {
                canvas.drawText("Click to play!", 100,  getHeight() - 200, paint);
            }

            pauseTimer += 1;
        }

        else if(gameLoopThread.pause == false) {
            background.onDraw(canvas);

            brain.onDraw(canvas);
            zombie.onDraw(canvas);

            timer.onDraw(canvas);

            if(zombie.isWalking) {
                timer.update();
            }

            Paint paint;
            paint = new Paint();
            paint.setARGB(200,  255,  0,  0);
            paint.setTextSize(25);

            canvas.drawText(Integer.toString(score), 10,  30, paint);

            if(zombie.isCollition(brain.x,  brain.y, brain.width, brain.height)) {
                brain.changePos();

                if(zombie.isWalking) {
                    score += 1;
                    mBrain.start();
                }

                timer.reset();
            }

            if(timer.width <= 0) {
                mGameover.start();
                pauseTimer = 0;
                gameLoopThread.pause = true;
                mTheme.setVolume(0.3f, 0.3f);
            }
        } else {
            background.onDraw(canvas);

            Paint paint;
            paint = new Paint();
            paint.setARGB(200,  255,  0,  0);
            paint.setTextSize(30);

            canvas.drawText("Your Score: " + Integer.toString(score), 100,  (getHeight() / 2) - 40, paint);

            if(pauseTimer >= 20) {
                canvas.drawText("Click to play again!", 100,  getHeight() / 2, paint);
            }

            pauseTimer += 1;
        }
    }

    public boolean onTouchEvent(MotionEvent event) {
        if(event.getAction() == MotionEvent.ACTION_DOWN) {
            zombie.changeDir();
            if(intro == true && pauseTimer >= 20) {
                intro = false;
                mTheme.start();
                mCollect.start();

                pauseTimer = 0;

                gameLoopThread.pause = false;

                mTheme.setVolume(0.99f, 0.99f);
                mTheme.start();

                timer.width = timer.widthMax;
                score = 0;

                zombie.x = zombie.xStart;
                zombie.y = zombie.yStart;
                zombie.isWalking = false;
                zombie.xSpeed = 1;
                zombie.ySpeed = 0;
                zombie.currentFrame = 0;

                brain.changePos();
            }

            if(gameLoopThread.pause == true && pauseTimer >= 20) {
                pauseTimer = 0;

                gameLoopThread.pause = false;

                mTheme.setVolume(0.99f, 0.99f);
                mTheme.start();

                mCollect.start();

                timer.width = timer.widthMax;
                score = 0;

                zombie.x = zombie.xStart;
                zombie.y = zombie.yStart;
                zombie.isWalking = false;
                zombie.xSpeed = 1;
                zombie.ySpeed = 0;
                zombie.currentFrame = 0;

                brain.changePos();
            }
        }

        return super.onTouchEvent(event);
    }
}

(“bmp”名称只是暂时的,所有声音都不是MediaPlayer对象)

GameLoopThread.java:

package com.example.appname;

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;
           long sleepTime;

             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) {}
             }
       }
}

如果您需要查看更多代码,请告诉我们。我不知道故障在哪里。

2 个答案:

答案 0 :(得分:1)

我很确定该视图将等于null传递给GameLoopThread构造函数,因此当您调用setRunning(true)时,此行将抛出NPE:

c = view.getHolder().lockCanvas();

您应该通过调用GameLoopThread(view)发布其他代码片段,以便更好地了解问题。

祝你好运

答案 1 :(得分:0)

这很简单,在Grass.java文件的第24行,您有一个NullPointerException,因此使用断点和Debug模式(而不是Run)可以轻松检查该行的值,并查看哪些变量可能为null,并在该行之前放置一个空检查器或捕获异常:

1

if(canvas != null) {

...

}

2

try {

...

} catch (NullPointerException e) {

....
}