I am making an android game that needs to run a method continiously, kind of like a timer. I need that it is being called every second. How can i make this possible???
Java code:
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.widget.TextView;
import android.widget.Toast;
public class ExampleView extends SurfaceView implements SurfaceHolder.Callback
{
class ExampleThread extends Thread
{
private ArrayList<Parachuter> parachuters;
private Bitmap parachuter;
private Paint black;
private boolean running;
private SurfaceHolder mSurfaceHolder;
private Context mContext;
private Handler mHandler;
private GameScreenActivity mActivity;
private long frameRate;
private boolean loading;
public ExampleThread(SurfaceHolder sHolder, Context context, Handler handler)
{
mSurfaceHolder = sHolder;
mHandler = handler;
mContext = context;
mActivity = (GameScreenActivity) context;
parachuters = new ArrayList<Parachuter>();
parachuter = BitmapFactory.decodeResource(getResources(), R.drawable.parachuteman);
black = new Paint();
black.setStyle(Paint.Style.FILL);
black.setColor(Color.WHITE);
running = true;
// This equates to 26 frames per second.
frameRate = (long) (1000 / 26);
loading = true;
}
#Override
public void run()
{
while (running)
{
Canvas c = null;
try
{
c = mSurfaceHolder.lockCanvas();
synchronized (mSurfaceHolder)
{
long start = System.currentTimeMillis();
doDraw(c);
long diff = System.currentTimeMillis() - start;
if (diff < frameRate)
Thread.sleep(frameRate - diff);
}
} catch (InterruptedException e)
{
}
finally
{
if (c != null)
{
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
protected void doDraw(Canvas canvas)
{
canvas.drawRect(0, 0, canvas.getWidth(), canvas.getHeight(), black);
//Draw
for (int i = 0; i < parachuters.size(); i++)
{
canvas.drawBitmap(parachuter, parachuters.get(i).getX(), parachuters.get(i).getY(), null);
parachuters.get(i).tick();
}
//Remove
for (int i = 0; i < parachuters.size(); i++)
{
if (parachuters.get(i).getY() > canvas.getHeight())
parachuters.remove(i);
}
}
public boolean onTouchEvent(MotionEvent event)
{
if (event.getAction() != MotionEvent.ACTION_DOWN)
return false;
float x = event.getX();
float y = event.getY();
Parachuter p = new Parachuter(x, y);
parachuters.add(p);
Toast.makeText(getContext(), "x=" + x + " y=" + y, 15).show();
return true;
}
public void setRunning(boolean bRun)
{
running = bRun;
}
public boolean getRunning()
{
return running;
}
}
/** Handle to the application context, used to e.g. fetch Drawables. */
private Context mContext;
/** Pointer to the text view to display "Paused.." etc. */
private TextView mStatusText;
/** The thread that actually draws the animation */
private ExampleThread eThread;
public ExampleView(Context context)
{
super(context);
// register our interest in hearing about changes to our surface
SurfaceHolder holder = getHolder();
holder.addCallback(this);
// create thread only; it's started in surfaceCreated()
eThread = new ExampleThread(holder, context, new Handler()
{
#Override
public void handleMessage(Message m)
{
// mStatusText.setVisibility(m.getData().getInt("viz"));
// mStatusText.setText(m.getData().getString("text"));
}
});
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event)
{
return eThread.onTouchEvent(event);
}
public ExampleThread getThread()
{
return eThread;
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3)
{
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder)
{
if (eThread.getState() == Thread.State.TERMINATED)
{
eThread = new ExampleThread(getHolder(), getContext(), getHandler());
eThread.start();
}
else
{
eThread.start();
}
}
#Override
public void surfaceDestroyed(SurfaceHolder holder)
{
boolean retry = true;
eThread.setRunning(false);
while (retry)
{
try
{
eThread.join();
retry = false;
}
catch (InterruptedException e)
{
}
}
}
}
I need to add a function or a socalled "method", a public void or something like that, that should be called every second and should do the exact same code as the MotionEvent event method, the onTouchEvent.
Following Rob's commented link, consider (which is not the accepted answer, though) reviewing this from the Android Developer's site, Resources section: http://developer.android.com/resources/articles/timed-ui-updates.html
It describes how to use the android os Handler class to implement a timer, rather than using the Timer and TimerTask classes themselves.
This pretty much what you are looking for.
How to run a Runnable thread in Android?
It does sth every 1000ms using a thread.
Related
When I restart my App, I mean when I press the Homebutton and start it from the Task window, or when I debug it while it is still runnning the whole screen went black!
This is my MainView:
package net.kex.toll;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
public class MainView extends SurfaceView implements SurfaceHolder.Callback{
public GameLoop gameLoop;
public Player player;
private int playerX = 50;
private int playerY = 50;
public MainView(final Context context) {
super(context);
getHolder().addCallback(this);
player = new Player();
this.setOnTouchListener(new View.OnTouchListener() {
#Override
public boolean onTouch(View v, MotionEvent event) {
playerX = playerX + 20;
playerY = playerY + 20;
player.play();
return false;
}
}
);
setFocusable(true);
}
public void surfaceChanged(SurfaceHolder surfaceHolder, int foramt, int width, int height){
}
public void surfaceDestroyed(SurfaceHolder surfaceHolder){
boolean retry = true;
while (true) {
try {
gameLoop.setRunning(false);
gameLoop.join();
} catch (Exception e) { e.printStackTrace();}
retry = false;
}
}
public void surfaceCreated(SurfaceHolder surfaceHolder){
gameLoop = new GameLoop(getHolder(), this);
gameLoop.setRunning(true);
gameLoop.start();
}
public void update(){
player.update();
}
public void draw(Canvas canvas){
if(canvas == null) {
return;
}
canvas.drawColor(Color.WHITE);
player.draw(canvas);
}
}
This is my GameLoop:
package net.kex.toll;
import android.graphics.Canvas;
import android.util.Log;
import android.view.SurfaceHolder;
public class GameLoop extends Thread {
public static final int MAX_FPS = 30;
private double averageFPS;
private MainView mainView;
private SurfaceHolder surfaceHolder;
private boolean running;
public static Canvas canvas;
public void setRunning(boolean running) {
this.running = running;
}
public GameLoop(SurfaceHolder surfaceHolder, MainView mainView) {
super();
this.surfaceHolder = surfaceHolder;
this.mainView = mainView;
}
#Override
public void run(){
long startTime;
long timeMillis = 1000/MAX_FPS;
long waitTime;
long frameCount = 0;
long totalTime = 0;
long targetTime = 1000/MAX_FPS;
while (running) {
startTime = System.nanoTime();
canvas = null;
try {
canvas = this.surfaceHolder.lockCanvas();
synchronized (surfaceHolder) {
this.mainView.update();
this.mainView.draw(canvas);
}
}catch (Exception e){ e.printStackTrace();}
finally {
if (canvas != null) {
try {
surfaceHolder.unlockCanvasAndPost(canvas);
}catch (Exception e){ e.printStackTrace();}
}
}
timeMillis = (System.nanoTime() - startTime)/1000000;
waitTime = targetTime - timeMillis;
try {
if (waitTime >= 0){
this.sleep(waitTime);
}
}catch (Exception e){ e.printStackTrace();}
totalTime += System.nanoTime() - startTime;
frameCount++;
if (frameCount == MAX_FPS) {
averageFPS = 1000/((totalTime/frameCount)/1000000);
frameCount = 0;
totalTime = 0;
Log.i("GameLoop", "averageFPS: " + Double.toString(averageFPS));
}
}
}
}
I don't know what to do! If you want some other class please tell me and I will send it to you!
Please help I´m sitting here and trying to solve this problem for hours!
Repaint the object, it will render it again. For example in onResume add Repaint()
In order to display a view with moving objects (from bitmaps) and touch events, I've been using the following code for a SurfaceView in Android. It has alwas worked fine on my development devices, but it turned out that lots of users just see a black box in place of that View. After quite a long time of (unsuccessful) debugging, I've come to the conclusion that it must be Android 4.1 which causes the SurfaceView to stop working correctly.
My development devices are Android 4.0 but users complaining about the black-only SurfaceView have Android 4.1. Checked that with a Android 4.1 emulator - and it's not working there, either.
Can you see what is wrong with the code? Is it caused by the "Project Butter" things in Android 4.1, perhaps?
Of course, I've checked that the Bitmap objects are valid (saved them to SD card in appropriate lines) and all methods for drawing are periodically called as well - everything's normal there.
package com.my.package.util;
import java.util.ArrayList;
import java.util.List;
import com.my.package.Card;
import com.my.package.MyApp;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Rect;
import android.util.AttributeSet;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MySurface extends SurfaceView implements SurfaceHolder.Callback {
private MyRenderThread mRenderThread;
private volatile List<Card> mGameObjects;
private volatile int mGameObjectsCount;
private int mScreenWidth;
private int mScreenHeight;
private int mGameObjectWidth;
private int mGameObjectHeight;
private int mHighlightedObject = -1;
private Paint mGraphicsPaint;
private Paint mShadowPaint;
private Rect mDrawingRect;
private int mTouchEventAction;
private Bitmap bitmapToDraw;
private int mOnDrawX1;
private BitmapFactory.Options bitmapOptions;
// ...
public MySurface(Context activityContext, AttributeSet attributeSet) {
super(activityContext, attributeSet);
getHolder().addCallback(this);
setFocusable(true); // touch events should be processed by this class
mGameObjects = new ArrayList<Card>();
mGraphicsPaint = new Paint();
mGraphicsPaint.setAntiAlias(true);
mGraphicsPaint.setFilterBitmap(true);
mShadowPaint = new Paint();
mShadowPaint.setARGB(160, 20, 20, 20);
mShadowPaint.setAntiAlias(true);
bitmapOptions = new BitmapFactory.Options();
bitmapOptions.inInputShareable = true;
bitmapOptions.inPurgeable = true;
mDrawingRect = new Rect();
}
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) { }
public void surfaceCreated(SurfaceHolder arg0) {
mScreenWidth = getWidth();
mScreenHeight = getHeight();
mGameObjectHeight = mScreenHeight;
mGameObjectWidth = mGameObjectHeight*99/150;
mCurrentSpacing = mGameObjectWidth;
setDrawingCacheEnabled(true);
mRenderThread = new MyRenderThread(getHolder(), this);
mRenderThread.setRunning(true);
mRenderThread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
mRenderThread.setRunning(false); // stop thread
while (retry) { // wait for thread to close
try {
mRenderThread.join();
retry = false;
}
catch (InterruptedException e) { }
}
}
public void stopThread() {
if (mRenderThread != null) {
mRenderThread.setRunning(false);
}
}
#Override
public void onDraw(Canvas canvas) {
if (canvas != null) {
synchronized (mGameObjects) {
mGameObjectsCount = mGameObjects.size();
canvas.drawColor(Color.BLACK);
if (mGameObjectsCount > 0) {
mCurrentSpacing = Math.min(mScreenWidth/mGameObjectsCount, mGameObjectWidth);
for (int c = 0; c < mGameObjectsCount; c++) {
if (c != mHighlightedObject) {
try {
drawGameObject(canvas, mGameObjects.get(c).getDrawableID(), false, c*mCurrentSpacing, c*mCurrentSpacing+mGameObjectWidth);
}
catch (Exception e) { }
}
}
if (mHighlightedObject > -1) {
mOnDrawX1 = Math.min(mHighlightedObject*mCurrentSpacing, mScreenWidth-mGameObjectWidth);
try {
drawGameObject(canvas, mGameObjects.get(mHighlightedObject).getDrawableID(), true, mOnDrawX1, mOnDrawX1+mGameObjectWidth);
}
catch (Exception e) { }
}
}
}
}
}
private void drawGameObject(Canvas canvas, int resourceID, boolean highlighted, int xLeft, int xRight) {
if (canvas != null && resourceID != 0) {
try {
if (highlighted) {
canvas.drawRect(0, 0, mScreenWidth, mScreenHeight, mShadowPaint);
}
bitmapToDraw = MyApp.gameObjectCacheGet(resourceID);
if (bitmapToDraw == null) {
bitmapToDraw = BitmapFactory.decodeResource(getResources(), resourceID, bitmapOptions);
MyApp.gameObjectCachePut(resourceID, bitmapToDraw);
}
mDrawingRect.set(xLeft, 0, xRight, mGameObjectHeight);
canvas.drawBitmap(bitmapToDraw, null, mDrawingRect, mGraphicsPaint);
}
catch (Exception e) { }
}
}
#Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (mRenderThread.getSurfaceHolder()) { // synchronized so that there are no concurrent accesses
mTouchEventAction = event.getAction();
if (mTouchEventAction == MotionEvent.ACTION_DOWN || mTouchEventAction == MotionEvent.ACTION_MOVE) {
if (event.getY() >= 0 && event.getY() < mScreenHeight) {
mTouchEventObject = (int) event.getX()/mCurrentSpacing;
if (mTouchEventObject > -1 && mTouchEventObject < mGameObjectsCount) {
mHighlightedObject = mTouchEventObject;
}
else {
mHighlightedObject = -1;
}
}
else {
mHighlightedObject = -1;
}
}
else if (mTouchEventAction == MotionEvent.ACTION_UP) {
if (mActivityCallback != null && mHighlightedObject > -1 && mHighlightedObject < mGameObjectsCount) {
try {
mActivityCallback.placeObject(mGameObjects.get(mHighlightedObject));
}
catch (Exception e) { }
}
mHighlightedObject = -1;
}
}
return true;
}
// ...
}
And this is the code for the thread that periodically calls the SurfaceView's onDraw():
package com.my.package.util;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
public class MyRenderThread extends Thread {
private SurfaceHolder mSurfaceHolder;
private MySurface mSurface;
private boolean mRunning = false;
public MyRenderThread(SurfaceHolder surfaceHolder, MySurface surface) {
mSurfaceHolder = surfaceHolder;
mSurface = surface;
}
public SurfaceHolder getSurfaceHolder() {
return mSurfaceHolder;
}
public void setRunning(boolean run) {
mRunning = run;
}
#Override
public void run() {
Canvas c;
while (mRunning) {
c = null;
try {
c = mSurfaceHolder.lockCanvas(null);
synchronized (mSurfaceHolder) {
if (c != null) {
mSurface.onDraw(c);
}
}
}
finally { // when exception is thrown above we may not leave the surface in an inconsistent state
if (c != null) {
mSurfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
The SurfaceView is included in my Activity's layout XML:
<com.my.package.util.MySurface
android:id="#+id/my_surface"
android:layout_width="fill_parent"
android:layout_height="#dimen/my_surface_height" />
Then in code it is accessed like this:
MySurface mySurface = (MySurface) findViewById(R.id.my_surface);
Rename your draw method to onDraw2(). Change the thread code to call onDraw2. This way you are not overidding the base class's ondraw. I think you might be getting 2 hits in your onDraw. One from the base class override and one from the thread.
This would explain why setting the z-order helps. You will reverse the order the 2 windows draw therefore avoiding the problem. As to the "why now" part of the question. Since you have the 2 pathways to onDraw I suspect this is unsupported android behavior, so no telling what might happen.
Also I saw you called setDrawingCache enabled. I don't think that is helping you. Usually you would call getDrawingCache at some point. Try removing it if it is not important.
The only other thing I see is that you create the thread and pass the holder in surface created. You might want to take action when surfaceChanged occurs, or at
Least verify that nothing important has changed.
I have this code
package com.cerbertek;
import java.util.ArrayList;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class PlayGameView extends SurfaceView implements SurfaceHolder.Callback {
private CanvasThread canvasthread;
private Context mContext;
private Region firstRec;
private ArrayList<Region> regions;
private class CanvasThread extends Thread {
private SurfaceHolder _holder;
private boolean _run = false;
public CanvasThread(SurfaceHolder surfaceHolder) {
_holder = surfaceHolder;
}
public void setRunning(boolean run) {
_run = run;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _holder.lockCanvas(null);
synchronized (_holder) {
onDraw(c);
}
} finally {
if (c != null) {
_holder.unlockCanvasAndPost(c);
}
}
}
}
}
public PlayGameView (Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
canvasthread = new CanvasThread(getHolder());
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint ();
Bitmap wrench = BitmapFactory.decodeResource(getResources(), R.drawable.wrench);
canvas.drawColor(Color .BLACK);
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
int left = canvas.getWidth()/2 - wrench.getWidth()*2 + j*wrench.getWidth();
int top = 0 + i*wrench.getHeight();
canvas.drawBitmap(wrench, left, top, null);
Log.d(i + " " + j, left+ " " + top);
Region reg = new Region(left, top, left + wrench.getWidth(), top + wrench.getHeight());
regions.add(reg);
}
}
}
public ArrayList<Region> getRegions() {
return regions;
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
canvasthread.setRunning(true);
canvasthread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
boolean retry = true;
canvasthread.setRunning(false);
while (retry) {
try {
canvasthread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
in onDraw() method I want to create a Region and add it to ArrayList, that returning by getRegions() method.
But it now works!
I saw first image and then NullPoiterExeption on regions.add(reg); line.
Please hlp me
In the constructor put:
regions = new ArrayList<Region>();
You were forgetting to initialize it.
there is class, that draws on canvas some field
package com.cerbertek;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Region;
import android.util.AttributeSet;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class PlayGameView extends SurfaceView implements SurfaceHolder.Callback {
private CanvasThread canvasthread;
private Context mContext;
private Region firstRec;
private class CanvasThread extends Thread {
private SurfaceHolder _holder;
private boolean _run = false;
public CanvasThread(SurfaceHolder surfaceHolder) {
_holder = surfaceHolder;
}
public void setRunning(boolean run) {
_run = run;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _holder.lockCanvas(null);
synchronized (_holder) {
onDraw(c);
}
} finally {
if (c != null) {
_holder.unlockCanvasAndPost(c);
}
}
}
}
}
public PlayGameView (Context context, AttributeSet attrs) {
super(context, attrs);
SurfaceHolder holder = getHolder();
holder.addCallback(this);
canvasthread = new CanvasThread(getHolder());
setFocusable(true);
}
#Override
public void onDraw(Canvas canvas) {
Paint paint = new Paint ();
Bitmap wrench = BitmapFactory.decodeResource(getResources(), R.drawable.wrench);
canvas.drawColor(Color .BLACK);
for(int i = 0; i < 4; i++) {
for(int j = 0; j < 4; j++) {
int left = canvas.getWidth()/2 - wrench.getWidth()*2 + j*wrench.getWidth();
int top = 0 + i*wrench.getHeight();
canvas.drawBitmap(wrench, left, top, null);
Log.d(i + " " + j, left+ " " + top);
}
}
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
canvasthread.setRunning(true);
canvasthread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
boolean retry = true;
canvasthread.setRunning(false);
while (retry) {
try {
canvasthread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}
so i want to detect where i click on(for exemple there is 2 rects and i want to detect what rect i click on). i can set setOnClickListener to my view, but how to get position of click?
then i want to set the regions while drawing( it is right, yeah? or not?) and in activity i'll check is click coordinates contains regions
so
1) how can i get coord of click
2) what is the pretty good way to do do all that stuff, because my ideas are poor often
Look at the setOnTouchListener.
The OnTouchListener implements a method with the following signature:
public boolean onTouch(View v, MotionEvent event)
The MotionEvent has information about where the touch actually happened. (event.getX() and event.getY())
onRestoreInstanceState(Bundle savedInstanceState)
is not geting called, I am pasting my code below. Actually I want to redraw all the points that are saved when my activity went in background.
package com.geniteam.mytest;
import java.util.ArrayList;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.Window;
public class Tutorial2D extends Activity {
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(new Panel(this));
}
#Override
protected void onSaveInstanceState(Bundle outState) {
super.onSaveInstanceState(outState);
Panel panel = new Panel(this);
outState.putSerializable("test", panel._graphics);
}
#Override
protected void onRestoreInstanceState(Bundle savedInstanceState) {
super.onRestoreInstanceState(savedInstanceState);
Panel panel = new Panel(this);
panel.set_graphics((ArrayList<GraphicObject>) savedInstanceState.getSerializable("test"));
}
class Panel extends SurfaceView implements SurfaceHolder.Callback {
private TutorialThread _thread;
private ArrayList<GraphicObject> _graphics = new ArrayList<GraphicObject>();
public ArrayList<GraphicObject> get_graphics() {
return _graphics;
}
public void set_graphics(ArrayList<GraphicObject> graphics) {
_graphics = graphics;
}
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
_thread = new TutorialThread(getHolder(), this);
setFocusable(true);
}
#Override
public boolean onTouchEvent(MotionEvent event) {
synchronized (_thread.getSurfaceHolder()) {
// if (event.getAction() == MotionEvent.ACTION_DOWN) {
GraphicObject graphic = new GraphicObject(BitmapFactory.decodeResource(getResources(), R.drawable.icon));
graphic.getCoordinates().setX((int) event.getX() - graphic.getGraphic().getWidth() / 2);
graphic.getCoordinates().setY((int) event.getY() - graphic.getGraphic().getHeight() / 2);
_graphics.add(graphic);
//}
return true;
}
}
#Override
public void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
Bitmap bitmap;
GraphicObject.Coordinates coords;
for (GraphicObject graphic : _graphics) {
bitmap = graphic.getGraphic();
coords = graphic.getCoordinates();
canvas.drawBitmap(bitmap, coords.getX(), coords.getY(), null);
}
}
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
try{
_thread.setRunning(true);
_thread.start();
}catch(Exception ex){
_thread = new TutorialThread(getHolder(), this);
_thread.start();
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
// simply copied from sample application LunarLander:
// 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) {
// we will try it again and again...
}
}
}
}
class TutorialThread extends Thread {
private SurfaceHolder _surfaceHolder;
private Panel _panel;
private boolean _run = false;
public TutorialThread(SurfaceHolder surfaceHolder, Panel panel) {
_surfaceHolder = surfaceHolder;
_panel = panel;
}
public void setRunning(boolean run) {
_run = run;
}
public SurfaceHolder getSurfaceHolder() {
return _surfaceHolder;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = _surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_panel.onDraw(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);
}
}
}
}
}
class GraphicObject {
/**
* Contains the coordinates of the graphic.
*/
public class Coordinates {
private int _x = 100;
private int _y = 0;
public int getX() {
return _x + _bitmap.getWidth() / 2;
}
public void setX(int value) {
_x = value - _bitmap.getWidth() / 2;
}
public int getY() {
return _y + _bitmap.getHeight() / 2;
}
public void setY(int value) {
_y = value - _bitmap.getHeight() / 2;
}
public String toString() {
return "Coordinates: (" + _x + "/" + _y + ")";
}
}
private Bitmap _bitmap;
private Coordinates _coordinates;
public GraphicObject(Bitmap bitmap) {
_bitmap = bitmap;
_coordinates = new Coordinates();
}
public Bitmap getGraphic() {
return _bitmap;
}
public Coordinates getCoordinates() {
return _coordinates;
}
}
}
onRestoreInstanceState only gets called if the app is destroyed and re-created. Putting the app in the background then bringing it up again will call onResume, but not onRestoreInstanceState.