getHolder().lockCanvas() always returns null after resuming

Put problem concerning Views, Layouts and other XML-Resources (like AndroidManifest) here.

getHolder().lockCanvas() always returns null after resuming

Postby andreleitao » Tue Mar 10, 2009 10:20 pm

Hi, folks! :)

I'm with a boring problem :?
I'm making a little game renderer. I'll present you my two main classes.

At first, the main activity:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.  
  3.  
  4. public class MainActivity extends Activity implements Runnable{
  5.  
  6.  
  7.  
  8.         public static MainActivity instance;
  9.  
  10.         public boolean isPaused;
  11.  
  12.         private int fps;
  13.  
  14.        
  15.  
  16.         public int MAX_GAME_FPS;
  17.  
  18.         public int GAME_DELAY;
  19.  
  20.  
  21.  
  22.         private Thread thread;
  23.  
  24.         private boolean mainThreadAlive;
  25.  
  26.  
  27.  
  28.         public EssentialSurface mSurface;
  29.  
  30.         Screen mSurfaceScreen;
  31.  
  32.  
  33.  
  34.         /** Called when the activity is first created. */
  35.  
  36.         @Override
  37.  
  38.         public void onCreate(Bundle savedInstanceState) {
  39.  
  40.                 super.onCreate(savedInstanceState);
  41.  
  42.                 if(instance == null){
  43.  
  44.                         MAX_GAME_FPS = 20;
  45.  
  46.                         GAME_DELAY = (1000 / MAX_GAME_FPS);
  47.  
  48.                         //String s = R.string.
  49.  
  50.                         instance = this;
  51.  
  52.                         isPaused = false;
  53.  
  54.                         instance.mContext = this;
  55.  
  56.                        
  57.  
  58.                 }
  59.  
  60.                        activateGamePlayMode();
  61.  
  62.         }
  63.  
  64.        
  65.  
  66.         private void activateGamePlayMode(){
  67.  
  68.                 setContentView(R.layout.main);
  69.  
  70.                 mSurface = (EssentialSurface) findViewById(R.id.gamex);
  71.  
  72.                 instance.startThread();        
  73.  
  74.         }
  75.  
  76.        
  77.  
  78.         //please ignore this method <img src="http://www.anddev.org/images/smilies/smile.png" alt=":)" title="Smile" />
  79.  
  80.         public void changeScreen(int screenID){        
  81.  
  82.                 instance.mSurfaceScreen = ScreenManager.getScreen(screenID);
  83.  
  84.         }
  85.  
  86.        
  87.  
  88.  
  89.  
  90.         /* ************************* PAUSE ******************
  91.  
  92.          ****************************************************/
  93.  
  94.         @Override
  95.  
  96.         protected void onPause() {
  97.  
  98.                 super.onPause();
  99.  
  100.                 this.processPause();
  101.  
  102.                 instance.mSurface.mPaused = true;
  103.  
  104.         }
  105.  
  106.  
  107.  
  108.         public synchronized void processPause() {
  109.  
  110.                 if (instance.isPaused == false) {
  111.  
  112.                         instance.isPaused = true;
  113.  
  114.                         instance.stopThread();
  115.  
  116.                 }
  117.  
  118.         }
  119.  
  120.  
  121.  
  122.  
  123.  
  124.         /* ************************* RESUME ******************
  125.  
  126.          ****************************************************/
  127.  
  128.         @Override
  129.  
  130.         protected void onResume() {
  131.  
  132.                 super.onResume();
  133.  
  134.                 processResume();
  135.  
  136.         }
  137.  
  138.  
  139.  
  140.        
  141.  
  142.         public void processResume() {
  143.  
  144.                 if (instance.isPaused == true) {
  145.  
  146.                         instance.isPaused = false;
  147.  
  148.                         instance.startThread();
  149.  
  150.                 }
  151.  
  152.         }
  153.  
  154.         @Override
  155.  
  156.         protected void onStop() {
  157.  
  158.                 super.onStop();
  159.  
  160.                 processPause();
  161.  
  162.         }
  163.  
  164.  
  165.  
  166.  
  167.  
  168.  
  169.  
  170.  
  171.  
  172.         /* ************************* DESTROY ********************
  173.  
  174.          ****************************************************/
  175.  
  176.  
  177.  
  178.  
  179.  
  180.         @Override
  181.  
  182.         protected void onDestroy() {
  183.  
  184.                 super.onDestroy();
  185.  
  186.                 instance.stopThread();
  187.  
  188.         }
  189.  
  190.  
  191.  
  192.         private void stopThread() {
  193.  
  194.                 instance.mainThreadAlive = false;
  195.  
  196.         }
  197.  
  198.  
  199.  
  200.  
  201.  
  202.         /* ************************* RUN ********************
  203.  
  204.          ****************************************************/
  205.  
  206.  
  207.  
  208.         public void run() {
  209.  
  210.  
  211.  
  212.                 while (instance.mainThreadAlive) {
  213.  
  214.                        
  215.  
  216.                         try {
  217.  
  218.                                 long initialTime = System.currentTimeMillis();
  219.  
  220.                                 instance.mSurface.gameLoop();
  221.  
  222.  
  223.  
  224.                         }catch (Exception e) {
  225.  
  226.                                 e.printStackTrace();                           
  227.  
  228.                         }
  229.  
  230.                        
  231.  
  232.                 }
  233.  
  234.         }
  235.  
  236.  
  237.  
  238.         private void startThread(){
  239.  
  240.                 while (instance.thread != null && !instance.mainThreadAlive && instance.thread.isAlive()) {
  241.  
  242.                         try {
  243.  
  244.                                 Thread.sleep(GAME_DELAY);
  245.  
  246.                         } catch (Exception e) {
  247.  
  248.                                 e.printStackTrace();
  249.  
  250.                         }
  251.  
  252.                 }
  253.  
  254.                 instance.thread = new Thread(instance);
  255.  
  256.                 instance.mainThreadAlive = true;
  257.  
  258.                 instance.thread.start();
  259.  
  260.         }
  261.  
  262. }
  263.  
  264.  
