0

I've seen a few posts with this same error. However, none of them have as yet offered a working solution to my problem.

I have two activity classes, MainActivity and GameActivity. MainActivity starts GameActivity on a button press. If I press the back button on my phone, it goes back to the main activity. However, when I press the button again to start a new GameActivity, I am prompted with an error pointing to the line of code

setContentView(R.layout.activity_game);

Error:

08-02 02:16:56.365 2220-2220/joseph.imbroglio E/AndroidRuntime: FATAL EXCEPTION: main
Process: joseph.imbroglio, PID: 2220
    java.lang.RuntimeException: Unable to start activity ComponentInfo{joseph.imbroglio/joseph.imbroglio.GameActivity}: android.view.InflateException: Binary XML file line #7: Error inflating class <unknown>
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2661)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726)
    at android.app.ActivityThread.access$900(ActivityThread.java:172)
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421)
    at android.os.Handler.dispatchMessage(Handler.java:102)
    at android.os.Looper.loop(Looper.java:145)
    at android.app.ActivityThread.main(ActivityThread.java:5835)
    at java.lang.reflect.Method.invoke(Native Method)
    at java.lang.reflect.Method.invoke(Method.java:372)
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399)
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194)
    Caused by: android.view.InflateException: Binary XML file line #7: Error inflating class <unknown>
    at android.view.LayoutInflater.createView(LayoutInflater.java:640)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:750)
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:813)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:511)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:415)
    at android.view.LayoutInflater.inflate(LayoutInflater.java:366)
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:428)
    at android.app.Activity.setContentView(Activity.java:2241)
    at joseph.imbroglio.GameActivity.onCreate(GameActivity.java:30)
    at android.app.Activity.performCreate(Activity.java:6221)
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119)
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2614)
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
    at android.app.ActivityThread.access$900(ActivityThread.java:172) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:145) 
    at android.app.ActivityThread.main(ActivityThread.java:5835) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 
    Caused by: java.lang.reflect.InvocationTargetException
    at java.lang.reflect.Constructor.newInstance(Native Method)
    at java.lang.reflect.Constructor.newInstance(Constructor.java:288)
    at android.view.LayoutInflater.createView(LayoutInflater.java:614)
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:750) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:813) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:511) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:415) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:366) 
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:428) 
    at android.app.Activity.setContentView(Activity.java:2241) 
    at joseph.imbroglio.GameActivity.onCreate(GameActivity.java:30) 
    at android.app.Activity.performCreate(Activity.java:6221) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2614) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
    at android.app.ActivityThread.access$900(ActivityThread.java:172) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:145) 
    at android.app.ActivityThread.main(ActivityThread.java:5835) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 
    Caused by: java.lang.OutOfMemoryError: Failed to allocate a 72000012 byte allocation with 16777216 free bytes and 65MB until OOM
    at dalvik.system.VMRuntime.newNonMovableArray(Native Method)
    at android.graphics.BitmapFactory.nativeDecodeAsset(Native Method)
    at android.graphics.BitmapFactory.decodeStream(BitmapFactory.java:726)
    at android.graphics.BitmapFactory.decodeResourceStream(BitmapFactory.java:547)
    at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:575)
    at android.graphics.BitmapFactory.decodeResource(BitmapFactory.java:605)
    at joseph.imbroglio.Entity.<init>(Entity.java:42)
    at joseph.imbroglio.Face.<init>(Face.java:13)
    at joseph.imbroglio.GameView.init(GameView.java:67)
    at joseph.imbroglio.GameView.<init>(GameView.java:52)
    at java.lang.reflect.Constructor.newInstance(Native Method) 
    at java.lang.reflect.Constructor.newInstance(Constructor.java:288) 
    at android.view.LayoutInflater.createView(LayoutInflater.java:614) 
    at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:750) 
    at android.view.LayoutInflater.rInflate(LayoutInflater.java:813) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:511) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:415) 
    at android.view.LayoutInflater.inflate(LayoutInflater.java:366) 
    at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:428) 
    at android.app.Activity.setContentView(Activity.java:2241) 
    at joseph.imbroglio.GameActivity.onCreate(GameActivity.java:30) 
    at android.app.Activity.performCreate(Activity.java:6221) 
    at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1119) 
    at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2614) 
    at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2726) 
    at android.app.ActivityThread.access$900(ActivityThread.java:172) 
    at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1421) 
    at android.os.Handler.dispatchMessage(Handler.java:102) 
    at android.os.Looper.loop(Looper.java:145) 
    at android.app.ActivityThread.main(ActivityThread.java:5835) 
    at java.lang.reflect.Method.invoke(Native Method) 
    at java.lang.reflect.Method.invoke(Method.java:372) 
    at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:1399) 
    at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:1194) 

