Perhaps this would be a better way to inspire feedback.   Is it
possible to pause and resume a view based upon SurfaceView?  What
would be the correct way to restart the view so that the thread can
begin drawing again?






On Fri, Apr 24, 2009 at 1:29 PM, Jason Van Anden
<jason.van.an...@gmail.com> wrote:
> I created a toy app that demos my problem ... the complete code can be
> found here:  http://www.smileproject.com/SurfCodeExample.zip
>
> Feedback super appreciated.  Here is the code from the activity and
> view only ...
>
> public class Surf extends Activity {
>    /** Called when the activity is first created. */
>
>    private SurfView mView;
>    private SurfThread mThread;
>
>        private static final int COLOR_MENU_ID = Menu.FIRST;
>        public static final int ACTIVITY_ASSIGN_COLOR = 0;
>
>   �...@override
>    public void onCreate(Bundle savedInstanceState) {
>
>        super.onCreate(savedInstanceState);
>
>        mView= new SurfView(this, null);
>        setContentView(mView);
>   }
>
>       �...@override
>        protected void onPause() {
>                // TODO Auto-generated method stub
>                super.onPause();
>
>                System.out.println ("PAUSED");
>                mThread.pause();
>        }
>
>       �...@override
>        protected void onResume() {
>                // TODO Auto-generated method stub
>                super.onResume();
>
>                System.out.println ("RESUMED");
>
>                mThread = mView.getThread();
>            mThread.resume();
>        }
>
>       �...@override
>        public boolean onCreateOptionsMenu(Menu menu) {
>
>                boolean result = super.onCreateOptionsMenu(menu);
>
>                menu.add(0, COLOR_MENU_ID, 0, R.string.menu_color);
>
>                return result;
>        }
>
>       �...@override
>        public boolean onPrepareOptionsMenu(Menu menu) {
>                super.onPrepareOptionsMenu(menu);
>                return true;
>        }
>
>       �...@override
>        public boolean onOptionsItemSelected(MenuItem item) {
>
>                super.onOptionsItemSelected(item);
>
>                switch (item.getItemId()) {
>
>                case COLOR_MENU_ID:
>                        Intent i = new Intent(this, SurfChooser.class);
>                        startActivityForResult(i, ACTIVITY_ASSIGN_COLOR);
>                        return true;
>                }
>
>                return true;
>        }
>
>         @Override
>         protected void onActivityResult(int requestCode, int resultCode,
> Intent data) {
>                // TODO Auto-generated method stub
>                super.onActivityResult(requestCode, resultCode, data);
>
>                Bundle extras;
>
>                if (data == null) return;
>
>                extras = data.getExtras();
>
>                switch(requestCode) {
>
>                case ACTIVITY_ASSIGN_COLOR:
>                        Log.w(this.getClass().getName(), "back");
>                        if (data == null) return;
>
>                }
>         }
> }
>
> class SurfView extends SurfaceView implements SurfaceHolder.Callback,
> OnGestureListener  {
>
>        private String TAG  = "SurfView";
>    private boolean is_dirty = true;
>
>    private boolean block_block = false;
>    private boolean block_after_draw = true;
>
>    /** The thread that actually draws the animation */
>    private SurfThread thread;
>        private GestureDetector mGestureDetector;
>
>
>        public float offset_x = 0; // review this later
>        public float offset_y = 0;
>
>        public float x_velocity = 0; // review this later
>        public float y_velocity = 0;
>
>        private float last_pos_x = 0;
>        private float last_pos_y = 0;
>
>        private int keep_on_trucking = -1;
>
>        // used for managing timing in physics
>    private long start_time = System.currentTimeMillis();
>    private long end_time = 0;
>    private long sleep_time = 0;
>    private long diff_time = 0;
>    private long action_period = 20; // 50 = 20fps
>
>    /** coords of bg circle */
>    private float bX;
>    private float bY;
>
>    /** coords of pointer (m == mouse). */
>    private float mX;
>    private float mY;
>
>    /** Handle to the surface manager object we interact with */
>    private boolean hasSurface;
>
>        class SurfThread extends Thread {
>
>        private int mCanvasWidth = -1;
>        private int mCanvasHeight = -1;
>
>        /** !!! Message handler used by thread to interact with TextView */
>        // private Handler mHandler;
>
>        /** Used to figure out elapsed time between frames */
>        private long mLastTime;
>
>         /** The state of the game. One of READY, RUNNING, PAUSE,
> LOSE, or WIN */
>        private int mMode;
>
>        /** Scratch rect object. */
>        private RectF mScratchRect;
>
>                Paint mPaint = new Paint();
>
>                int transparent_white;
>
>            /** Indicate whether the surface has been created & is ready to 
> draw */
>        private boolean mRunning = false;
>                public boolean is_drawing = false;
>
>                private ConditionVariable mCondition = new ConditionVariable();
>
>            private SurfaceHolder mHolder;
>            private Context mContext;
>
>                public SurfThread(SurfaceHolder holder, Context context){
>
>                    mHolder = holder;
>                    mContext = context;
>
>                        mRunning = false;
>                        init();
>                }
>
>                public void init(){
>                        mPaint.setColor(Color.RED);
>                }
>
>                public void pause(){
>                        synchronized (this) {
>                                Log.v("PeepThread", "pause?");
>                                //requestExitAndWait();
>
>                                setRunning(false);
>                                mCondition.open();
>                                //holdup = false;
>
>                        }
>                }
>
>        public void setRunning(boolean b) {
>            mRunning = b;
>        }
>
>                public boolean holdup = false;
>
>        public void do_draw(){
>
>                is_dirty = true;
>                block_after_draw = true;
>                mCondition.open();
>        }
>
>        /** this is key to most everything */
>       �...@override
>        public void run() {
>
>                SurfaceHolder surfaceHolder = mHolder;
>                mCondition = new ConditionVariable(false);
>
>                Log.v("Peep Thread", "restarted?");
>
>                mRunning = true;
>
>            while (mRunning) {
>
>                Log.v("Peep Thread", "run?");
>
>                while (holdup){
>
>                        mCondition.block(100);
>                        System.out.println ("not running?");
>
>                        if (!mRunning){
>                                is_dirty = false;
>                                break;
>                        }
>                }
>
>                is_drawing = true;
>
>                updatePhysics();
>
>                if (is_dirty){
>
>                        Canvas c = null;
>
>                        c = surfaceHolder.lockCanvas(null); // moved this out
> of "try" loop as per Stoyan suggestion
>
>                        try {
>                            synchronized (surfaceHolder) {
>                                draw_me(c);
>                            }
>
>                        } finally {
>                            // do this in a finally so that if an exception is 
> thrown
>                            // during the above, we don't leave the Surface in 
> an
>                            // inconsistent state
>                            if (c != null) {
>                                surfaceHolder.unlockCanvasAndPost(c);
>                            }
>                        }
>                        is_dirty = false;
>                    }
>
>                start_time = System.currentTimeMillis();
>
>                is_drawing = false;
>
>                // !!! this needs to work off a stack
>                if (block_after_draw) {
>                        mCondition.close();
>                        mCondition.block();
>                }
>            }
>
>            System.out.println ("thread killed?");
>
>        }
>
>        public void requestExitAndWait(){
>
>                mRunning = false;
>
>                try {
>                        join();
>                } catch (InterruptedException ex){
>            // nothing is supposed to happen here
>                // (left intentionally blank)
>                }
>        }
>
>        /* Callback invoked when the surface dimensions change. */
>        public void setSurfaceSize(int width, int height) {
>            // synchronized to make sure these all change atomically
>
>                // !!! TODO: make sure center of screen stays.  Might make
> sense to draw a mini-screen_bubble to confirm.
>
>            synchronized (mHolder) {
>
>                // this can be improved - ask ben to write something that
> will determine the smallest circle that will fit around the largest
> square
>                System.out.println ("setSurfaceSize");
>
>                mCanvasWidth = width;
>                mCanvasHeight = height;
>            }
>        }
>
>
>        public void unpause() {
>
>            // Move the real time clock up to now
>            synchronized (mHolder) {
>            }
>
>            thread.do_draw();
>        }
>
>        /**
>         * Draw operations go in here
>         */
>        private void draw_me(Canvas canvas) {
>
>                canvas.drawColor(Color.WHITE); // draw background color
>
>                        canvas.save();
>                        canvas.translate(offset_x, offset_y);
>
>                        canvas.drawCircle(mX, mY, 60, mPaint);
>
>                        canvas.restore();
>                        canvas.translate(offset_x * -1, offset_y * -1);
>        }
>
>        /**
>         * Figures the lander state (x, y, fuel, ...) based on the passage of
>         * realtime. Does not invalidate(). Called at the start of draw().
>         * Detects the end-of-game and sets the UI to the next state.
>         */
>        private void updatePhysics() {
>
>                end_time = System.currentTimeMillis();
>                diff_time = (end_time - start_time);
>                sleep_time = action_period - diff_time;
>
>                if (sleep_time < 1) sleep_time = 1;
>
>                        try {
>                                Thread.sleep(sleep_time);
>                        }
>                        catch(InterruptedException ex) {
>
>                        }
>
>                        is_dirty = true;
>
>                }
>        }
>
>    private void init(){
>        // register our interest in hearing about changes to our surface
>
>                mGestureDetector = new GestureDetector(this);
>                mGestureDetector.setIsLongpressEnabled(false);  // true
>
>                setLongClickable(false);
>
>        hasSurface = false;
>     }
>
>    public SurfView(Context context, AttributeSet attrs) {
>        super(context, attrs);
>
>        init(); // prep stuff for view
>
>        SurfaceHolder holder = getHolder();
>        holder.addCallback(this);
>        holder.setType(SurfaceHolder.SURFACE_TYPE_GPU);
>
>        thread = new SurfThread(holder, context);
>    }
>
>    /**
>     * Fetches the animation thread corresponding to this View.
>     *
>     * @return the animation thread
>     */
>    public SurfThread getThread() {
>        return thread;
>    }
>
>    /**
>     * Standard window-focus override. Notice focus lost so we can pause on
>     * focus lost. e.g. user switches to take a call.
>     */
>   �...@override
>    public void onWindowFocusChanged(boolean hasWindowFocus) {
>
>   }
>
>    /* Callback invoked when the surface dimensions change. */
>    public void surfaceChanged(SurfaceHolder holder, int format, int
> width, int height) {
>        thread.setSurfaceSize(width, height);
> //        if (thread != null)   thread.setSurfaceSize(width, height);
>    }
>
>    /*
>     * Callback invoked when the Surface has been created and is ready 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
>
>        is_dirty = true;
>
>        Log.w(this.getClass().getName(), thread.isAlive() + "?");
>
>
>                try {
>                    thread.start();
>                } catch (Exception e){
>                        // thread.run();
>                        System.out.println ("resurfaced"); // DEAL WITH THIS 
> DIFF
>                }
>
>    }
>
>    /*
>     * 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!
>     */
>    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 after we return and explode
>        boolean retry = true;
>
>        thread.setRunning(false);
>
>        while (retry) {
>            try {
>                thread.join();
>                retry = false;
>            } catch (InterruptedException e) {
>
>            }
>        }
>
>        Log.v(this.getClass().getName(), "SURFACE DESTROYED");
>
>    }
>
>       �...@override
>        public boolean onTouchEvent(MotionEvent event) {
>                return false;
>        }
>
>
>       �...@override
>        public boolean dispatchTouchEvent(MotionEvent event) {
>
>                boolean returnValue = false;
>
>                        is_dirty = true;
>
>                        returnValue  =  mGestureDetector.onTouchEvent(event);
>                        returnValue  =  returnValue ?  returnValue : 
> onTouchEvent(event);
>
>                return returnValue;
>        }
>
>        public boolean onDown(MotionEvent event) {
>
>                System.out.println ("down");
>                thread.do_draw();
>                return true;
>        }
>
>        public boolean onFling(MotionEvent first_event, MotionEvent
> last_event, float velocityX, float velocityY) {
>                return false;
>        }
>
>        public void onLongPress(MotionEvent event) {
>                thread.do_draw();
>        }
>
>        public boolean onScroll(MotionEvent arg0, MotionEvent event, float
> distance_x, float distance_y) {
>                return false;
>        }
>
>        public void onShowPress(MotionEvent arg0) {
>                // TODO Auto-generated method stub
>        }
>
>        public boolean onSingleTapUp(MotionEvent event) {
>
>                mX = event.getX();
>                mY = event.getY();
>                thread.do_draw();
>
>                return false;
>        }
>
> }
>
> Thank You,
> Jason
>
>
>
>
>
>
>
>
> On Fri, Apr 24, 2009 at 12:03 PM, robotissues <jason.van.an...@gmail.com> 
> wrote:
>> I am stuck.  My main activity creates and starts a SurfaceView.  My
>> app needs to access a listview via the options menu to change
>> properties of the items shown in the view.
>>
>> Two strange things occur:
>>
>> 1.) When I scroll the listview quickly, the list sometimes gets
>> farklempt.  Words overlap each other.
>>
>> 2.) When I select the item and the app returns to the main activity,
>> the thread is no longer alive.
>>
>> If someone out there can offer help I will post the code.  This will
>> take a little effort.  My code is loosely based upon LunarLander and
>> the GLSurfaceView examples.  If there is a good example (more recent
>> example) someone can point me to, that would be boss.
>>
>> Thank You
>

--~--~---------~--~----~------------~-------~--~----~
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