Search code examples
androidandroid-layoutandroid-viewandroid-custom-view

Custom View Fatal Exception


I got some big troubles getting a simple app together (I'm also new in Android Development)

The problem is, i have 4 activities. The first one is the MainActivity with some Buttons on it to go to the next activity.

In this Activity a person need to shake his mobile device to get to the next Activity.

In this activity there will automaticly play a Video of a dude making the bottom of Pizza. Now i have programmed it like when the Video has quited playing.. Someone has to get to the next activity (Automaticly implented in setOnCompletionListener.

Now i have looked up on many Stack Overflow questions about a Custom View Exception that also had an error that was noticing the custom added View package name.

I have been wrestling for like 5 hours now on this single bug that makes my App Forced Down so my question is if you guys can help me out to see where this problem is coming from.

Edited Forgot my Error-Log (stupid me -_-)

06-07 17:55:54.391: E/AndroidRuntime(22116): FATAL EXCEPTION: main
06-07 17:55:54.391: E/AndroidRuntime(22116): java.lang.RuntimeException: Unable to start activity ComponentInfo{nl.jaydijkstra.pizzabuilder/nl.jaydijkstra.pizzabuilder.SauceActivity}: android.view.InflateException: Binary XML file line #12: Error inflating class nl.jaydijkstra.pizzabuilder.MyGraphicsView
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2308)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2362)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.ActivityThread.access$700(ActivityThread.java:168)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1329)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.os.Handler.dispatchMessage(Handler.java:99)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.os.Looper.loop(Looper.java:137)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.ActivityThread.main(ActivityThread.java:5493)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at java.lang.reflect.Method.invokeNative(Native Method)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at java.lang.reflect.Method.invoke(Method.java:525)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1209)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1025)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at dalvik.system.NativeStart.main(Native Method)
06-07 17:55:54.391: E/AndroidRuntime(22116): Caused by: android.view.InflateException: Binary XML file line #12: Error inflating class nl.jaydijkstra.pizzabuilder.MyGraphicsView
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.LayoutInflater.createView(LayoutInflater.java:626)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:702)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.LayoutInflater.rInflate(LayoutInflater.java:761)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.LayoutInflater.inflate(LayoutInflater.java:498)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.LayoutInflater.inflate(LayoutInflater.java:398)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.LayoutInflater.inflate(LayoutInflater.java:354)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:361)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.Activity.setContentView(Activity.java:1956)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at nl.jaydijkstra.pizzabuilder.SauceActivity.onCreate(SauceActivity.java:18)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.Activity.performCreate(Activity.java:5372)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1104)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2270)
06-07 17:55:54.391: E/AndroidRuntime(22116):    ... 11 more
06-07 17:55:54.391: E/AndroidRuntime(22116): Caused by: java.lang.reflect.InvocationTargetException
06-07 17:55:54.391: E/AndroidRuntime(22116):    at java.lang.reflect.Constructor.constructNative(Native Method)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at java.lang.reflect.Constructor.newInstance(Constructor.java:417)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.LayoutInflater.createView(LayoutInflater.java:600)
06-07 17:55:54.391: E/AndroidRuntime(22116):    ... 22 more
06-07 17:55:54.391: E/AndroidRuntime(22116): Caused by: java.lang.OutOfMemoryError
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:596)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:444)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.graphics.drawable.Drawable.createFromResourceStream(Drawable.java:832)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.content.res.Resources.loadDrawable(Resources.java:2988)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.content.res.TypedArray.getDrawable(TypedArray.java:602)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.View.<init>(View.java:3563)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at android.view.View.<init>(View.java:3492)
06-07 17:55:54.391: E/AndroidRuntime(22116):    at nl.jaydijkstra.pizzabuilder.MyGraphicsView.<init>(MyGraphicsView.java:28)
06-07 17:55:54.391: E/AndroidRuntime(22116):    ... 25 more

Sauce Activity.java

package nl.jaydijkstra.pizzabuilder;

import android.app.Activity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
import android.view.View;
import android.widget.ImageButton;
import android.widget.LinearLayout;

