ClassCastException occurs when trying to perform a seemingly valid explicit cast - android

I'm trying to build this simple game, and I keep encountering a ClassCastException when trying to cast my my SurfaceView into a PuzzleSurfaceView (which extends SurfaceView).
package com.scf.android.CAPuzzle;
import android.app.Activity;
import android.os.Bundle;
import android.view.View;
public class CAPuzzleActivity extends Activity {
PuzzleSurfaceView puzzleSurfaceView;
View.OnClickListener puzzleClickListener;
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.main);
puzzleSurfaceView = (PuzzleSurfaceView)findViewById(R.id.puzzleSurfaceView);
puzzleClickListener = new View.OnClickListener() {
public void onClick(View v) {
}
};
}
}
And the PuzzleSurfaceView class:
package com.scf.android.CAPuzzle;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
class PuzzleSurfaceView extends SurfaceView implements SurfaceHolder.Callback {
Bitmap live;
Bitmap dead;
public PuzzleSurfaceView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
#Override
public void onDraw(Canvas c) {
c.drawBitmap(live, 0, 0, null);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2,
int arg3) {
// TODO Auto-generated method stub
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
// TODO Auto-generated method stub
live = BitmapFactory.decodeResource(getResources(), R.drawable.icon);
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
// TODO Auto-generated method stub
}
}
Please advise... I've been banging my head against the wall for hours now...
My main.xml:
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:orientation="vertical"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
>
<SurfaceView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/puzzleSurfaceView"></SurfaceView>
<SurfaceView android:layout_height="wrap_content" android:layout_width="fill_parent" android:id="#+id/solutionSurfaceView"></SurfaceView>
</LinearLayout>

You will need to instantiate your class and add it to the layout. You can't simply cast. Casting only works when casting to the same or parent classes or interfaces. You could also make it a custom component as detailed here and use your PuzzleSurfaceView in your main.xml

You must replace one row in main.xml to following:
<com.scf.android.CAPuzzle.PuzzleSurfaceView android:layout_width="fill_parent" android:layout_height="wrap_content" android:id="#+id/puzzleSurfaceView"></com.scf.android.CAPuzzle.PuzzleSurfaceView>
and add constructor
PuzzleSurfaceView(Context context, AttributeSet attrs)
at your PuzzleSurfaceView class.

Related

I would like to know how to draw using canvas over my XML layout

I've created a custom XML layout and I’m trying to draw the map background and the pawn player( the bitmap) over it.
Instead, its painting the pawn player over a white background without the map background that I put as the background on the XML file.
MyViev Class:
package com.example.alpha;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.util.AttributeSet;
import android.view.View;
public class MyView extends View {
Bitmap playerW;
float changingY;
float changingX;
public MyView(Context context) {
super(context);
playerW = BitmapFactory
.decodeResource(getResources(), R.drawable.black);
changingY=0;
// TODO Auto-generated constructor stub
}
#Override
protected void onDraw(Canvas canvas) {
// TODO Auto-generated method stub
super.onDraw(canvas);
canvas.drawBitmap(playerW,4+changingX, (canvas.getHeight())-288-changingY, null);
}
public MyView(Context context, AttributeSet attrs, int defStyleAttr) {
super(context, attrs, defStyleAttr);
// TODO Auto-generated constructor stub
}
public MyView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
}
my MainActivity Class:
package com.example.alpha;
import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
public class MainActivity extends ActionBarActivity {
MyView ourView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
ourView = new MyView(this);
setContentView(ourView);
}
}
My XML file:
<?xml version="1.0" encoding="utf-8"?>
<view class="com.example.alpha.MyView"
xmlns:android="http://schemas.android.com/apk/res/android"
android:id="#+id/myView"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:background="#drawable/mapeasy"
/>
It's because you're not actually setting it to use your XML layout. Instead, you've set the content View to be a new instance of MyView, which doesn't have the XML background property set.
Therefor you have 2 options:
Option 1: Call ourView.setBackgroundDrawable(R.drawable.mapeasy); after you created a new instance of MyView.
or
Option 2: Set the content View to be your actual layout file and then find your MyView by using findViewById(int).
Eg.
public class MainActivity extends ActionBarActivity {
MyView ourView;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.your_layout_file);
ourView = (MyView)findViewById(R.id.myView);
}
}