onCreate method for MainActivity:

@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    requestWindowFeature(Window.FEATURE_NO_TITLE);
    setContentView(R.layout.activity_main);
    mainActivity = this;
    playbtn = (ImageView) findViewById(R.id.imageView);
    final Intent intent = new Intent(getBaseContext(), GameActivity.class);
    intent.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP);
    playbtn.setOnTouchListener(new View.OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {
            playbtn.setImageResource(R.drawable.playbutton2);
            startActivity(intent);
            getIntent().removeExtra("startTest");
            return true;
        }
    });
}

onCreate method for GameActivity:

public void onCreate(Bundle savedInstanceState){
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_game);

    gameView = (GameView)findViewById(R.id.gameView);
    gameView.setGameActivity(this);
    gameThread = new Thread(gameView);
    gameThread.start();
    MainActivity.resetButton();
}

activity_game XML file:

<?xml version="1.0" encoding="utf-8"?>
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    tools:context="joseph.imbroglio.GameActivity"
    android:layout_width="match_parent"     android:layout_height="match_parent">

    <joseph.imbroglio.GameView
        android:id="@+id/gameView"
        android:layout_width="match_parent"
        android:layout_height="match_parent" />

    <TextView
        android:text="TextView"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_centerVertical="true"
        android:layout_centerHorizontal="true"
        android:id="@+id/textView"
        android:textSize="24sp"
        android:textColor="?android:attr/colorBackground" />
</RelativeLayout>

Code for that resetButton method:

public static void resetButton(){
    playbtn.setImageResource(R.drawable.playbutton);
}

As requested, here's the code for the GameView class:

import android.view.MotionEvent;
import android.view.SurfaceHolder;
import android.view.SurfaceView;
import android.view.View;

import java.util.ArrayList;

/**
 * Created by root on 7/4/16.
 */
