Android的onResume()方法没有被调用

7

我一直在使用Java开发一个适用于Android的游戏引擎。不幸的是,我的onResume()方法似乎没有被调用。我正在使用线程来运行所有内容,当我最小化应用程序然后再次打开应用程序时,它只会给我一个空白的黑屏。但是当我关闭屏幕再次打开时,它确实可以工作。

这是我用于活动的代码:

 package org.simplecorporation.myengine.core.android;

 import org.simplecorporation.myengine.core.Settings;
 import org.simplecorporation.myengine.core.android.input.AndroidInput;
 import org.simplecorporation.myengine.core.game.BaseGame;

 import android.app.Activity;
 import android.content.pm.ActivityInfo;
 import android.os.Bundle;
 import android.view.MotionEvent;
 import android.view.Window;
 import android.view.WindowManager;

 public abstract class AndroidActivity extends Activity {

/* The abstract methods*/
public abstract void activityCreated();
public abstract void activityPaused();
public abstract void activityResumed();
public abstract void activityStopped();
public abstract void activityRestarted();
public abstract void activityDestroy();

/* The android display */
public AndroidDisplay androidDisplay;

/* The onCreate method */
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Set the title
    this.setTitle(Settings.Window.Title);
    //Check the orientation and set it
    if (AndroidSettings.ScreenOrientation == AndroidSettings.SCREEN_ORIENTATION_PORTRAIT)
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    else if (AndroidSettings.ScreenOrientation == AndroidSettings.SCREEN_ORIENTATION_LANDSCAPE)
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    //Check if the activity should be fullscreen
    if (Settings.Window.Fullscreen) {
        //Get rid of the title bar
        this.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        //Make the activity fullscreen
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN , WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
}

/* The onCreate method */
protected void onCreate(BaseGame androidGame , Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    //Set the title
    this.setTitle(Settings.Window.Title);
    //Check the orientation and set it
    if (AndroidSettings.ScreenOrientation == AndroidSettings.SCREEN_ORIENTATION_PORTRAIT)
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
    else if (AndroidSettings.ScreenOrientation == AndroidSettings.SCREEN_ORIENTATION_LANDSCAPE)
        this.setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
    //Check if the activity should be fullscreen
    if (Settings.Window.Fullscreen) {
        //Get rid of the title bar
        this.getWindow().requestFeature(Window.FEATURE_NO_TITLE);
        //Make the activity fullscreen
        this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN , WindowManager.LayoutParams.FLAG_FULLSCREEN);
    }
    //Create the display
    androidDisplay = new AndroidDisplay(this , androidGame);
    //Set the content view
    this.setContentView(androidDisplay);
    //Call the activity create method
    this.activityCreated();
}

/* Called when the activity is paused */
public void onPause() {
    super.onPause();
    //Pause the thread
    this.androidDisplay.androidGameThread.paused = true;
    //Call the method
    this.activityPaused();
}

/* Called when the activity is resumed */
public void onResume() {
    super.onResume();
    //Resume the thread
    this.androidDisplay.androidGameThread.paused = false;
    //Call the method
    this.activityResumed();
}

/* Called when the activity is stopped */
public void onStop() {
    super.onStop();
    //Call the method
    this.activityStopped();
}

/* Called when the activity is restarted */
public void onRestart() {
    super.onRestart();
    //Call the method
    this.activityRestarted();
}

/* Called when the activity is destroyed */
public void onDestroy() {
    super.onDestroy();
    //Call the method
    this.activityDestroy();
    //Destroy
    this.finish();
}
 }

The code that I am using for the thread:

package org.simplecorporation.myengine.core.android;

import org.simplecorporation.myengine.core.game.BaseGame;
import org.simplecorporation.myengine.core.input.InputManager;

import android.util.Log;
import android.view.SurfaceHolder;

public class AndroidGameThread extends Thread {

/* Is the thread running */
public boolean running;

/* Is the thread paused */
public boolean paused;

/* The surface holder */
public SurfaceHolder surfaceHolder;

/* The android game */
public BaseGame androidGame;

/* The constructor */
public AndroidGameThread(SurfaceHolder surfaceHolder , BaseGame androidGame) {
    //Set running to false
    this.running = false;
    //Set paused to false
    this.paused = false;
    //Assign the surface holder
    this.surfaceHolder = surfaceHolder;
    //Assign the android game
    this.androidGame = androidGame;
}

/* The method to set the running variable */
public void setRunning(boolean running) {
    this.running = running;
}

/* Returns whether the thread is running */
public boolean isRunning() {
    return this.running;
}

/* The run method */
public void run() {
    //Start the game
    this.androidGame.create();
    //Run while the variable running is true
    while (running) {
        //Check if the thread is paused
        if (! this.paused) {
            //Check the input
            InputManager.checkInput();
            //Set the game canvas to null
            AndroidStore.gameCanvas = null;
            //Try statement
            try {
                //Set the game canvas
                AndroidStore.gameCanvas = this.surfaceHolder.lockCanvas();
                synchronized (this.surfaceHolder) {
                    //Update/Render the game
                    this.androidGame.tick();
                }
            } finally {
                //Check that the canvas isn't null
                if (AndroidStore.gameCanvas != null) {
                    this.surfaceHolder.unlockCanvasAndPost(AndroidStore.gameCanvas);
                }
            }
        }
    }
}

}