Set an image as background android, using canvas

My app consist on moving a picture when the user speaks. I have done this, but what I want to do now is that I want to set a image as background for my app. I am working with canvas, as you can see in the class I have included below. So how can I set a background using canvas and not influencing the movement of my picture. Or is there any possibility to connect this class with a xml file where I can define the background?
Thanks in advance
Here is the class:
package com.example.prova1;
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.hardware.SensorManager;
import android.os.Bundle;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
public class MoveBalloon extends Activity {
Bitmap balloon;
DrawBalloon myView;
float x,y,sensorX, sensorY;
SensorManager sm;
Microphone mic;
public class DrawBalloon extends SurfaceView implements Runnable {
SurfaceHolder ourHolder ;
Thread ourThread = null;
boolean isRunning=true;
public DrawBalloon(Context context) {
super(context);
ourHolder= getHolder();
}
public void pause() {
isRunning=false;
while(true){
try{
ourThread.join();
} catch (InterruptedException e){
e.printStackTrace();
}
break;
}
ourThread=null;
}
public void resume(){
isRunning=true;
ourThread = new Thread(this);
ourThread.start();
}
#Override
public void run (){
while(isRunning){
if(!ourHolder.getSurface().isValid())
continue;
Canvas canvas = ourHolder.lockCanvas();
updateMic();
canvas.drawColor(Color.BLACK);
canvas.drawBitmap(balloon, sensorX, sensorY,null);
ourHolder.unlockCanvasAndPost(canvas);
}
}
}
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
/*sm= (SensorManager) getSystemService(Context.SENSOR_SERVICE);
if(sm.getSensorList(Sensor.TYPE_ACCELEROMETER).size()!=0){
Sensor s = sm.getSensorList(Sensor.TYPE_ACCELEROMETER).get(o);
sm.registerListener(this,s ,SensorManager.SENSOR_DELAY_NORMAL);
}*/
mic = new Microphone();
balloon = BitmapFactory.decodeResource(getResources(), R.drawable.images);
sensorX=150;
sensorY=350;
//x=y=sensorX=sensorY=0;
myView= new DrawBalloon (this);
myView.resume();
setContentView(myView);
}
/*#Override
public void onAccuracyChanged(Sensor sensor, int accuracy) {
// TODO Auto-generated method stub
}
#Override
public void onSensorChanged(SensorEvent event) {
// TODO Auto-generated method stub
try {
Thread.sleep(20);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sensorX=event.values[0];
sensorY=event.values[1];
}
*/
public void updateMic(){
int level = mic.getLevel();
sensorY-=level;
}
#Override
public void onBackPressed() {
finish();
}
}
You can use an xml layout instead of setting content view with a java object :
setContentView(R.layout.move_balloon);
and add your custom view (DrawBalloon) in the xml layout by specifying it's package location, and change the background by setting an image to the background of the root element :
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context=".MoveBalloon"
android:background="#drawable/ic_launcher"
>
<com.example.prova1.MoveBalloon.DrawBalloon
android:id="#+id/drawBalloon1"
android:layout_width="match_parent"
android:layout_height="match_parent"
android:layout_alignParentTop="true"
android:layout_centerHorizontal="true"
android:layout_marginTop="182dp" />
</RelativeLayout>
but for this to work , your custom view must have a special constructor in able to be inflated from xml layout file :
public DrawBalloon(Context context, AttributeSet attrs) {
super(context, attrs);
ourHolder= getHolder();
}

multiple intent's starting by onTouch event