Parsed in 0.041 seconds, using GeSHi 1.0.8.4


As we know, the run() method has the main loop of the application.

This is my second class:

Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2. public class EssentialSurface extends SurfaceView implements SurfaceHolder.Callback{
  3.  
  4.  
  5.  
  6.         //TODO: isso ta com dias contados ou não?
  7.  
  8.         //private TextView mStatusText;
  9.  
  10.         //      private Screen mScreen;
  11.  
  12.  
  13.  
  14.         boolean mPressing;
  15.  
  16.         boolean mPaused;
  17.  
  18.  
  19.  
  20.         public Canvas canvas;
  21.  
  22.  
  23.  
  24.         public EssentialSurface(Context context, AttributeSet attrs) {
  25.  
  26.                 super(context, attrs);
  27.  
  28.                 setFocusable(true); // make sure we get key events
  29.  
  30.                 setHorizontalScrollBarEnabled(true);
  31.  
  32.                 setHorizontalFadingEdgeEnabled(true);
  33.  
  34.                 instance.mSurfaceScreen = ScreenManager.getScreen(ScreenManager.MTM_LOGO);//ignore this
  35.  
  36.                 getHolder().addCallback(this);
  37.  
  38.         }
  39.  
  40.  
  41.  
  42.         ///////////////////// LOOK AT THIS METHOD ////////////////////////////////
  43.  
  44.         public void gameLoop() {
  45.  
  46.                 ///////////////////// getHolder().lockCanvas()   IS THE PROBLEM.////////////////
  47.  
  48.                 canvas = getHolder().lockCanvas(null);
  49.  
  50.  
  51.  
  52.                 update();                      
  53.  
  54.                 if(canvas!=null)
  55.  
  56.                 {
  57.  
  58.                         draw(canvas);          
  59.  
  60.                         getHolder().unlockCanvasAndPost(canvas);
  61.  
  62.                 }
  63.  
  64.  
  65.  
  66.         }
  67.  
  68.        
  69.  
  70.         public void surfaceChanged(SurfaceHolder holder, int format, int width,
  71.  
  72.                         int height)
  73.  
  74.         {
  75.  
  76.                 instance.mSurfaceScreen.setSurfaceSize(width, height);
  77.  
  78.         }
  79.  
  80.  
  81.  
  82.         public void surfaceCreated(SurfaceHolder holder) {
  83.  
  84.  
  85.  
  86.         }
  87.  
  88.  
  89.  
  90.         public void surfaceDestroyed(SurfaceHolder holder) {
  91.  
  92.  
  93.  
  94.         }
  95.  
  96.  
  97.  
  98.         @Override
  99.  
  100.         public boolean onKeyDown(int keyCode, KeyEvent msg) {
  101.  
  102.                 //instance.setContentView(R.layout.novo);
  103.  
  104.                 return instance.mSurfaceScreen.doKeyDown(keyCode, msg);
  105.  
  106.         }
  107.  
  108.  
  109.  
  110.         @Override
  111.  
  112.         public boolean onKeyUp(int keyCode, KeyEvent msg) {
  113.  
  114.                 mPaused = false;
  115.  
  116.                 return instance.mSurfaceScreen.doKeyUp(keyCode, msg);
  117.  
  118.         }
  119.  
  120.  
  121.  
  122.         public void update(){
  123.  
  124.                 instance.mSurfaceScreen.update();
  125.  
  126.         }
  127.  
  128.  
  129.  
  130.         @Override
  131.  
  132.         public void draw(Canvas canvas) {
  133.  
  134.                 //Log.d("MAINACTIVITY","DEU DRAW COM CANVAS!!!!!!!");
  135.  
  136.                 //if(!mPaused){
  137.  
  138.                 Paint p = new Paint();
  139.  
  140.                 p.setColor(Color.RED);
  141.  
  142.                 instance.mSurfaceScreen.draw(canvas);
  143.  
  144.                 canvas.drawText("FPS: " + instance.getFPS(), 20, 20, p);
  145.  
  146.                 //button.draw(canvas);
  147.  
  148.                 //}
  149.  
  150.  
  151.  
  152.         }
  153.  
  154.  
  155.  
  156.         @Override
  157.  
  158.         public boolean onTouchEvent(MotionEvent event) {
  159.  
  160.                 return instance.mSurfaceScreen.onTouchEvent(event);
  161.  
  162.         }
  163.  
  164.  
  165.  
  166.         @Override
  167.  
  168.         public void onWindowFocusChanged(boolean hasWindowFocus) {
  169.  
  170.  
  171.  
  172.         }
  173.  
  174.  
  175.  
  176.         public Screen getScreen(){
  177.  
  178.                 return instance.mSurfaceScreen;
  179.  
  180.         }
  181.  
  182.  
  183.  
  184.  
  185.  
  186.  
  187.  
  188. }
  189.  
  190.  
  191.  
  192.  