此外,我使用以下代码启动线程:

import org.simplecorporation.myengine.core.Settings;
import org.simplecorporation.myengine.core.game.BaseGame;
import org.simplecorporation.myengine.core.input.InputManager;
import org.simplecorporation.myengine.utils.ScreenUtils;

import android.app.Activity;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class AndroidDisplay extends SurfaceView implements SurfaceHolder.Callback {

/* The android game */
public BaseGame androidGame;

/* The android game thread */
public AndroidGameThread androidGameThread;

/* The constructor */
public AndroidDisplay(Activity gameActivity , BaseGame androidGame) {
    //Call the super constructor
    super(gameActivity);

    //Add the callback
    this.getHolder().addCallback(this);

    //Set the game activity in the AndroidStore
    AndroidStore.gameActivity = gameActivity;

    //Set the android game
    this.androidGame = androidGame;

    //Create the android game thread
    this.androidGameThread = new AndroidGameThread(this.getHolder(), this.androidGame);

    //Set the surface view focusable
    this.setFocusable(true);
}

/* Called when the surface is created */
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    //Create the input
    InputManager.create();
    //Set the size of the screen in the settings if full screen
    if (Settings.Window.Fullscreen) {
        Settings.Window.Size.Width = ScreenUtils.getScreenWidth();
        Settings.Window.Size.Height = ScreenUtils.getScreenHeight();
    } else {
        //Set the size of the screen in the settings
        Settings.Window.Size.Width = this.getWidth();
        Settings.Window.Size.Height = this.getHeight();
    }
    //Set the game resources
    AndroidStore.gameResources = this.getResources();
    //Create the game
    this.androidGame.gameCreated();
    //Create the paint object
    AndroidStore.gamePaint = new Paint();
    //Start the android game thread
    this.androidGameThread.setRunning(true);
    this.androidGameThread.start();
}

/* Called when the surface is changed */
public void surfaceChanged(SurfaceHolder surfaceHolder , int format , int width , int height) {
    //Set the size of the screen in the settings
    Settings.Window.Size.Width = ScreenUtils.getScreenWidth();
    Settings.Window.Size.Height = ScreenUtils.getScreenHeight();
}

/* Called when the surface is destroyed */
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    //Should the loop continue
    boolean retry = true;
    while(retry) {
        //Try and catch statement
        try {
            //Stop the game
            this.androidGame.gameStopped();
            //Close the game
            this.androidGame.gameClosing();
            //Join the thread
            this.androidGameThread.join();
            //Stop the while loop
            retry = false;
        } catch (InterruptedException e) {

        }
    }
}

}

为了运行这一切,我有一个类,它“扩展”了AndroidActvity并使用以下方法:
protected void onCreate(Bundle savedInstanceState) {
    Settings.Window.Title = "MyEngine Android Tests";
    Settings.Android = true;
    Settings.Video.OpenGL = false;
    Settings.Audio.SoundEffectVolume = 10;
    AndroidSettings.ScreenOrientation = 1;
    Settings.Window.Fullscreen = true;
    this.onCreate(new FileTest() ,  savedInstanceState);
}

测试类:

import org.simplecorporation.myengine.core.Settings;
import org.simplecorporation.myengine.core.android.AndroidActivity;
import org.simplecorporation.myengine.core.android.AndroidSettings;

import android.os.Bundle;
import android.util.Log;