Hey guys i am getting to start an intent if a user clicks on specific location.at first touch he opens a menu and on second he opens the activity.The problem is that many copy's of same intent are started
import android.app.Activity;
import android.content.Context;
import android.content.Intent;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Paint.Align;
import android.os.Bundle;
import android.text.TextPaint;
import android.view.MotionEvent;
import android.view.View;
import android.view.View.OnTouchListener;
import android.widget.Toast;
public class gfx extends Activity implements OnTouchListener{
Bitmap a,b;
gfx1 drw;
String a1;
boolean flag=false,flag1=false,flag2=false;
Canvas c1;
float x=0,y=0,z=0,bitx=0,bity=0;
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
drw = new gfx1(this);
drw.setOnTouchListener(this);
setContentView(drw);
}
public class gfx1 extends View implements Runnable {
public gfx1(Context context) {
super(context);
// TODO Auto-generated constructor stub
a = BitmapFactory.decodeResource(getResources(),
R.drawable.greenball);
}
void callin(String a1)
{
Intent inte = new Intent(a1);
startActivity(inte);
}
#Override
protected void onDraw(Canvas c1) {
// TODO Auto-generated method stub
super.onDraw(c1);
c1.drawColor(Color.YELLOW);
b=Bitmap.createScaledBitmap(a,c1.getWidth()/3, c1.getHeight()/3, true);
bitx=(c1.getWidth()/2)-(a.getWidth()/2);
bity=(c1.getHeight()/2)-(a.getHeight()/2);
c1.drawBitmap(a, bitx, bity, null);
Paint textPaint = new Paint();
textPaint.setARGB(50, 254, 10, 50);
textPaint.setTextAlign(Align.CENTER);
textPaint.setTextSize(30);
if(flag)
{
c1.drawText("clicked",300, 300,textPaint);
c1.drawBitmap(b,(c1.getWidth()/2)-(b.getWidth()/2),(c1.getHeight()/2)+(a.getHeight()/2), null);
c1.drawBitmap(b,(c1.getWidth()/2)-(b.getWidth()/2),(c1.getHeight()/2)-(a.getHeight()/2)-(b.getHeight()), null);
}
float bitbx1=(c1.getWidth()/2)-(b.getWidth()/2);
float bitbx2=(c1.getWidth()/2)+(b.getWidth()/2);
float bitby1=(c1.getHeight()/2)-(b.getHeight())-(a.getHeight()/2);
float bitby2=((c1.getHeight()/2)-(a.getHeight()/2));
if(flag2)
{
c1.drawText("Opening...please wait", 600, 600, textPaint);
flag1=true;
if(flag1)
{
a1="com.example.claci.MAINACTIVITY";
callin(a1);
}
flag1=false;
}
if((x>bitx&&x<bitx+(a.getWidth()))&& (y>bity&&y<bity+(a.getHeight())))
{
flag=true;
}
if((x>bitbx1&&x<bitbx2)&&(y>bitby1&&y<bitby2))
{
if(flag)
{
flag2=true;
}
}
invalidate();
}
#Override
public void run() {
// TODO Auto-generated method stub
}
}
#Override
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
switch(event.getAction()){
case MotionEvent.ACTION_DOWN:
x=event.getX();
y=event.getY();
break;
}
return true;
}
}
A much better structure would be to have your menu creation, and subsequent activity creation called from onTouch method. As psink mentioned, that is not the proper use of onDraw, and it unnecessarily links tow very unrelated things.
I would also use two class variables-- one that is a flag for if the menu exists yet, and another that is a reference to the newly created activity. If an activity already exists, you don't create another one. When the existent activity completes, though, it needs to return a result to this activity so you can clear that reference and be ready to create a new one when needed.

android XML Error inflating class

