Mr Robbes
Mr Robbes

Reputation: 49

Android application can not load once a new class is introduced

Hello there am crawling into this android world slowly and following the android bootcamp exercise 2012 edition. I am able to test my application on the AVm with just one layout and one class however on introducing the second class, second layout and coding the button, the application does not open and the log cat error looks like this

06-18 17:22:29.461: D/AndroidRuntime(542): Shutting down VM
06-18 17:22:29.461: W/dalvikvm(542): threadid=1: thread exiting with uncaught exception (group=0x409961f8)
06-18 17:22:29.471: E/AndroidRuntime(542): FATAL EXCEPTION: main
06-18 17:22:29.471: E/AndroidRuntime(542): java.lang.RuntimeException: Unable to start activity ComponentInfo{com.example.helloworld/com.example.helloworld.Main}: java.lang.NullPointerException
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1955)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:1980)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.app.ActivityThread.access$600(ActivityThread.java:122)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1146)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.os.Handler.dispatchMessage(Handler.java:99)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.os.Looper.loop(Looper.java:137)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.app.ActivityThread.main(ActivityThread.java:4340)
06-18 17:22:29.471: E/AndroidRuntime(542):  at java.lang.reflect.Method.invokeNative(Native Method)
06-18 17:22:29.471: E/AndroidRuntime(542):  at java.lang.reflect.Method.invoke(Method.java:511)
06-18 17:22:29.471: E/AndroidRuntime(542):  at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:784)
06-18 17:22:29.471: E/AndroidRuntime(542):  at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:551)
06-18 17:22:29.471: E/AndroidRuntime(542):  at dalvik.system.NativeStart.main(Native Method)
06-18 17:22:29.471: E/AndroidRuntime(542): Caused by: java.lang.NullPointerException
06-18 17:22:29.471: E/AndroidRuntime(542):  at com.example.helloworld.Main.onCreate(Main.java:24)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.app.Activity.performCreate(Activity.java:4465)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1049)
06-18 17:22:29.471: E/AndroidRuntime(542):  at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1919)
06-18 17:22:29.471: E/AndroidRuntime(542):  ... 11 more

this is the main.java

public class Main extends Activity {


    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        Button b = (Button)findViewById(R.id.btnPlay);
        b.setOnClickListener(new OnClickListener() {
                @Override

            public void onClick(View v) {
                startActivity(new Intent(Main.this, Recipe.class));
                // TODO Auto-generated method stub
            }

        });

        if (savedInstanceState == null) {
             getFragmentManager().beginTransaction()
                     .add(R.id.container, new PlaceholderFragment())
                     .commit();
         }
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
     }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
       // Handle action bar item clicks here. The action bar will
       // automatically handle clicks on the Home/Up button, so long
       // as you specify a parent activity in AndroidManifest.xml.

       int id = item.getItemId();
       if (id == R.id.action_settings) {
            return true;
     }
     return super.onOptionsItemSelected(item);

     }

     /**
       * A placeholder fragment containing a simple view.
      */

    public static class PlaceholderFragment extends Fragment {
        public PlaceholderFragment() {}

        @Override
       public View onCreateView(LayoutInflater inflater, ViewGroup container,
               Bundle savedInstanceState) {
              View rootView = inflater.inflate(R.layout.fragment_main, container, false);
            return rootView;
          }
      }
    }

this is the new class

package com.example.helloworld;

import android.app.Activity;
import android.os.Bundle;

public class Recipe extends Activity {
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        // TODO Auto-generated method stub
        super.onCreate(savedInstanceState);
        setContentView(R.layout.recipe);

    }

}

this is the manifest

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

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

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name="com.example.helloworld.Main"
            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="Recipe"></activity>
    </application>

</manifest>

activity_main

<FrameLayout xmlns:android="http://schemas.android.com/apk/res/android"
    xmlns:tools="http://schemas.android.com/tools"
    android:id="@+id/container"
    android:layout_width="match_parent"
    android:layout_height="match_parent"
    tools:context="com.example.helloworld.Main"
    tools:ignore="MergeRootFrame" />

