This is the main Activity of my app. The one holding a CupView.

package my.package;


import my.package.CupView.CupThread;
import org.openintents.hardware.SensorManagerSimulator;
import org.openintents.provider.Hardware;

import android.app.Activity;
import android.content.Intent;
import android.hardware.SensorListener;
import android.hardware.SensorManager;
import android.os.Bundle;
import android.util.Log;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

public class MyActivity extends Activity {

        private static final int MENU_NEWGAME = 1;
        private static final int MENU_RESUMEGAME = 2;
        private static final int MENU_EXITGAME = 3;
        private static final int ROLL_DICE_ACTIVITY = 1;
        /** The modes the game can be in **/
        private static final int ENTER = 1; // just entered the game
        private static final int IN_PROGRESS = 2; // less than 13 turns
        private static final int GAME_OVER = 3; // 13 turns has been reached
        private int mMode;
        private int mTurnCount;
        private int mHeldDiceCount;
        private String mName;
        private CupView mCupView;
        private Button mScoreButton;
        private Button mRollButton;
        private int mRollCount;
        public static ScoresDbAdapter mDbHelper;
        private CupThread mCupThread;
        private long mGameID;
        TextView mInstruct;
        private SensorManager mSensorManager;
        private float mLastX;
        private SensorListener mAccellListener;
        private int mShake;
        private boolean mShaking;

    /** Called when the activity is first created. */
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        // set the content view to the main game board (the cup)
        setContentView(R.layout.board);
        if (savedInstanceState == null){
                setState(ENTER);
                mHeldDiceCount = 0;
                mRollCount = 0;
        }else{
                setState(IN_PROGRESS);
        }

        mInstruct = (TextView) findViewById(R.id.top_text);

        //get the cup view
        mCupView = (CupView) findViewById(R.id.cup);
        mCupThread = mCupView.getThread();

        // Before calling any of the Simulator data,
        // the Content resolver has to be set !!
        Hardware.mContentResolver = getContentResolver();

        // Link sensor manager to OpenIntents Sensor simulator
        mSensorManager =
                (SensorManager) new SensorManagerSimulator((SensorManager)
                                   getSystemService(SENSOR_SERVICE));

        //setUpAccell();

        // give the LunarView a handle to the TextView used for
messages
        mCupView.setTextView((TextView) findViewById(R.id.text));

        // get the score sheet button and set its listener
        mScoreButton = (Button) findViewById(R.id.score_button);
        mScoreButton.setOnClickListener(new Button.OnClickListener() {
                public void onClick(View v){
                        openScoreSheet();
                }
        });

        mRollButton = (Button) findViewById(R.id.roll_button);
        mRollButton.setOnClickListener(new Button.OnClickListener() {
                public void onClick(View v){
                        rollDice();
                }
        });
        mDbHelper = new ScoresDbAdapter(this);
        mDbHelper.open();

    }
    //-------------------------------------------------------------------------
    private void openScoreSheet(){
        if (mMode==IN_PROGRESS){
                        Intent i = new Intent(this, ScoreSheet.class);
                        i.putExtra("my.package.GameID", mGameID);
                        startActivity(i);
        }
    }
    //-------------------------------------------------------------------------
    public boolean onCreateOptionsMenu(Menu menu){
        super.onCreateOptionsMenu(menu);

        menu.add(0,MENU_NEWGAME,0,R.string.menu_newgame);
        menu.add(0,MENU_RESUMEGAME,0,R.string.menu_resumegame);
        menu.add(0,MENU_EXITGAME,0,R.string.menu_exitgame);

        return true;
    }
    //-------------------------------------------------------------------------
    public boolean onOptionsItemSelected(MenuItem item){
        switch (item.getItemId()){
                case MENU_NEWGAME:
                        createNewGame();
                        return true;
                case MENU_RESUMEGAME:
                        resumeGame();
                        return true;
                case MENU_EXITGAME:
                        return true;
        }
        return false;
    }
    //-------------------------------------------------------------------------
    /**
     * My own listener interface to use for getting values back from a
dialog.
     */
        public interface CreateGameListener{
                        public void onOKClick(String name);
                        public void onCancelClick();
        }
        
//-------------------------------------------------------------------------
        /**
         * Method called from CreateGameListener's onOKClick
         */
        public void okClick(String n, long game){
                mName = n;
//              TextView topText = (TextView) findViewById(R.id.top_text);
//              Long gameInt = new Long(game);
//              topText.setText(gameInt.toString());
                mGameID = mDbHelper.createGame(n);
        }
        