I am trying to overlay a drawing on top of a camera preview. I made two custom class extended from SurfaceView: one for the overlay, and one for the cam.
Here is my logcat (only the "Caused by" statements) :
04-11 19:58:06.549: W/dalvikvm(867): threadid=1: thread exiting with uncaught exception (group=0x40a71930)
04-11 19:58:06.609: E/AndroidRuntime(867): Caused by: android.view.InflateException: Binary XML file line #5: Error inflating class com.example.gui_v9.Activity1.CamView
04-11 19:58:06.609: E/AndroidRuntime(867): Caused by: java.lang.ClassNotFoundException: Didn't find class "com.example.gui_v9.Activity1.CamView" on path: /data/app/com.example.gui_v9-2.apk
The second error where it cannot find the class, is because it did not inflate.
Eclipse Graphical Layout successfully compiles the xml code and gives a decent preview. Here is my XML code:
<?xml version="1.0" encoding="utf-8"?>
<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent">
<com.example.gui_v9.Activity1.CamView
android:id="#+id/camview"
android:layout_width="fill_parent"
android:layout_height="fill_parent"/>
<com.example.gui_v9.Activity1.OverlayView
android:id="#+id/overlay"
android:layout_width="200dp"
android:layout_height="200dp"/>
</FrameLayout>
I tried to change the flags from
<com.example.gui_v9.Activity1.OverlayView .../>
to
<com.example.gui_v9.Activity1.OverlayView ...></com.example.gui_v9.Activity1.OverlayView>
or to
<SurfaceView class="com.example.gui_v9.Activity1$OverlayView" ... />
or even
<SurfaceView class="com.example.gui_v9.Activity1$OverlayView" ... ></SurfaceView>
without luck. In the latter case, I have a casting problem (CamView cannot be casted in SurfaceView) and Eclipse's XML Graphical Layout fails to render, so I m guessing that the first one takes me further in the compiling process.
You may also take a look at my main activity:
package com.example.gui_v9;
import java.io.IOException;
import android.os.Bundle;
import android.util.AttributeSet;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.app.Activity;
import android.content.Context;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.PixelFormat;
import android.hardware.Camera;
public class Activity1 extends Activity {
CamView camview = null;
OverlayView overlay = null;
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity1);
camview = (CamView) findViewById(R.id.camview);
overlay = (OverlayView) findViewById(R.id.overlay);
overlay.getHolder().setFormat(PixelFormat.TRANSLUCENT);
}
public static class CamView extends SurfaceView implements SurfaceHolder.Callback {
Camera cam = null;
SurfaceHolder camviewholder = null;
public CamView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public CamView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public CamView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
if (cam!=null) {
try {
cam.setPreviewDisplay(camviewholder);
}
catch (IOException e) {
}
cam.startPreview();
}
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
cam = Camera.open();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
cam.stopPreview();
cam.release();
}
}
public static class OverlayView extends SurfaceView implements SurfaceHolder.Callback {
private Paint paint = new Paint();
OverlayThread overlaythread = null;
public OverlayView(Context context) {
super(context);
// TODO Auto-generated constructor stub
}
public OverlayView(Context context, AttributeSet attrs) {
super(context, attrs);
// TODO Auto-generated constructor stub
}
public OverlayView(Context context, AttributeSet attrs, int defStyle) {
super(context, attrs, defStyle);
// TODO Auto-generated constructor stub
}
#Override
public void onDraw(Canvas canvas) {
paint.setColor(Color.BLUE);
canvas.drawCircle(100, 100, 100, paint);
}
#Override
public void surfaceChanged(SurfaceHolder arg0, int arg1, int arg2, int arg3) {
}
#Override
public void surfaceCreated(SurfaceHolder arg0) {
setWillNotDraw(false); //Allows us to use invalidate() to call onDraw()
overlaythread = new OverlayThread(getHolder(), this);
overlaythread.setRunning(true);
overlaythread.start();
}
#Override
public void surfaceDestroyed(SurfaceHolder arg0) {
try {
overlaythread.setRunning(false);
overlaythread.join();
}
catch (InterruptedException e) {
}
}
}
public static class OverlayThread extends Thread {
private OverlayView overlay;
private SurfaceHolder overlayholder;
private boolean _run = false;
public OverlayThread(SurfaceHolder _overlayholder, OverlayView _overlay) {
overlayholder = _overlayholder;
overlay = _overlay;
}
public void setRunning(boolean run) {
_run = run;
}
#Override
public void run() {
Canvas c;
while (_run) {
c = null;
try {
c = overlayholder.lockCanvas(null);
synchronized (overlayholder) {
overlay.invalidate();
}
}
finally {
if (c != null) {
overlayholder.unlockCanvasAndPost(c);
}
}
}
}
}
}
As you can see, I have the three constructors for each classes (with 1,2 and 3 arguments) which is a common error in inflating class failure.
I got this to work when I implemented CamView and OverlayView in two separate classes (CamView.java and OverlayView.java), respectively. So I don't understand why importing classes makes it work. Maybe something with the static workspace?
Thank yall for your help!

not able to link SurfaceViewExample to MainActivity

