I'm a noobie in android dev and I'm having a issue. I'm trying to make a simple game using SurfaceView. But surfaceCreated is never called when I'm launching the app.
I'm using his answer to use less ram with the background
Here is where the setcontentView is placed:
call_surfaceView = new class_surfaceView(cMainActivity);
// Setup your SurfaceView
SurfaceView surfaceView = call_surfaceView; // use any SurfaceView you want
surfaceView.setZOrderOnTop(true);
surfaceView.getHolder().setFormat(PixelFormat.TRANSPARENT);
// Setup your ImageView
ImageView bgImagePanel = new ImageView(cMainActivity);
bgImagePanel.setBackgroundResource(R.drawable.background); // use any Bitmap or BitmapDrawable you want
// Use a RelativeLayout to overlap both SurfaceView and ImageView
RelativeLayout.LayoutParams fillParentLayout = new RelativeLayout.LayoutParams(RelativeLayout.LayoutParams.MATCH_PARENT, RelativeLayout.LayoutParams.MATCH_PARENT);
RelativeLayout rootPanel = new RelativeLayout(cMainActivity);
rootPanel.setLayoutParams(fillParentLayout);
rootPanel.addView(bgImagePanel, fillParentLayout);
rootPanel.addView(surfaceView, fillParentLayout);
setContentView(rootPanel);
and here is my surfaceView code:
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.PorterDuff;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class class_surfaceView extends SurfaceView implements SurfaceHolder.Callback {
Thread t;
Canvas c;
SurfaceHolder holder;
Bitmap ghost;
Bitmap lifebar;
Bitmap player;
Bitmap sol;
Bitmap tombe;
public class_surfaceView(Context context) {
super(context);
holder = getHolder();
Log.d("Essai", "Class_surfaceView");
}
public void surfaceCreated(SurfaceHolder holder) {
Log.d("Essai", "surfaceCreated");
new Thread(new Runnable() {
#Override
public void run() {
lauch_game();
}
}).start();
}
#Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {
}
#Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
}
public void lauch_game() {
ghost = BitmapFactory.decodeResource(getResources(),R.drawable.ghost);
c = holder.lockCanvas();
if(c != null){
c.drawColor(0, PorterDuff.Mode.CLEAR);
c.drawBitmap(ghost,0,0,null);
holder.unlockCanvasAndPost(c);
} else {
Log.d("DEBUG","c is null");
}
Log.d("Essai", "Essais de dessin");
}
}
Thanks for helping !
In your class_surfaceView constructor after holder = getHolder(), you must call holder.addCallback(this) to register the callback.
Try to use #Override above method
Related
I am trying to write a simple app that displays a coloured circle which fades to black as it gets further from the centre of the screen. However, whenever I click the app, it crashes. When I remove the onClick code the app runs fine. The only error I can find in logcat is:
Fatal signal 11 (SIGSEGV), code 1, fault addr 0x94 in tid 11955 (raphicstutorial)
And I don't know what to do with that.
Code below:
package com.example.a2dgraphicstutorial;
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.os.Bundle;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends AppCompatActivity {
public class MyView extends View {
private Canvas thisCanvas;
private int colourID;
private Paint fillPaint = new Paint();
public MyView(Context context){
super(context);
colourID = 0;
fillPaint.setStyle(Paint.Style.FILL);
}
public void drawCircle(){
int x = getWidth();
int y = getHeight();
//Drawing the circles
for (int i = 255;i >= 0;i--){
//Determining colour
if (colourID == 0){
fillPaint.setColor(Color.argb(255,255-i,0,0));
}
else if (colourID == 1){
fillPaint.setColor(Color.argb(255,0,255-i,0));
}
else if (colourID == 2){
fillPaint.setColor(Color.argb(255,0,0,255-i));
}
thisCanvas.drawCircle(x/2,y/2,i,fillPaint);
}
//Cycling the colourID so the next circle will be a different colour
colourID = (colourID + 1)%3;
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
thisCanvas = canvas;
//Setting the background to be black
fillPaint.setColor(Color.parseColor("#000000"));
thisCanvas.drawPaint(fillPaint);
//Drawing the first circle
drawCircle();
}
}
MyView theScreen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theScreen = new MyView(this);
theScreen.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
theScreen.drawCircle();
}
});
setContentView(theScreen);
}
}
Instead of overriding the onCreate()
Override onTouchEvent() and listen to a click:
#Override
public boolean onTouchEvent(MotionEvent event) {
super.onTouchEvent(event);
switch (event.getAction()) {
case MotionEvent.ACTION_DOWN:
//the finger is down do something.....
return true;
case MotionEvent.ACTION_UP:
//the finger is up do something.....(this is a click)
//to redraw
invalidate();
return true;
}
return false;
}
By the way:
To trigger the onDraw(), call this after a click:
invalidate();
One upon a time I had a problem similar to this
and the solutions was to replace "this" by "the name of activity".class
// replace this to theScreen = new MyView(this);
theScreen = new MyView(MainActivity.class);
Another solution is to replace this By "getBaseContext()"
// replace this to theScreen = new MyView(this);
theScreen = new MyView(getBaseContext());
this the context returns the current context of the activity, belong to the activity, the activity is destroyed then it will destroy also.
getBaseContext() is the method of ContextWrapper Which is "Proxying implementation of Context that simply delegates all of its calls to another Context. Can be subclassed to modify behaviour
without changing the original Context."
That error occurs when you call the Canvas outside of the onDraw method, try this code
import androidx.appcompat.app.AppCompatActivity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Point;
import android.os.Bundle;
import android.view.Display;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnClickListener;
public class MainActivity extends AppCompatActivity {
public class MyView extends View {
private Canvas thisCanvas;
private int colourID;
private Paint fillPaint = new Paint();
public MyView(Context context){
super(context);
colourID = 0;
fillPaint.setStyle(Paint.Style.FILL);
}
#Override
protected void onDraw(Canvas canvas){
super.onDraw(canvas);
thisCanvas = canvas;
//Setting the background to be black
fillPaint.setColor(Color.parseColor("#000000"));
thisCanvas.drawPaint(fillPaint);
int x = getWidth();
int y = getHeight();
//Drawing the circles
for (int i = 255;i >= 0;i--){
//Determining colour
if (colourID == 0){
fillPaint.setColor(Color.argb(255,255-i,0,0));
}
else if (colourID == 1){
fillPaint.setColor(Color.argb(255,0,255-i,0));
}
else if (colourID == 2){
fillPaint.setColor(Color.argb(255,0,0,255-i));
}
thisCanvas.drawCircle(x/2,y/2,i,fillPaint);
}
//Cycling the colourID so the next circle will be a different colour
colourID = (colourID + 1)%3;
}
}
MyView theScreen;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
theScreen = new MyView(this);
theScreen.setOnClickListener(new OnClickListener(){
#Override
public void onClick(View v){
theScreen.invalidate();
}
});
setContentView(theScreen);
}
}
I moved the drawCircle method to inside the onDraw and change theScreen from calling drawCircle to call invalidate() instead, I'm not sure it's the result you want but at least that's the issue of the error.
Hye there I'm new to OpenCV but somehow good at Android! I have edited a code to change the Camera Background. For the Image to Set at the Background; I have been successfully done with it! Now the problem is that the ImageView comes over the camera screen! I just want my ImageView to come under the Camera I mean at the back of my camera! My code that I'm using is:
import android.util.Log;
import java.io.IOException;
import android.app.Activity;
import android.content.pm.ActivityInfo;
import android.content.res.Resources;
import android.graphics.PixelFormat;
import android.hardware.Camera;
import android.os.Bundle;
import android.view.LayoutInflater;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.ViewGroup.LayoutParams;
import android.widget.ImageView;
import android.graphics.Canvas;
import android.graphics.drawable.Drawable;
import java.util.Random;
public class CustomCameraActivity extends Activity implements SurfaceHolder.Callback {
Camera camera;
SurfaceView surfaceView;
SurfaceHolder surfaceHolder;
boolean previewing = false;
LayoutInflater controlInflater = null;
private static final String TAG = "Svetlin SurfaceView";
private ImageView image;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
getWindow().setFormat(PixelFormat.UNKNOWN);
surfaceView = (SurfaceView)findViewById(R.id.camerapreview);
surfaceHolder = surfaceView.getHolder();
surfaceHolder.addCallback(this);
surfaceHolder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
controlInflater = LayoutInflater.from(getBaseContext());
View viewControl = controlInflater.inflate(R.layout.custom, null);
LayoutParams layoutParamsControl = new LayoutParams(LayoutParams.FILL_PARENT,
LayoutParams.FILL_PARENT);
this.addContentView(viewControl, layoutParamsControl);
image=(ImageView)findViewById(R.id.myimage);
image.setAlpha(150);
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
if(previewing){
camera.stopPreview();
previewing = false;
}
if (camera != null){
try {
camera.setPreviewDisplay(surfaceHolder);
camera.startPreview();
previewing = true;
} catch (IOException e) {
e.printStackTrace();
}
}
}
#Override
public void surfaceCreated(SurfaceHolder holder) {
camera = Camera.open();
Camera.Parameters params = camera.getParameters();
params.setSceneMode(Camera.Parameters.SCENE_MODE_SUNSET);
//ImageView overlay = (ImageView) findViewById(R.id.ImageView01);
//overlay.bringToFront();
camera.setParameters(params);
// tryDrawing(holder);
}
#Override
public void surfaceDestroyed(SurfaceHolder holder) {
camera.stopPreview();
camera.release();
camera = null;
previewing = false;
}
private void tryDrawing(SurfaceHolder holder) {
Log.i(TAG, "Trying to draw...");
Canvas canvas = holder.lockCanvas();
if (canvas == null) {
Log.e(TAG, "Cannot draw onto the canvas as it's null");
} else {
drawMyStuff(canvas);
holder.unlockCanvasAndPost(canvas);
}
}
private void drawMyStuff(final Canvas canvas) {
Random random = new Random();
Log.i(TAG, "Drawing...");
canvas.drawRGB(255, 128, 128);
}
}
The White Image Should Come Behind the Camera as you can see in the screen shot!
The thing is I just need to know that how can I change the Camera Background doing so! Please give me Hints or any Idea so that can help me. THANKS IN ADVANCE!
I saw this one from here. And I just want to try if it is working.
Link: http://www.javacodegeeks.com/2011/03/android-http-camera-live-preview.html
This is the first class called MyCamAppActivity.java
package com.javacodegeeks.android.camera;
import android.app.Activity;
import android.os.Bundle;
import android.view.SurfaceView;
import android.view.Window;
public class MyCamAppActivity extends Activity {
private SurfaceView cameraPreview;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
cameraPreview = new CameraPreview(this);
setContentView(cameraPreview);
}
}
And this is the 2nd class called the CameraPreview
package com.javacodegeeks.android.camera;
import android.content.Context;
import android.hardware.Camera;
import android.util.Log;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class CameraPreview extends SurfaceView implements SurfaceHolder.Callback {
private SurfaceHolder holder;
private Camera camera;
public CameraPreview(Context context) {
super(context);
holder = getHolder();
holder.addCallback(this);
holder.setType(SurfaceHolder.SURFACE_TYPE_PUSH_BUFFERS);
}
#Override
public void surfaceChanged(SurfaceHolder holder2, int format, int w, int h) {
Camera.Parameters parameters = camera.getParameters();
parameters.setPreviewSize(w, h);
camera.setParameters(parameters);
camera.startPreview();
}
#Override
public void surfaceCreated(SurfaceHolder holder1) {
try {
camera = Camera.open();
camera.setPreviewDisplay(holder1);
}
catch (Exception e) {
Log.i("Exception surfaceCreated()", "e=" + e);
camera.release();
camera = null;
}
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
camera.stopPreview();
camera.release();
camera = null;
}
}
As far as I know, when you use surfaceview in android programming it automatically generated the picture on your screen. But in my case, it's just plain black picture. Btw, the complete package in the site doesn't have any .xml contents in it. So, I don't know if I still have to fix something in the xml. Hope someone or any of you could help me ASAP.
I've been trying to follow the tutorial here:
http://www.edu4java.com/en/androidgame/androidgame2.html
But have hit a snag. For some reason, eclipse doesn't recognise getHolder() and gives me the following error:
The method getHolder() is undefined for the type GameView
And the following solutions:
Change to getHandler(...);
Create method getHolder()
The code is pretty much the same as the tutorial, but here is what I have anyway:
package com.example.killthemall;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceHolder.Callback;
import android.view.SurfaceView;
import android.view.View;
public class GameView extends View {
private Bitmap bmp;
private SurfaceHolder holder;
public GameView(Context context) {
super(context);
holder = getHolder();
holder.addCallback(new Callback() {
public void surfaceDestroyed(SurfaceHolder holder) {
}
public void surfaceCreated(SurfaceHolder holder) {
Canvas c = holder.lockCanvas(null);
onDraw(c);
holder.unlockCanvasAndPost(c);
}
public void surfaceChanged(SurfaceHolder holder, int format,
int width, int height) {
}
});
bmp = BitmapFactory.decodeResource(getResources(), R.drawable.ic_launcher);
}
#Override
protected void onDraw(Canvas canvas) {
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(bmp, 10, 10, null);
}
}
getHolder() is a method of SurfaceView, and you're extending View. Change to:
public class GameView extends SurfaceView {
I am an amateur programmer, and have been playing around with android development. I am currently trying my hand at generating a fractal heightmap. In order to test if teh map is generating properly I need to be able to draw the map to the screen. This is where I've been running into trouble.
Here's the code for my MainActivity, DrawMap class (where my onDraw() is), and my CanvasThread() class.
Main Activity:
package com.psstudios.HMG;
import android.app.*;
import android.os.*;
import android.view.*;
import android.widget.*;
import android.view.View.OnClickListener;
import android.util.Log;
public class MainActivity extends Activity
{
/** Called when the activity is first created. */
Button Startgen = null;
Boolean run=true;
private void log(String text) {
Log.d("heightmap",text);
AppendLog app = new AppendLog(text);
}
#Override
public void onCreate(Bundle savedInstanceState)
{
super.onCreate(savedInstanceState);
requestWindowFeature(Window.FEATURE_NO_TITLE);
setContentView(R.layout.main);
Startgen = (Button) findViewById(R.id.startgen);
log("loop");
Startgen.setOnClickListener(new View.OnClickListener(){
public void onClick(View v){
log("Starting world generation");
WorldGen world=new WorldGen(200,200);
log("World generation complete, drawing heightmap");
setContentView(new DrawMap(MainActivity.this, world));
log("Went too far");
}
});
run=false;
}
}
DrawMap:
package com.psstudios.HMG;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Bitmap;
import android.graphics.Bitmap.*;
import android.graphics.Paint;
import android.graphics.Color;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.util.Log;
import android.util.*;
public class DrawMap extends SurfaceView implements SurfaceHolder.Callback
{
int drawtype=1; //variable for which type of map to draw
Bitmap drawbitmap=null;
CanvasThread canvasThread=null;
Boolean run= true;
int Worldx=200;
int Worldy=200;
WorldGen _world=null;
public void log(String text){
Log.d("Heightmap", text);
AppendLog app = new AppendLog(text);
}
public void init(){
log("init();");
canvasThread=new CanvasThread(getHolder(), this);
setFocusable(true);
log("Post-CanvasThread");
}
public DrawMap(Context context){
super(context);
log("DrawMap(Context context)");
getHolder().addCallback(this);
init();
}
public DrawMap(Context context, AttributeSet attrs) {
super(context, attrs);
log("DrawMap(Context context, AttributeSet attrs)");
getHolder().addCallback(this);
init();
}
public DrawMap(Context context,WorldGen world){
super(context);
log("DrawMap(Context context, WorldGen world)");
getHolder().addCallback(this);
_world=world;
init();
}
#Override
public void surfaceChanged(SurfaceHolder holder, int format,int width, int height){
log("surfaceChanged()");
}
#Override
public void surfaceCreated(SurfaceHolder holder){
log("Surface Created");
canvasThread.setRunning(true);
canvasThread.run();
}
#Override
public void surfaceDestroyed(SurfaceHolder holder){
log("Surface Destroyed");
Boolean retry = true;
canvasThread.setRunning(false);
while(retry){
try {
canvasThread.join();
retry=false;
} catch (InterruptedException e) {
//we will try again and again
}
}
}
#Override
public void onDraw(Canvas canvas){
log("onDraw()");
Paint paint = new Paint();
Paint paint2 = new Paint();
//canvas.drawColor(Color.BLACK);
paint.setColor(Color.WHITE);
paint.setStrokeWidth(10);
paint2.setColor(Color.BLUE);
for(int x=0; x<Worldx-1; x++){
for(int y=0; y<Worldy-1; y++){
//log(x + " : " + y);
canvas.drawPoint(x+20, y+20, paint);
canvas.drawPoint(x+220, y+220, paint2);
}
}
}
}
CanvasThread:
package com.psstudios.HMG;
import android.graphics.Canvas;
import android.view.*;
import android.util.Log;
public class CanvasThread extends Thread
{
private SurfaceHolder _surfaceHolder;
private DrawMap _drawMap;
private Boolean _run = false;
private void log(String text){
Log.d("HeightmapGen",text);
AppendLog app = new AppendLog(text);
}
public CanvasThread(SurfaceHolder surfaceHolder, DrawMap drawMap){
_surfaceHolder=surfaceHolder;
_drawMap=drawMap;
log("CanvasThread()");
}
public void setRunning(Boolean run){
log("setRunning()");
_run=run;
}
#Override
public void run() {
log("run()");
Canvas c;
while(_run){
c=null;
try{
c=_surfaceHolder.lockCanvas(null);
synchronized (_surfaceHolder) {
_drawMap.onDraw(c);
}
} finally {
if(c != null){
_surfaceHolder.unlockCanvasAndPost(c);
}
}
}
}
}
The program makes it to the onDraw(); function, and runs through the for loop, but nothing is showing up on the screen. I imagine I'm missing something pretty stupid, but I cannot seem to figure out what's wrong.
Thanks in advance for any help you guys can give me.