following is my simple code, actually i want to log HELLO in the draw() method repeatedly but my surfacecreated method is not called and so thread is not started. plz help me
public class MainActivity extends Activity{
private MyThread myThread ;
Panel _View;
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
_View = new Panel(this);
}
public class Panel extends SurfaceView implements SurfaceHolder.Callback {
Canvas canvas;
public Panel(Context context) {
super(context);
getHolder().addCallback(this);
}//end of panel
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
myThread= new MyThread(this);
myThread.setRunning(true);
myThread.start();
}
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
myThread.setRunning(false);
}
public void Draw(Canvas canvas){
super.draw(canvas);
this.canvas = canvas;
Log.d("HELLO", 0+"");
}//end of DRAW()
}//end of Panel class
public class MyThread extends Thread {
Panel panel;
private SurfaceHolder myHolder;
boolean mRun=false;
public MyThread(Panel panel)
{
this.panel= panel;
this.myHolder = panel.getHolder();
}
public void setRunning(boolean run){
this.mRun=run;
}
public void run(){
Canvas canvas = null;
while(mRun)
{
canvas=myHolder.lockCanvas();
if(canvas!=null)
{
panel.Draw(canvas);
}
myHolder.unlockCanvasAndPost(canvas);
}
}
}//MyThread class ends
}//end of bird mania activity
The surface is not created until you add it to the View hierarchy. If it is your only View, you can set it with
setContentView( _View);
in your onCreate() method.
Related
I'm trying to get an application to paint something on a canvas every half a second, but the SurfaceHolder.getSurface().isValid() returns false, and when I call SurfaceHolder.lockCanvas() this returns null.
As per this SO question, I should use a SurfaceHolder.Callback.surfaceCreated but the surface is never created.
The onCreate method from my main Activity
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
ChartPainter p = new ChartPainter(this);
}
And part of my ChartPainter.java
public ChartPainter(Context context) {
super(context);
holder = getHolder();
final boolean a[] = new boolean[1];
a[0] = false;
holder.addCallback(new Callback() {
#Override
public void surfaceCreated(SurfaceHolder holder) {
// TODO Auto-generated method stub
a[0] = true;
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
// TODO Auto-generated method stub
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
// TODO Auto-generated method stub
}
});
} [...]//more omitted code here
How do I create the surface for the SurfaceHolder?
Does ChartPainter extends SurfaceView?
Note: SurfaceHolder is usually used with SurfaceView. When the activity goes to the foreground and its SurfaceView is about to be rendered, WindowManager will ask SurfaceFlinger to create a new surface. Then SurfaceHolder's surfaceCreated() will be called.
I used this tutorial to create a SurfaceView for a game. The tutorial fixed the problems I had with handling the thread but now whenever I open the fragment it takes anywhere between 3 and 15 seconds for the screen to turn yellow.
I thought it might have something to with the code in the container activity but the only thing I changed is this fragment alone. The speed before the change was fine.
public class VirtualMapFragment extends Fragment {
private MapSurfaceView mapSurfaceView;
#Override
public void onResume() {
if (mapSurfaceView != null){
mapSurfaceView.surfaceRestart();
}
super.onResume();
}
#Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
if(mapSurfaceView == null)
mapSurfaceView = new MapSurfaceView(getActivity());
return mapSurfaceView;
}
#Override
public void onPause() {
if (mapSurfaceView != null){
mapSurfaceView.surfaceDestroyed(mapSurfaceView.getHolder());
}
super.onPause();
}
private class MapSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceThread surfaceThread;
public MapSurfaceView(Context context) {
super(context);
setFocusable(true);
surfaceThread = new SurfaceThread(this);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width,
int height) {
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
surfaceThread.restartSurface();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
surfaceThread.terminateSurface();
}
public void surfaceRestart(){
if (surfaceThread != null){
surfaceThread.restartSurface();
}
}
public void doDraw(Canvas canvas){
canvas.drawColor(Color.YELLOW);
}
#Override
public boolean onTouchEvent(MotionEvent event){
return false;
}
}
private class SurfaceThread implements Runnable {
private SurfaceHolder mSurfaceHolder;
private MapSurfaceView mMapSurfaceView;
private Canvas mCanvas;
volatile Thread thread;
public SurfaceThread(MapSurfaceView mapSurfaceView){
mSurfaceHolder = mapSurfaceView.getHolder();
mMapSurfaceView = mapSurfaceView;
mCanvas = new Canvas();
thread = new Thread(this);
thread.start();
}
public void terminateSurface(){
this.thread.interrupt();
}
public void restartSurface() {
if (thread.getState() == Thread.State.TERMINATED){
thread = new Thread(this);
thread.start(); // Start a new thread
}
}
public SurfaceHolder getSurfaceHolder() {
return mSurfaceHolder;
}
#Override
public void run() {
while (!Thread.currentThread().isInterrupted()) {
try {
mCanvas = mSurfaceHolder.lockCanvas(null);
if (mCanvas == null){
mSurfaceHolder = mMapSurfaceView.getHolder();
} else {
synchronized (mSurfaceHolder) {
mapSurfaceView.doDraw(mCanvas);
}
}
} finally {
if (mCanvas != null) {
mSurfaceHolder.unlockCanvasAndPost(mCanvas);
}
}
}
}
}
}
So, I have searched for an answer. Most results show how to update from outside the Layout. Here is my simplified code.
MainActivity:
public class MainActivity extends Activity{
/** Called when the activity is first created. */
#Override
public void onCreate(Bundle savedInstanceState)
{ this.requestWindowFeature(Window.FEATURE_NO_TITLE);
this.getWindow().setFlags(WindowManager.LayoutParams.FLAG_FULLSCREEN,
WindowManager.LayoutParams.FLAG_FULLSCREEN);
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
LinearLayout surface = (LinearLayout)findViewById(R.id.surface);
surface.addView(new UnitActivity(this));}}
UnitActivity:
public class UnitActivity extends SurfaceView
{
private MainThread thread;
private SurfaceHolder holder;
public UnitActivity(Context context){
super(context);touch = new MyTouchListener();
this.setOnTouchListener(touch);
thread = new MainThread(this);
holder=getHolder();
holder.addCallback(new SurfaceHolder.Callback(){
#Override
public void surfaceCreated(SurfaceHolder p1)
{
thread.setRunning(true);
thread.start();
}
#Override
public void surfaceChanged(SurfaceHolder p1, int p2, int p3, int p4)
{
// TODO: Implement this method
}
#Override
public void surfaceDestroyed(SurfaceHolder p1)
{
boolean retry = true;
while (retry)
{
try
{
thread.join();
retry = false;
}
catch(Exception e){
}
}
}
});
setFocusable(true)
}
#Override
public void onDraw(Canvas c) {
//draw to canvas here
*******Here is where I want to, in some way
make a call to add a ScrollView or
TextView to the original Layout******
}
}
Basically, my SurfaceView is updating running a Thread. I want a certain condition to trigger a TextView or ScrollView to become visible on screen. I thought maybe I could just get the Layout to run a thread and update itself, but killed my app doing so... I appreciate any help or comments.
Have been looking on some tutorials for drawing canvas using SurfaceView, but the only thing that shows up is a black background.
public class FighterActivity extends Activity implements OnTouchListener {
/** Called when the activity is first created. */
SurfaceController surface;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
surface = new SurfaceController(this);
surface.setOnTouchListener(this);
setContentView(surface);
}
#Override
protected void onPause() {
// TODO Auto-generated method stub
super.onPause();
surface.pause();
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
surface.resume();
}
public class SurfaceController extends SurfaceView implements Runnable{
Thread thread = null;
SurfaceHolder holder;
public SurfaceController(Context context) {
super(context);
// TODO Auto-generated constructor stub
holder = getHolder();
System.out.println("HERE");
}
public void run() {
// TODO Auto-generated method stub
System.out.println("Hello World2");
while(true){
if(!holder.getSurface().isValid()){
System.out.println("NOT VALID");
continue;
}
System.out.println("VALID!");
Canvas can = holder.lockCanvas();
can.drawARGB(255, 150, 150, 0);
holder.unlockCanvasAndPost(can);
}
}
public void pause(){
}
public void resume(){
}
}
public boolean onTouch(View view, MotionEvent me) {
// TODO Auto-generated method stub
return false;
}
}
It gets to the System.out.println("HERE"); and prints out HERE, but nothing more happends, In other words the thread does not get started since "Hello World2" is not printed, what is the problem?
Thanks for any help
I'm assuming you're building off of this: http://android-coding.blogspot.ca/2011/05/drawing-on-surfaceview.html
You'll notice there the onResumeMySurfaceView and onPauseMySurfaceView (resume and pause in your SurfaceController, respectively) start the actual thread. You'll need to do that in your code, too, e.g. in SurfaceController:
protected boolean running = false;
public void resume() {
running = true;
thread = new Thread(this);
thread.start();
}
I have a small application in which i implement a surface view.Now depending on some condition(time) i would like to change the screen to a different layout.How do i do this in the following code.
Sketch of what i am doing.
public class df extends Activity
{
public void onCreate(Bundle savedInstanceState) {
}
class Panel extends SurfaceView implements SurfaceHolder.Callback {
public Panel(Context context){
super(context);
}
public void onDraw(Canvas canvas) {
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
// TODO Auto-generated method stub
}
public void surfaceCreated(SurfaceHolder holder) {
}
}
public void surfaceDestroyed(SurfaceHolder holder) {
boolean retry = true;
_thread.setRunning(false);
while (retry) {
try {
_thread.join();
retry = false;
} catch (InterruptedException e) {
// we will try it again and again...
}
}
}
}