In DrawingTheBall class making some animation stuff..
In SUrfaceViewExample class Touchevent will be detecetd..
my problem is i am not able to link MainActivity and SurtfaceViewExample ..
no issues with DrawingTheBall..
MAIN CLASS:...
package maddy.first;
import android.app.Activity;
import android.os.Bundle;
public class Madhu1Activity extends Activity {
/** Called when the activity is first created. */
Drwwingtheball v;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
v = new Drawingtheball(this);
setContentView(v);
}
}
CLASS SurfaceViewExample:
package maddy.first;
import android.app.Activity;
import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.BitmapFactory;
import android.graphics.Canvas;
import android.os.Bundle;
import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;
import android.view.View.OnTouchListener;
public class SurfaceViewExample extends Activity implements OnTouchListener{
OurView v;
Bitmap ball;
float x,y;
#Override
protected void onCreate(Bundle savedInstanceState) {
// TODO Auto-generated method stub
super.onCreate(savedInstanceState);
v=new OurView(this);
v.setOnTouchListener(this);
ball=BitmapFactory.decodeResource(getResources(),R.drawable.tennis_ball);
x = y = 0;
setContentView(v);
}
#Override
protected void onResume() {
// TODO Auto-generated method stub
super.onResume();
v.resume();
}
public class OurView extends SurfaceView implements Runnable{
Thread t;
SurfaceHolder holder;
boolean isItOk=false;
public OurView(Context context) {
super(context);
// TODO Auto-generated constructor stub
holder=getHolder();
}
public void run() {
// TODO Auto-generated method stub
while( isItOk ==true)
{
//drawing
if(holder.getSurface().isValid()) {
continue;
}
Canvas c=holder.lockCanvas();
c.drawARGB(255,150,150,10);
c.drawBitmap(ball, x-(ball.getWidth()), y-(ball.getHeight()), null);
holder.unlockCanvasAndPost(c);
}
}
public void pause()
{
isItOk=false;
while(true) {
try {
t.join();
}catch(InterruptedException e) {
e.printStackTrace();
}
break;
}
}
public void resume()
{
isItOk=true;
t=new Thread(this);
t.start();
}
}
public boolean onTouch(View v, MotionEvent event) {
// TODO Auto-generated method stub
return false;
}
}
Class DrawingTheBall:
package maddy.first;
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.view.View;
public class DrawingTheBall extends View {
Bitmap bball;
int x,y;
public DrawingTheBall(Context context) {
super(context);
bball=BitmapFactory.decodeResource(getResources() ,R.drawable.tennis_ball);
x = 0;
y = 0;
}
protected void onDraw(Canvas canvas)
{
super.onDraw(canvas);
Rect ourRect=new Rect();
ourRect.contains( 0, 0,canvas.getWidth(),canvas.getHeight()/2);
Paint blue=new Paint();
blue.setColor(Color.RED);
blue.setStyle(Paint.Style.FILL);
canvas.drawRect(ourRect, blue);
if(x < canvas.getWidth())
x+=10;
else
x=0;
if(y<canvas.getHeight())
y+=10;
else
y=0;
Paint p=new Paint();
canvas.drawBitmap(bball,x,y,p);
invalidate();
}
}
}
Your question is not clear. What actually do you want to link?
You want to start activity from another another?
Or you want to pass some parameter from one to another activity?
If you want to run SurfaceViewExample activity from Main activity -
This is the code -
startActivity(new Intent(this, SurfaceViewExample.class)
finish();
And AndroidManifest.xml file should be -
<application
android:icon="#drawable/ic_launcher"
android:label="#string/app_name" >
<activity
android:name="Madhu1Activity"
android:label="#string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" />
<category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
<activity android:name="SurfaceViewExample"></activity>
</application>
And if you want to pass parameter from one activity to another -
This is the code -
startActivity(new Intent(this, SurfaceViewExample.class)
.putExtra("key", [value])); // if you want to pass class the class should be Serializable, otherwise you can pass value like a hash map.
//in other activity convert it to class-
<classname> obj = (<classname>)getIntent().getSerializableExtra("key");
If this are not sufficient then tell me what actually want.
Enjoy..
I think it throws some exception otherwise your layout has some error, so that it is unable to set the content view.
This is the easiest way to keep your SurfaceViewExample class as main activity follow it -
goto application AndroidManifest.xml file and then -
Application tab -> select launch activity(that is your main activity) ->
Name*(right side) -> browse(take for a while to loading activity list) - >
select SurfaceViewExample -> remove previous SurfaceViewExample activity if already added.
set a default layout in SurfaceViewExample setContentView(layout.main); // if it exists
And run your application to check it is able to show your layout.
If it can run successfully, then check out your DrawingTheBall code.
Have fun...

Categories

Resources