public class MainActivity extends AndroidActivity {

protected void onCreate(Bundle savedInstanceState) {
    Settings.Window.Title = "MyEngine Android Tests";
    Settings.Android = true;
    Settings.Video.OpenGL = false;
    Settings.Audio.SoundEffectVolume = 10;
    AndroidSettings.ScreenOrientation = 1;
    Settings.Window.Fullscreen = true;
    this.onCreate(new FileTest() ,  savedInstanceState);
}

@Override
public void activityCreated() {
    // TODO Auto-generated method stub

}

@Override
public void activityPaused() {
    // TODO Auto-generated method stub
    Log.d("HELLO", "I HAVE BEEN PAUSED");
}

@Override
public void activityResumed() {
    // TODO Auto-generated method stub
    Log.d("HELLO", "I HAVE BEEN RESUMED");
}

@Override
public void activityStopped() {
    // TODO Auto-generated method stub
    Log.d("HELLO", "I HAVE BEEN STOPPED");
}

@Override
public void activityRestarted() {
    // TODO Auto-generated method stub
    Log.d("HELLO", "I HAVE BEEN RESTARTED");
}

@Override
public void activityDestroy() {
    // TODO Auto-generated method stub
    Log.d("HELLO", "I HAVE BEEN DESTROYED");
}

}

文件测试:

package com.simplecorporation.myengine.android.tests;

import java.util.List;

import org.simplecorporation.myengine.core.Settings;
import org.simplecorporation.myengine.core.audio.clip.AndroidAudio;
import org.simplecorporation.myengine.core.game.BaseGame;
import org.simplecorporation.myengine.core.game2d.entity.ImageEntity2D;
import org.simplecorporation.myengine.core.gui.GUIButton;
import org.simplecorporation.myengine.core.gui.GUICheckBox;
import org.simplecorporation.myengine.core.gui.GUIRenderer;
import org.simplecorporation.myengine.core.gui.GUIScrollBar;
import org.simplecorporation.myengine.core.gui.GUISlider;
import org.simplecorporation.myengine.core.gui.GUITextDisplayArea;
import org.simplecorporation.myengine.core.gui.font.GUIFont;
import org.simplecorporation.myengine.core.gui.font.bitmap.BitmapFont;
import org.simplecorporation.myengine.core.image.Image;
import org.simplecorporation.myengine.core.input.event.TouchEvent;
import org.simplecorporation.myengine.core.render.basic.BasicRenderer;
import org.simplecorporation.myengine.core.render.colour.Colour;
import org.simplecorporation.myengine.utils.AndroidFileUtils;
import org.simplecorporation.myengine.utils.ArrayUtils;
import org.simplecorporation.myengine.utils.FileUtils;
import org.simplecorporation.myengine.utils.font.FontUtils;

import android.os.Environment;
import android.util.Log;