public class SauceActivity extends Activity {

private MyGraphicsView drawView;
private ImageButton currPaint;
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_sauce);

        drawView = (MyGraphicsView)findViewById(R.id.drawing);
        LinearLayout paintLayout = (LinearLayout)findViewById(R.id.paint_colors);
        currPaint = (ImageButton)paintLayout.getChildAt(0);
        currPaint.setImageDrawable(getResources().getDrawable(R.drawable.sauce_pressed));
    }

    public void paintClicked(View view){
        //What color will be chosen?
        if(view!= currPaint){
        ImageButton imgView = (ImageButton)view;
        String color = view.getTag().toString();

        drawView.setColor(color);

        imgView.setImageDrawable(getResources().getDrawable(R.drawable.sauce_pressed));
        currPaint.setImageDrawable(getResources().getDrawable(R.drawable.sauce));
        currPaint=(ImageButton)view;
        }
        }
    }

activity_sauce.xml

 <LinearLayout 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"
    android:background="#FFCCCCCC"
    android:orientation="vertical"
    tools:context="${packageName}.${activityClass}" >


    <!-- Custom View -->

    <nl.jaydijkstra.pizzabuilder.MyGraphicsView
        android:id="@+id/drawing"
        android:layout_width="fill_parent"
        android:layout_height="0dp"
        android:layout_marginBottom="3dp"
        android:layout_marginLeft="5dp"
        android:layout_marginRight="5dp"
        android:layout_marginTop="3dp"
        android:layout_weight="1"
        android:background="@drawable/bottom_unbaked" />

    <!-- Color Pallette Holder -->

    <LinearLayout
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_gravity="center"
        android:orientation="vertical" >

        <!--What Color To Choose? -->

        <LinearLayout
            android:id="@+id/paint_colors"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:orientation="horizontal" >

            <ImageButton
                android:layout_width="@dimen/large_brush"
                android:layout_height="@dimen/large_brush"
                android:layout_margin="2dp"
                android:background="#FF660000"
                android:contentDescription="@string/paint"
                android:onClick="paintClicked"
                android:src="@drawable/sauce"
                android:tag="#FF660000" />

            <ImageButton
                android:layout_width="@dimen/large_brush"
                android:layout_height="@dimen/large_brush"
                android:layout_margin="2dp"
                android:background="#FFFF0000"
                android:contentDescription="@string/paint"
                android:onClick="paintClicked"
                android:src="@drawable/sauce"
                android:tag="#FFFF0000" />

            <ImageButton
                android:layout_width="@dimen/large_brush"
                android:layout_height="@dimen/large_brush"
                android:layout_margin="2dp"
                android:background="#FFFF6600"
                android:contentDescription="@string/paint"
                android:onClick="paintClicked"
                android:src="@drawable/sauce"
                android:tag="#FFFF6600" />

            <ImageButton
                android:layout_width="@dimen/large_brush"
                android:layout_height="@dimen/large_brush"
                android:layout_margin="2dp"
                android:background="#FFFFCC00"
                android:contentDescription="@string/paint"
                android:onClick="paintClicked"
                android:src="@drawable/sauce"
                android:tag="#FFFFCC00" />

            <ImageButton
                android:layout_width="@dimen/large_brush"
                android:layout_height="@dimen/large_brush"
                android:layout_margin="2dp"
                android:background="#FF009900"
                android:contentDescription="@string/paint"
                android:onClick="paintClicked"
                android:src="@drawable/sauce"
                android:tag="#FF009900" />

            <ImageButton
                android:layout_width="@dimen/large_brush"
                android:layout_height="@dimen/large_brush"
                android:layout_margin="2dp"
                android:background="#FF009999"
                android:contentDescription="@string/paint"
                android:onClick="paintClicked"
                android:src="@drawable/sauce"
                android:tag="#FF009999" />
        </LinearLayout>


    </LinearLayout>

</LinearLayout>

My Custom View

package nl.jaydijkstra.pizzabuilder;

import android.content.Context;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Paint;
import android.graphics.Path;
import android.util.AttributeSet;
import android.util.Log;
import android.view.MotionEvent;
import android.view.View;
import android.widget.ImageView;