//-------------------------------------------------------------------------
    private void createNewGame(){
        mRollCount = 0;
        mTurnCount = 0;
        setState(IN_PROGRESS);
        // start the activity that asks for the name of the new game
        CreateGameListener listener = new CreateGameListener(){
                public void onOKClick(String n){
                        okClick(n,mGameID);
                }
                public void onCancelClick(){

                }
        };
        CreateGame dialog = new CreateGame(mCupView.getContext
(),listener);
        dialog.show();
    }
    //-------------------------------------------------------------------------
    private void resumeGame(){
        setState(IN_PROGRESS);
        // create a new intent that has a list of all the games
        Intent i = new Intent(this,ResumeGameList.class);
        startActivity(i);
    }
    //-------------------------------------------------------------------------
    private void rollDice(){
        if (mMode==IN_PROGRESS){
                // create a new intent for the roll dice view
                Intent i = new Intent(this,RollDice.class);
                        mRollCount = mRollCount + 1;
                        if (mRollCount == 3){
                                mTurnCount += 1;
                        }
                        if (mTurnCount == 13){
                                setState(GAME_OVER);
                        }
                i.putExtra("my.package.RollCount", mRollCount);
                i.putExtra("my.package.GameID",mGameID);
                startActivityForResult(i,ROLL_DICE_ACTIVITY);
//              startActivity(i);
//              finish();
        }
    }
    //-------------------------------------------------------------------------
        @Override
        protected void onActivityResult(int requestCode, int resultCode,
                        Intent data) {
                super.onActivityResult(requestCode, resultCode, data);
                if (requestCode == 1){
                        // if its returning after the third role
                        if (resultCode == RollDice.READY_TO_SCORE){
                                // start the ChooseScore Activity.
                                mRollCount = 0;
                                startActivity(data);
                        }else{
                                mHeldDiceCount = resultCode;
                        }
                }
        }
        
//-------------------------------------------------------------------------
        public void setState(int mode){
                if (mode == ENTER){
                        //mInstruct.setText("Press Menu to start a game.");
                }
                if (mode == IN_PROGRESS){
                        //mInstruct.setText("Shake phone to shake dice.");
                }
                if (mode == GAME_OVER){
                        //mInstruct.setText("Game Over");
                }
                mMode = mode;
        }
        
//-------------------------------------------------------------------------
        public int getState(){return mMode;}

    //-------------------------------------------------------------------------
    protected void onPause(){
        super.onPause();
    }
//    
//-------------------------------------------------------------------------
    protected void onResume(){
        super.onResume();
    }
    //-------------------------------------------------------------------------
    public void setUpAccell(){
        mLastX = 0;
        mShake = 0;
        mAccellListener = new SensorListener() {
                Float x;
                public void onSensorChanged(int sensor, float[] values){
                        if (sensor == SensorManager.SENSOR_ACCELEROMETER){
                                x = values[SensorManager.DATA_X];

                                if ((x-mLastX>.5)||(x-mLastX<-.5)){
                                        mShake += 1;
                                }
//                              if 
(((x-mLastX<.5)||(x-mLastX>-.5))&&(mShake>=0)){
//                                      mShake -= 1;
//                              }

                                if (mShake>3){
                                        mShaking = true;
                                        
mCupThread.setState(mCupThread.STATE_SHAKING);
                                }
                                if (mShake==0&&mShaking){
                                        mShaking = false;
                                        
mCupThread.setState(mCupThread.STATE_RUNNING);
                                }
                                mLastX = x;
                        }
                }
                public void onAccuracyChanged(int sensor, int acc){}
        };


        // now connect to simulator
        SensorManagerSimulator.connectSimulator();



        // now enable the new sensors
        mSensorManager.registerListener(mAccellListener,
                   SensorManager.SENSOR_ACCELEROMETER);
    }
}