public class FileTest extends BaseGame {

public ImageEntity2D image;
public Colour colour;
public GUIButton button;
public GUICheckBox checkBox;
public AndroidAudio audio;
public GUIFont bitmapFont;
public GUIScrollBar scrollBar;

public GUIScrollBar verticalslider;
public GUIScrollBar horizontalslider;
public GUITextDisplayArea textDisplayArea;

public FileTest() {
    createGame();
}

@Override
public void gameCreated() {
    // TODO Auto-generated method stub
    image = new ImageEntity2D(new Image(R.drawable.menubutton));
    image.position.x = 200;
    image.position.y = 200;
    image.width = 200;
    image.height = 60;
    image.rotationVelocity = 1;
    colour = new Colour(0d, 0d, 0d, 1d);
    button = new GUIButton("AndroidGUIButton" , "Click Me" , new GUIRenderer(new Colour[] {
            Colour.LIGHT_BLUE , Colour.ORANGE , Colour.BLUE
    } , FontUtils.buildGUIFont("Arial" , Colour.WHITE , 46f)));
    button.position.x = 300;
    button.position.y = 200;
    button.width = 300;
    button.height = 60;
    button.visible = true;

    checkBox = new GUICheckBox("AndroidCheckBox" , new GUIRenderer(new Colour[] { Colour.WHITE , Colour.BLUE }));
    checkBox.position.x = 500;
    checkBox.position.y = 300;
    checkBox.width = 100;
    checkBox.height = 100;
    checkBox.visible = true;

    bitmapFont = new GUIFont(new BitmapFont(new Image(R.drawable.test) , 40, 16));

    GUIButton verticalsliderButton = new GUIButton("Button2" , "" , new GUIRenderer(new Colour[] {
            Colour.ORANGE ,
            Colour.LIGHT_BLUE ,
            Colour.BLUE
    } , FontUtils.buildGUIFont("Segoe UI" , Colour.WHITE , 20f)));
    verticalsliderButton.width = 100;
    verticalsliderButton.height = 20;
    verticalsliderButton.visible = true;

    verticalslider = new GUIScrollBar("Slider1" , verticalsliderButton , GUISlider.DIRECTION_VERTICAL , 1, new GUIRenderer(new Colour[] { Colour.RED }));

    verticalslider.visible = true;
    verticalslider.position.x = 200;
    verticalslider.position.y = 200;
    verticalslider.width = 30;
    verticalslider.height = 100;

    GUIButton horizontalsliderButton = new GUIButton("Button2" , "" , new GUIRenderer(new Colour[] {
            Colour.ORANGE ,
            Colour.LIGHT_BLUE ,
            Colour.BLUE
    } , FontUtils.buildGUIFont("Segoe UI" , Colour.WHITE , 20f)));
    horizontalsliderButton.width = 20;
    horizontalsliderButton.height = 100;
    horizontalsliderButton.visible = true;

    horizontalslider = new GUIScrollBar("Slider2" , horizontalsliderButton , GUISlider.DIRECTION_HORIZONTAL , 1, new GUIRenderer(new Colour[] { Colour.RED }));

    horizontalslider.visible = true;
    horizontalslider.position.x = 300;
    horizontalslider.position.y = 300;
    horizontalslider.width = 100;
    horizontalslider.height = 30;

    audio = new AndroidAudio(R.raw.encode , false , false);

    List<String> text = ArrayUtils.toStringList(new String[] {
            "Hello, this test application was made using MyEngine " + Settings.EngineVersion,
            "with the build " + Settings.EngineBuild + ". Below this message you should find",
            "a bitmap font:"
    });
    this.textDisplayArea = new GUITextDisplayArea("TextArea", text, FontUtils.buildGUIFont("Arial" , Colour.WHITE , 40f), Settings.Window.Size.Width);
    this.textDisplayArea.position.x = 0;
    this.textDisplayArea.position.y = 500;
    this.textDisplayArea.visible = true;

    AndroidFileUtils.writeToInternalStorage("hello.txt", ArrayUtils.toStringList(new String[] {
            "Hello World, From hello.txt"
    }));
    this.textDisplayArea.setText(AndroidFileUtils.readFromInternalStorage("hello.txt"));

    AndroidFileUtils.writeToExternalStorage("hello.txt", ArrayUtils.toStringList(new String[] {
            "Hello World, From hello.txt in an External Storage file :)"
    }));

    this.textDisplayArea.setText(FileUtils.read("eclipse.txt", false));

    Log.d("HELLO", "" + AndroidFileUtils.isExternalStorageWritable() + " " + Environment.getExternalStorageDirectory());
}

public void gameRender() {
    BasicRenderer.setColour(colour);
    BasicRenderer.renderFilledRectangle(0 , 0 , Settings.Window.Size.Width , Settings.Window.Size.Height);
    BasicRenderer.setColour(Colour.BLUE);
    BasicRenderer.renderFilledRectangle(100 , 100 , 100 , 100);
    BasicRenderer.setColour(Colour.WHITE);
    verticalslider.render();
    horizontalslider.render();
    image.render();
    button.render();
    checkBox.render();
    textDisplayArea.render();
    BasicRenderer.setColour(Colour.WHITE);
    bitmapFont.render("This is a bitmap font :)" , 10 , 700);
}

public void gameUpdate() {
    button.update();
    checkBox.update();
    image.update();
    verticalslider.update();
    horizontalslider.update();
    if (button.clicked) {
        colour = new Colour(0d , 0d , 0d , 1d);
        audio.play();
    }
    textDisplayArea.update();
}

public void onTouch(TouchEvent e) {
    this.colour = new Colour(this.colour.getR() + 0.01, this.colour.getG() + 0.01, this.colour.getB() + 0.01);
}

}

非常感谢您提前的支持。

是的,在 AndroidDisplay 类中,我使用了 this.androidGameThread.setRunning(true); this.androidGameThread.start(); - 2851999
我已经尝试在那里放置日志,所以我认为它没有被调用。 - 2851999
还有,您能解释一下Activity的onCreate()方法的重载吗?如果我错了,请纠正我。我认为当Activity被创建时,会调用Activity.onCreate(Bundle bun)方法。而且这个方法不会创建任何线程。 - vivek
我有两个方法,一个是onCreate(Bundle savedInstanceState),另一个是onCreate(BaseGame androidGame, Bundle savedInstanceState)。我有一个类继承了上面展示的AndroidActivity,并且Android会调用onCreate(Bundle savedInstanceState)方法。在这个被覆盖的方法中,我调用另一个方法并将BaseGame的实例传递给它,从而调用另一个方法。因此,在我所做的测试中,我在被覆盖的onCreate(Bundle savedInstanceState)方法中使用以下代码:this.onCreate(new FileTest() , savedInstanceState); - 2851999
你能添加你的测试类的完整代码吗? - vivek
显示剩余5条评论
3个回答