public class MyGraphicsView extends View{

    private Path drawPath;

    private Paint drawPaint, canvasPaint;

    private int paintColor = 0xFF660000;

    private Canvas drawCanvas;

    private Bitmap canvasBitmap;

    public MyGraphicsView(Context context, AttributeSet attr) {
        super(context, attr);
        setupDrawing();
        // TODO Auto-generated constructor stub
    }

    private void setupDrawing(){
        drawPath = new Path();
        drawPaint = new Paint();

        drawPaint.setColor(paintColor);

        drawPaint.setAntiAlias(true);
        drawPaint.setStrokeWidth(20);
        drawPaint.setStyle(Paint.Style.STROKE);
        drawPaint.setStrokeJoin(Paint.Join.ROUND);
        drawPaint.setStrokeCap(Paint.Cap.ROUND);

        canvasPaint = new Paint(Paint.DITHER_FLAG);
    }

    @Override
        protected void onSizeChanged(int w, int h, int oldw, int oldh) {
            // TODO Auto-generated method stub
            super.onSizeChanged(w, h, oldw, oldh);

            canvasBitmap = Bitmap.createBitmap(w,h,Bitmap.Config.ARGB_8888);
            drawCanvas = new Canvas (canvasBitmap);
        }
    @Override
        protected void onDraw(Canvas canvas) {
            canvas.drawBitmap(canvasBitmap, 0, 0, canvasPaint);
            canvas.drawPath(drawPath, drawPaint);

        }
    @Override
        public boolean onTouchEvent(MotionEvent event) {

            float touchX = event.getX();
            float touchY = event.getY();

            switch (event.getAction()) {
            case MotionEvent.ACTION_DOWN:
                drawPath.moveTo(touchX,  touchY);
                break;
            case MotionEvent.ACTION_MOVE:
                drawPath.lineTo(touchX, touchY);
                break;
            case MotionEvent.ACTION_UP:
                drawCanvas.drawPath(drawPath, drawPaint);
                drawPath.reset();
                break;

            default:
                return false;
            }
            invalidate();
            return true;
        }

       public void setColor(String newColor){
            invalidate();

            paintColor = Color.parseColor(newColor);
            drawPaint.setColor(paintColor);
        }


}

And sorry for the long post! At last my:

Android ManiFest

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="nl.jaydijkstra.pizzabuilder"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="18"
        android:targetSdkVersion="19" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="nl.jaydijkstra.pizzabuilder.MainActivity"
            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="nl.jaydijkstra.pizzabuilder.GameOverActivity"
            android:label="@string/title_activity_game_over" >
        </activity>
        <activity
            android:name="nl.jaydijkstra.pizzabuilder.PizzaActivity"
            android:label="@string/title_activity_pizza" >
        </activity>
        <activity
            android:name="nl.jaydijkstra.pizzabuilder.Prefs"
            android:label="@string/settings_title" >
        </activity>
        <activity
            android:name="nl.jaydijkstra.pizzabuilder.DoughActivity"
            android:label="@string/title_activity_dough" >
        </activity>
        <activity
            android:name="nl.jaydijkstra.pizzabuilder.SauceActivity"
            android:label="@string/title_activity_sauce" >
        </activity>
        <activity
            android:name="nl.jaydijkstra.pizzabuilder.ShakeActivity"
            android:label="@string/title_activity_shake" >
        </activity>
    </application>

</manifest>

I really Hope you guys can help me out!!!

Kind Regards,

Jay


Solution

  • The problem is in the xml when you are inflating your custom view.

    android:background="@drawable/bottom_unbaked"
    

    The issue is the image bottom_unbaked is too large to be loaded for Android. When loading images you should make sure they are sized appropriately for the applications need. My guess is that image is way bigger than what is actually needed inside your view. Take a look at Supporting Multiple Screens docs to understand how you can supply different sizes of the same image so it will scale for devices that can take advantage of a larger image. For testing, use a program like Gimp or something to scale down the image to the smallest size that still looks good in the application.