On Mar 31, 10:35 pm, kbeal10 <kbea...@gmail.com> wrote:
> This is where the thread variable is declared.
>
>         private Context mContext;
>         /** The thread that actually draws teh animations. */
>         private CupThread thread;
>         private TextView mStatusText;
>
>         public CupView(Context context, AttributeSet attrs){
>                 super(context,attrs);
>
>                 //register our interest in hearing about changes to our 
> surface
>                 SurfaceHolder holder = getHolder();
>                 holder.addCallback(this);
>                 mContext = context;
>                 setFocusable(true);
>                 // create thread only; it's started in surfaceCreated()
>         }
>
> I'm sorry for the confusion about "exiting" in rollDice(). Indeed, I
> am not exiting here, but starting another Activity.
>
> I believe, as you mentioned, this is a case where the original
> activity is still there, and then being re-displayed. However,
> CupView's surfaceDestroyed() is called when I start the other Activity
> in rollDice(). This means that when the Activity holding CupView
> resumes I should be able to create a new thread and start it. I am
> aware you can't call start() on the same thread twice, but since
> surfaceDestroyed() is called that thread is terminated with the .join
> () call. A new thread is then created and started in surfaceCreated().
>
> I will post the full code to both the Activity holding the CupView, as
> well as the CupView in the following post.
>
> On Mar 31, 10:17 pm, Dianne Hackborn <hack...@android.com> wrote:
>
> > I don't think you've included enough code.  Where is this 'thread' variable
> > defined?  Where do you clear it after finishing the thread?
>
> > I am also confused by the comment saying you "exiting" the activity in
> > rollDice -- you aren't calling finish, you are just starting another
> > activity, so the original activity is still there, and its window will just
> > be re-displayed when it is shown again.
>
> > The only thing I can think of is that you aren't handling the case where
> > your window is hidden and then shown again, causing surfaceCreated to be
> > called a second time on the same SurfaceView, but again there isn't enough
> > code here to really tell what is happening.
>
> > Also you do know that you can only call Thread.start() once on a particular
> > thread object, right?
>
> >http://java.sun.com/j2se/1.5.0/docs/api/java/lang/Thread.html#start()
>
> > On Tue, Mar 31, 2009 at 6:46 PM, kbeal10 <kbea...@gmail.com> wrote:
>
> > > I'm writing a game using two different SurfaceView's (RollView and
> > > CupView) in two different activities. Both SurfaceView's heavily
> > > resemble the LunarLander demo.
>
> > > The RollView SurfaceView is working fine. When leaving the Activity,
> > > RollView's surfaceDestroyed() is called, killing the thread. If I then
> > > re-enter that Activity, the thread is recreated in RollView's
> > > constructor and then started in surfaceCreated().
>
> > > However in CupView the thread never seems to go away. SurfaceDestroyed
> > > is being called, but upon reentering the Activity I get the following
> > > error:
>
> > > java.lang.IllegalThreadStateException: Thread already started.
>
> > > This thrown is in surfaceCreated() at the thread.start() call.
>
> > > The difference between the two, and apparently the problem, is that in
> > > the RollView Activity I call finish() when done. When leaving the
> > > CupView Activity, I'm doing a startActivityForResult
> > > (i,ClassWithRollView.class);......not calling finish().
>
> > > This is because after leaving the RollView, I want to return to the
> > > CupView. Below is relevant code:
>
> > >   /** This where I'm exiting the Activity with the CupView **/
> > >    private void rollDice(){
> > >        if (mMode==IN_PROGRESS){
> > >                // create a new intent for the roll dice view
> > >                Intent i = new Intent(this,RollDice.class);
> > >                        mRollCount = mRollCount + 1;
> > >                        if (mRollCount == 3){
> > >                                mTurnCount += 1;
> > >                        }
> > >                        if (mTurnCount == 13){
> > >                                setState(GAME_OVER);
> > >                        }
> > >                i.putExtra("my.package.RollCount", mRollCount);
> > >                i.putExtra("my.package.GameID",mGameID);
> > >                startActivityForResult(i,ROLL_DICE_ACTIVITY);
> > >        }
> > >    }
>
> > > /** This is CupView's surfaceCreated/Destroyed **/
>
> > >  //-------------------------------------------------------------------------
> > >  --------------------
> > >        /* Callback invoked when the Surface has been created and is read 
> > > to
> > > be used. */
> > >        public void surfaceCreated(SurfaceHolder holder){
> > >                // start the thread here so that we don't busy-wait in 
> > > run()
> > >                // waiting for the surface to be created
> > >                Log.d("MyApp","cup view surface created");
> > >                thread.setRunning(true);
> > >                thread.start();
> > >        }
>
> > >  //-------------------------------------------------------------------------
> > >  --------------------
> > >        /* Callback invoked when the Surface has been destroyed and must no
> > > longer be touched.
> > >         * WARNING: after this method returns, the Surface/Canvas must 
> > > never
> > > be touched again!
> > >         * (Unless its REALLY asking for it.)
> > >         */
> > >        public void surfaceDestroyed(SurfaceHolder holder){
> > >                // we have to tell thread to shut down & wait for it to
> > > finish, or
> > > else it might touch
> > >                // the Surface(wouldn't want that!) after we return and
> > > explode
> > > (ahhh!).
> > >                Log.d("MyApp","cup view surface destroyed");
> > >                boolean retry = true;
> > >                thread.setRunning(false);
> > >                while (retry){
> > >                        try{
> > >                                thread.join();
> > >                                retry = false;
> > >                        }catch(InterruptedException e){
>
> > >                        }
> > >                }
> > >        }
>
> > > So why is the thread saying its already started when surfaceDestroyed
> > > () has been called?
>
> > > A possible workaround is to call finish() on the CupView Activity in
> > > the rollDice() method above. This doesn't seem to follow common
> > > paradigm though. Any other solutions, comments? All help is
> > > appreciated.
>
> > --
> > Dianne Hackborn
> > Android framework engineer
> > hack...@android.com
>
> > Note: please don't send private questions to me, as I don't have time to
> > provide private support.  All such questions should be posted on public
> > forums, where I and others can see and answer them.
--~--~---------~--~----~------------~-------~--~----~
You received this message because you are subscribed to the Google
Groups "Android Developers" group.
To post to this group, send email to android-developers@googlegroups.com
To unsubscribe from this group, send email to
android-developers-unsubscr...@googlegroups.com
For more options, visit this group at
http://groups.google.com/group/android-developers?hl=en
-~----------~----~----~----~------~----~------~--~---

Reply via email to