4
谢谢大家 :) 我花了一整天的时间来解决这个问题,现在终于把它解决了。
我找到了Android onResume not called这篇文章,然后我添加了一些Log.d()的调用来尝试弄清楚发生了什么。通过在AndroidDisplay和AndroidActivity中的每个方法中添加它们,我注意到当我关闭和打开屏幕时,我得到了“ACTIVITY PAUSED”、“ACTIVITY STOPPED”、“ACTIVITY RESTARTED”和“ACTIVITY RESUMED”的输出,这正是我所期望的。然后,当我点击菜单按钮时,会有一个额外的输出,“SURFACE DESTROYED”,所以我改变了AndroidDisplay,停止线程在surface被销毁时停止,所以我将那段代码移动到一个名为stopThread()的方法中,然后我发现由于AndroidDisplay中的surfaceCreated()方法,我重复创建了相同的线程,所以我在调用androidGameThread.start()之前做了一个if语句,使用了androidGameThread.isAlive(),从而解决了这个问题。
新的AndroidDisplay代码:
package org.simplecorporation.myengine.core.android;

import org.simplecorporation.myengine.core.Settings;
import org.simplecorporation.myengine.core.game.BaseGame;
import org.simplecorporation.myengine.core.input.InputManager;
import org.simplecorporation.myengine.utils.ScreenUtils;

import android.app.Activity;
import android.graphics.Paint;
import android.view.SurfaceHolder;
import android.view.SurfaceView;

public class AndroidDisplay extends SurfaceView implements SurfaceHolder.Callback {

/* The android game */
public BaseGame androidGame;

/* The android game thread */
public AndroidGameThread androidGameThread;

/* The boolean that states whether this has been created */
public boolean created;

/* The constructor */
public AndroidDisplay(Activity gameActivity , BaseGame androidGame) {
    //Call the super constructor
    super(gameActivity);

    //Add the callback
    this.getHolder().addCallback(this);

    //Set the game activity in the AndroidStore
    AndroidStore.gameActivity = gameActivity;

    //Set the android game
    this.androidGame = androidGame;

    //Create the android game thread
    this.androidGameThread = new AndroidGameThread(this.getHolder(), this.androidGame, this);

    //Set created to false
    this.created = false;

    //Set the surface view focusable
    this.setFocusable(true);
}

/* Called when the surface is created */
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    //Set created to true
    this.created = true;
    //Create the input
    InputManager.create();
    //Set the size of the screen in the settings if full screen
    if (Settings.Window.Fullscreen) {
        Settings.Window.Size.Width = ScreenUtils.getScreenWidth();
        Settings.Window.Size.Height = ScreenUtils.getScreenHeight();
    } else {
        //Set the size of the screen in the settings
        Settings.Window.Size.Width = this.getWidth();
        Settings.Window.Size.Height = this.getHeight();
    }
    //Set the game resources
    AndroidStore.gameResources = this.getResources();
    //Create the game
    this.androidGame.gameCreated();
    //Create the paint object
    AndroidStore.gamePaint = new Paint();
    //Start the android game thread if it has not already started
    this.androidGameThread.setRunning(true);
    if (! this.androidGameThread.isAlive())
        this.androidGameThread.start();
}

/* Called when the surface is changed */
public void surfaceChanged(SurfaceHolder surfaceHolder , int format , int width , int height) {
    //Set the size of the screen in the settings
    Settings.Window.Size.Width = ScreenUtils.getScreenWidth();
    Settings.Window.Size.Height = ScreenUtils.getScreenHeight();
    //Reassign the surface holder
    this.androidGameThread.surfaceHolder = surfaceHolder;
}

/* Called when the surface is destroyed */
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    //Set created to false
    this.created = false;
}

/* The method used to stop the thread */
public void stopThread() {
    //Should the loop continue
    boolean retry = true;
    while(retry) {
        //Try and catch statement
        try {
            //Stop the game
            this.androidGame.gameStopped();
            //Close the game
            this.androidGame.gameClosing();
            //Join the thread
            this.androidGameThread.join();
            //Stop the while loop
            retry = false;
        } catch (InterruptedException e) {

        }
    }
}

}

1
在 Manifest 文件中,将此代码用于启动器活动:

android:noHistory="false"

0
可能的问题可能是Activity.onCreate()方法的方法重载。
 protected void onCreate(Bundle savedInstanceState) 

这个方法(在活动创建时调用)不会创建任何线程。

我不知道下面的方法是否会在活动创建时被调用。

 protected void onCreate(BaseGame androidGame , Bundle savedInstanceState)

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接