fragment_main

<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"
    android:paddingBottom="@dimen/activity_vertical_margin"
    android:paddingLeft="@dimen/activity_horizontal_margin"
    android:paddingRight="@dimen/activity_horizontal_margin"
    android:paddingTop="@dimen/activity_vertical_margin"
    tools:context="com.example.helloworld.Main$PlaceholderFragment" >

    <TextView
        android:id="@+id/textView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentTop="true"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="28dp"
        android:text="@string/mduduzi_games"
        android:textSize="30sp" />

    <Button
        android:id="@+id/btnPlay"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/imageView1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="28dp"
        android:text="@string/play" />

    <ImageView
        android:id="@+id/imageView1"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/textView1"
        android:layout_centerHorizontal="true"
        android:layout_marginTop="27dp"
        android:src="@drawable/anim4" />

</RelativeLayout>

Upvotes: 0

Views: 40

Answers (3)

Sam Dozor
Sam Dozor

Reputation: 40744

From your stack trace, there is a NullPointerException on line 24 of Main.java:

at com.example.helloworld.Main.onCreate(Main.java:24)

This is your problem:

 Button b = (Button)findViewById(R.id.btnPlay);
 //b is null, so the next line throws a NullPointerException:
 b.setOnClickListener(...

b is null, meaning there is no Button with the id "btnPlay" in activity_main.xml

Check to make sure you have something like this in activity_main.xml:

<Button 
    android:layout_width="wrap_content"
    android:text="Some text"
    android:id="@+id/btnPlay"
    android:layout_height="wrap_content" />

EDIT:

You are calling findViewById from your Activity, which is searching amongst the Views of your Activity defined by activity_main.xml. Since you have defined your Button in your Fragment layout, you must get a reference to the Button from within your Fragment code. Remove the Button code from your Activity class, and stick it into your Fragment:

public static class PlaceholderFragment extends Fragment {
    public PlaceholderFragment() {}

    @Override
   public View onCreateView(LayoutInflater inflater, ViewGroup container,
           Bundle savedInstanceState) {
          View rootView = inflater.inflate(R.layout.fragment_main, container, false);
         //find your Button view in rootView
         Button b = (Button)rootView.findViewById(R.id.btnPlay);
         b.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
            startActivity(new Intent(Main.this, Recipe.class));
            // TODO Auto-generated method stub
            }
         });
        return rootView;
      }
  }

Upvotes: 1

Bryan Herbst
Bryan Herbst

Reputation: 67209

The problem is that btnPlay is defined in your Fragment's layout, but you are trying to find it in your Activity before the Fragment is added to the Activity.

When you call findViewById(R.id.btnPlay);, the only thing that has been added to your Activity's layout is activity_main, which only contains a FrameLayout. The Fragment containing btnPlay doesn't exist until you call

getFragmentManager().beginTransaction()
    .add(R.id.container, new PlaceholderFragment())
    .commit();

One solution would be to move the above three lines to before Button b = (Button)findViewById(R.id.btnPlay);.

However, it is generally a bad practice to reference Views defined in a Fragment from an Activity, because it is a very poor separation of concerns. Your Fragment should handle of the user interaction with Views belonging to that Fragment, and your Activity should only be concerned with Views defined in the Activity's layout.

Upvotes: 0

krodmannix
krodmannix

Reputation: 845

While you are on the right path, you need to change a line slightly in your manifest. Try:

<activity android:name="com.example.helloworld.Recipe"></activity>

Instead of

<activity android:name="Recipe"></activity>

EDIT: Actually, this doesn't seem to be the source of your current problem, but will be a source of a future problem once your current NullPointerException is fixed. As stated in other answers, it looks to deal with the button you set to navigate to your new Activity.

Upvotes: 0

Related Questions