Parsed in 0.039 seconds, using GeSHi 1.0.8.4


When the application runs for the first time, every things works fine. But when I press the Emulator HOME or BACK button and back to the application the problem appears :( : getHolder().lockCanvas(null) always returns null. What Android documentation says about this in SurfaceHolder's page is "A null is returned if the surface has not been created or otherwise can not be edited". When I back to the application the surface is still alive, I don't know what is happening.

Well, I have no more imagination to solve this for today (two days working hardly).
Can anyone help me?

Thanks in advance.

André :)
andreleitao
Experienced Developer
Experienced Developer
 
Posts: 70
Joined: Tue Mar 10, 2009 9:56 pm
Location: Recife - Brazil

Top

Postby MrSnowflake » Tue Mar 10, 2009 11:21 pm

You should recreate the Surface and also you should only start rendering when surfaceCreated() got called!
User avatar
MrSnowflake
Moderator
Moderator
 
Posts: 1439
Joined: Sat Feb 16, 2008 3:11 pm
Location: Flanders, Belgium

Postby andreleitao » Tue Mar 10, 2009 11:50 pm

Hi!

You mean instantiate the surface again inside MainActivity class? You also said for start rendering only when surfaceCreated() is called, right? You recommend I do something like that?


Syntax: [ Download ] [ Hide ]
Using java Syntax Highlighting
  1.  
  2.  
  3.  
  4. //atribute
  5.  
  6.    private void surfaceCalled;
  7.  
  8. //atribute
  9.  
  10. //...
  11.  
  12. public void surfaceCreated(SurfaceHolder holder) {
  13.  
  14.      surfaceCalled = true;
  15.  
  16.  }
  17.  
  18.  
  19.  
  20. //...
  21.  
  22.    public void gameLoop() {
  23.  
  24.           if(surfaceCalled)
  25.  
  26.              canvas = getHolder().lockCanvas(null);
  27.  
  28.  
  29.  
  30.           update();          
  31.  
  32.           if(canvas!=null)
  33.  
  34.           {
  35.  
  36.                draw(canvas);      
  37.  
  38.                getHolder().unlockCanvasAndPost(canvas);
  39.  
  40.           }
  41.  
  42.  
  43.  
  44.      }
  45.  
  46.  
  47.  
  48.  
Parsed in 0.036 seconds, using GeSHi 1.0.8.4
andreleitao
Experienced Developer
Experienced Developer
 
Posts: 70
Joined: Tue Mar 10, 2009 9:56 pm
Location: Recife - Brazil

Postby MrSnowflake » Wed Mar 11, 2009 12:14 am

Look at LunarLander demo, I believe they handle the life cycle correctly.
User avatar
MrSnowflake
Moderator
Moderator
 
Posts: 1439
Joined: Sat Feb 16, 2008 3:11 pm
Location: Flanders, Belgium

Postby andreleitao » Wed Mar 11, 2009 3:06 am

LunarLander crashes after pressing HOME button and return to the application :D
andreleitao
Experienced Developer
Experienced Developer
 
Posts: 70
Joined: Tue Mar 10, 2009 9:56 pm
Location: Recife - Brazil

Top

Return to View, Layout & Resource Problems

Who is online

Users browsing this forum: No registered users and 5 guests