public class GameView extends SurfaceView implements Runnable,     SurfaceHolder.Callback{

protected Resources resources;

private SurfaceHolder holder;

protected ArrayList<Entity> entities = new ArrayList<Entity>();

private long lastUpdate = 0;

protected GameActivity ga;

private Background background;
private Player player;
private Face face;
private TileSet tileSet;
private ArrayList<Fruit> fruits = new ArrayList<Fruit>();

private boolean surfaceCreated = false;
private boolean hasActiveHolder = false;
private boolean touchingRight = false;
private boolean touchingLeft = false;

private int accel = getResources().getDisplayMetrics().widthPixels/25;

private Physics physics;


public GameView(Context context){
    super(context);
    init();
}

public GameView(Context context, AttributeSet attrs){
    super(context, attrs);
    init();
}

public GameView(Context context, AttributeSet attrs, int defStyle){
    super(context, attrs, defStyle);
    init();
}

public void init(){
    //this.setBackgroundColor(Color.RED);
    //setWillNotDraw(false);
    resources = this.getResources();
    holder = getHolder();
    background = new Background(this, R.drawable.background, 1);
    player = new Player(this, R.drawable.yellowtest, 4);
    face = new Face(this, R.drawable.face, 8);
    tileSet = new TileSet(this);
    populateFruits();
    entities.add(background);
    entities.add(player);
    entities.add(face);
    entities.addAll(tileSet.getTiles());
    entities.addAll(fruits);
    holder.addCallback(this);
    physics = new Physics(entities);
    setOnTouchListener(new OnTouchListener() {
        @Override
        public boolean onTouch(View view, MotionEvent motionEvent) {

            if(motionEvent.getAction() == MotionEvent.ACTION_DOWN){
                if(motionEvent.getX() >= getResources().getDisplayMetrics().widthPixels/2){
                    touchingRight = true;
                } else {
                    touchingLeft = true;
                }
                return true;
            }
            if(motionEvent.getAction() == MotionEvent.ACTION_UP){
                touchingLeft=false;
                touchingRight=false;
                player.neutralize();
                return true;
            }
            return false;
        }
    });
}

public void draw(){
    synchronized (this) {
        while(!hasActiveHolder){
            try{
                this.wait();
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        Canvas canvas = holder.lockCanvas();
        if(canvas != null) {
            paintCanvas(canvas);
            holder.unlockCanvasAndPost(canvas);
        }
    }
}

public void paintCanvas(Canvas canvas){
    for(Entity e : entities){
        e.draw(canvas);
    }
    tileSet.tileDead(fruits);
    tileSet.checkFell(player.pos);
    player.animation1();
    face.eat();
}

@Override
public void run() {

    while(ga.playing){
        if((System.currentTimeMillis() - lastUpdate) < 16){
            try {
                Thread.sleep(Math.abs(16 - (System.currentTimeMillis()-lastUpdate)));
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        if(this.surfaceCreated) {
            physics.update();
            manage();
            draw();
            lastUpdate = System.currentTimeMillis();
        }

    }
}

@Override
public void surfaceCreated(SurfaceHolder surfaceHolder) {
    surfaceCreated = true;
    synchronized (this) {
        hasActiveHolder = true;
        this.notifyAll();
    }
}

@Override
public void surfaceChanged(SurfaceHolder surfaceHolder, int i, int i1, int i2) {

}

@Override
public void surfaceDestroyed(SurfaceHolder surfaceHolder) {
    surfaceCreated=false;
    synchronized (this){
        hasActiveHolder = false;

        synchronized(this){
            this.notifyAll();
        }
    }
}

public int getPlayerX(){
    return player.x;
}

public int getPlayerY(){
    return player.y;
}

public Player getPlayer(){
    return player;
}

public void manage(){
    if(player.x > (getResources().getDisplayMetrics().widthPixels - player.width)){
        player.x = getResources().getDisplayMetrics().widthPixels - player.width;
    }
    if(player.x < 0){
        player.x = 0;
    }
    face.x = player.x;
    //if((!touchingLeft) && (!touchingRight)){
        //player.ax = 0;
    //}
    if(player.isAlive()) {
        if (touchingRight) {
            player.ax += accel;
        }
        if (touchingLeft) {
            player.ax -= accel;
        }
    }

}

public void populateFruits(){
    for(int i = 0; i < 20; i++){
        fruits.add(new Fruit(this, R.drawable.fruit, 2, getResources().getDisplayMetrics().widthPixels/20, getResources().getDisplayMetrics().widthPixels/20));
    }
}

public Face getFace(){
    return face;
}

public void setGameActivity(GameActivity gl){
    ga = gl;
}

}

Any input on this problem?

David Wasser
  • 85,616
  • 15
  • 182
  • 239
Joseph
  • 13
  • 2

2 Answers2

0

I think that the image size you used for the app may not support your cell. Try to minimize the sizes of the images.

perror
  • 6,329
  • 16
  • 56
  • 72
  • Maybe you are right, A common issue is an out of memory exception when trying to inflate an imageview loading a drawable resource. If one of this resources has a high pixel resolution it would take a lot of memory causing then an inflate exception. – El0din Aug 02 '16 at 06:49
  • 1
    If the `GameActivity` opened correctly the first time, but not the second time, this answer cannot be right. How do these answers get upvotes? Think, people! – David Wasser Aug 02 '16 at 07:41
0

Assuming that your GameActivity starts correctly the first time, but after pressing BACK (to return to MainActivity) and then starting the GameActivity crashes (due to OutOfMemory), probably means that you are not properly and completely cleaning up when the original instance of GameActivity ends.

From the code you've posted, you probabnly have a memory leak. This code:

gameView = (GameView)findViewById(R.id.gameView);
gameView.setGameActivity(this);
gameThread = new Thread(gameView);
gameThread.start();

passes a reference to gameView to gameThread. gameView has a reference to the instance of GameActivity. If you don't properly cleanup this Thread when the instance of GameActivity shuts down, the garbage collector will not be able to reclaim the old GameActivity and all of its resources (including your images) before you try to start the second instance. You can use heap analysis and heap debugging tools to help you find memory leaks like this.

David Wasser
  • 85,616
  • 15
  • 182
  • 239
  • Thank you very much, this insight exactly resolved my problem. In case it's any help to someone else, I created an onStopRequested boolean set to true in GameActivity's onStop method. The thread's run method returns when it sees that this boolean is true. – Joseph Aug 03 '16 at 03:56