0

I have not used TabHost before, and following several tutorials to piece something together, but I keep getting a NullPointerException at my line 81 where I have my Resources class variable when using it to get an icon from a drawable using

TabSpec tabSpecVolcano = tabHost
                .newTabSpec("Volcano") // Line 81
                .setIndicator("", resrc.getDrawable(R.drawable.ic_tab_volcano))
                .setContent(intentVolcano);

Line 81 is the "caused by" in my LogCat. This error is causing the emulator to crash without showing anything at startup. Below I will post my MainSelectorActivity.java, its xml, and the xml layout for the tab belonging to line 81, the Volcano layout (and class too). All other tabs have a very similar layout and class as the Volcano one. Plus I will post my LogCat. Let me know if you need to see other files. Thanks very much.

UPDATE: The original error was solved by instantiating the getResources() inside of the onCreate method. See below for the answer with an explanation of why it worked.

MainSelectorActivity.java

package com.azurespot.disastertimer.app;

import android.content.Intent;
import android.content.res.Resources;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;
import android.support.v4.app.FragmentTabHost;
import android.widget.TabHost.TabSpec;


public class MainSelectorActivity extends FragmentActivity {

    Resources resrc = getResources();
    FragmentTabHost tabHost;

    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main_selector);

        // TabHost setup
        tabHost = (android.support.v4.app.FragmentTabHost)findViewById(android.R.id.tabhost);
        tabHost.setup(this, getSupportFragmentManager(), R.id.realtabcontent);

        //------Zombie tab------
        // Creates tab and sets zombie image in view
//        tabHost.addTab(tabHost.newTabSpec("zombie").setIndicator("Zombie",
//                        getResources().getDrawable(R.drawable.ic_tab_zombie)),
//                ZombieTab.class, null);
        // When icon is clicked, zombie image shows
        Intent intentZombie = new Intent().setClass(this, ZombieTab.class);
        TabSpec tabSpecZombie = tabHost
                .newTabSpec("Zombie")
                .setIndicator("", resrc.getDrawable(R.drawable.ic_tab_zombie))
                .setContent(intentZombie);

        //------Nuclear tab------
        // Creates tab and sets nuclear image in view
//        tabHost.addTab(tabHost.newTabSpec("nuclear").setIndicator("Nuclear",
//                        getResources().getDrawable(R.drawable.ic_tab_nuclear)),
//                NuclearTab.class, null);
        // When icon is clicked nuclear image shows
        Intent intentNuclear = new Intent().setClass(this, NuclearTab.class);
        TabSpec tabSpecNuclear = tabHost
                .newTabSpec("Nuclear")
                .setIndicator("", resrc.getDrawable(R.drawable.ic_tab_nuclear))
                .setContent(intentNuclear);

        //------Tsunami tab------
        // Creates tab and sets tsunami image in view
//        tabHost.addTab(tabHost.newTabSpec("tsunami").setIndicator("Tsunami",
//                        getResources().getDrawable(R.drawable.ic_tab_tsunami)),
//                TsunamiTab.class, null);
        // When icon is clicked tsunami image shows
        Intent intentTsunami = new Intent().setClass(this, TsunamiTab.class);
        TabSpec tabSpecTsunami = tabHost
                .newTabSpec("Tsunami")
                .setIndicator("", resrc.getDrawable(R.drawable.ic_tab_tsunami))
                .setContent(intentTsunami);

        //------Godzilla tab------
        // Creates tab and sets tsunami image in view
//        tabHost.addTab(tabHost.newTabSpec("godzilla").setIndicator("Godzilla",
//                        getResources().getDrawable(R.drawable.ic_tab_godzilla)),
//                GodzillaTab.class, null);
        // When icon is clicked godzilla image shows
        Intent intentGodzilla = new Intent().setClass(this, GodzillaTab.class);
        TabSpec tabSpecGodzilla = tabHost
                .newTabSpec("Godzilla")
                .setIndicator("", resrc.getDrawable(R.drawable.ic_tab_godzilla))
                .setContent(intentGodzilla);

        //------Volcano tab------
        // Creates tab and sets volcano image in view
//        tabHost.addTab(tabHost.newTabSpec("volcano").setIndicator("Volcano",
//                        getResources().getDrawable(R.drawable.ic_tab_volcano)),
//                VolcanoTab.class, null);
        // When icon is clicked volcano image shows
        Intent intentVolcano = new Intent().setClass(this, VolcanoTab.class);
        TabSpec tabSpecVolcano = tabHost
                .newTabSpec("Volcano")
                .setIndicator("", resrc.getDrawable(R.drawable.ic_tab_volcano))
                .setContent(intentVolcano);

        // add all tabs
        tabHost.addTab(tabSpecZombie);
        tabHost.addTab(tabSpecNuclear);
        tabHost.addTab(tabSpecTsunami);
        tabHost.addTab(tabSpecGodzilla);
        tabHost.addTab(tabSpecVolcano);

        //set Zombie tab as default (zero based)
        tabHost.setCurrentTab(0);

    }

}

activity_main_selector.xml

<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="com.azurespot.disastertimer.app.MainSelectorActivity">

    <android.support.v4.app.FragmentTabHost
        android:id="@android:id/tabhost"
        android:layout_width="match_parent"
        android:layout_height="match_parent" >

        <LinearLayout
            android:orientation="vertical"
            android:layout_width="match_parent"
            android:layout_height="match_parent" >

            <TabWidget
                android:id="@android:id/tabs"

                android:orientation="horizontal"
                android:layout_width="match_parent"
                android:layout_height="wrap_content"
                android:layout_weight="0" />

            <FrameLayout
                android:id="@android:id/tabcontent"
                android:layout_width="0dp"
                android:layout_height="0dp"
                android:layout_weight="0" />

            <FrameLayout
                android:id="@+id/realtabcontent"
                android:layout_width="match_parent"
                android:layout_height="0dp"
                android:layout_weight="1" />

        </LinearLayout>
    </android.support.v4.app.FragmentTabHost>

    <LinearLayout
        android:layout_width="match_parent"
        android:layout_height="140dp"
        android:orientation="horizontal"
        android:layout_marginTop="200dp"
        android:gravity="center_horizontal">

        <NumberPicker
            android:id="@+id/numberPicker1"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="16dp"
            android:layout_marginTop="20dp" />

        <NumberPicker
            android:id="@+id/numberPicker2"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:layout_marginTop="20dp" />

        <NumberPicker
            android:id="@+id/numberPicker3"
            android:layout_width="wrap_content"
            android:layout_height="wrap_content"
            android:layout_marginLeft="14dp"
            android:layout_marginTop="20dp" />
    </LinearLayout>

</RelativeLayout>

VolcanoTab.java

package com.azurespot.disastertimer.app;

import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

/**
 * Created by azuremoss on 4/22/14.
 */
public class VolcanoTab extends Fragment {

    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container,
                             Bundle savedInstanceState) {
        // Inflate the layout for this fragment
        View v = inflater.inflate(R.layout.volcano_tab, container, false);

        return v;
    }
}

volcano_tab.xml

<?xml version="1.0" encoding="utf-8"?>

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
    android:orientation="vertical" android:layout_width="match_parent"
    android:layout_height="match_parent">

    <ImageButton
        android:layout_width="match_parent"
        android:layout_height="160dp"
        android:layout_marginTop="0dp"
        android:id="@+id/imageButton"
        android:layout_gravity="center_horizontal"
        android:src="@drawable/volcano_image"
        android:text="@string/volcano_fragment_string"/>
</LinearLayout>

LogCat

1111-1111/com.azurespot.disastertimer.app E/AndroidRuntime﹕ FATAL EXCEPTION: main
    java.lang.RuntimeException: Unable to instantiate activity ComponentInfo{com.azurespot.disastertimer.app/com.azurespot.disastertimer.app.MainSelectorActivity}: java.lang.NullPointerException
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1983)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
            at android.app.ActivityThread.access$600(ActivityThread.java:130)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
     Caused by: java.lang.NullPointerException
            at android.content.ContextWrapper.getResources(ContextWrapper.java:81)
            at com.azurespot.disastertimer.app.MainSelectorActivity.<init>(MainSelectorActivity.java:13)
            at java.lang.Class.newInstanceImpl(Native Method)
            at java.lang.Class.newInstance(Class.java:1319)
            at android.app.Instrumentation.newActivity(Instrumentation.java:1053)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:1974)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2084)
            at android.app.ActivityThread.access$600(ActivityThread.java:130)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1195)
            at android.os.Handler.dispatchMessage(Handler.java:99)
            at android.os.Looper.loop(Looper.java:137)
            at android.app.ActivityThread.main(ActivityThread.java:4745)
            at java.lang.reflect.Method.invokeNative(Native Method)
            at java.lang.reflect.Method.invoke(Method.java:511)
            at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:786)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:553)
            at dalvik.system.NativeStart.main(Native Method)
Azurespot
  • 3,066
  • 3
  • 45
  • 73

2 Answers2

1

you should call getResources() in activity's onCreate() method.

Jiang YD
  • 3,205
  • 1
  • 14
  • 20
  • Do you mean in the main activity? I added that, but it still crashed at that same location (line 81). – Azurespot Apr 24 '14 at 02:17
  • the logcat shows that you have exception at ContextWrapper.java:81. ContextWrapper.java is one of Android Frameowrk, not your source code. – Jiang YD Apr 24 '14 at 02:41
  • 1
    you should replace "Resources resrc = getResources();" to "Resources resrc;", and add line "resrc = getResources();" in your onCreate() method. – Jiang YD Apr 24 '14 at 02:42
  • Ah, so it needs to instantiate in the onCreate()? I changed that, and that error went away, but then a new one: 'Unable to start activity ComponentInfo{com.azurespot.disastertimer.app/com.azurespot.disastertimer.app.MainSelectorActivity}: java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?' with the caused by reading: 'Caused by: java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?' But I don't know what this refers to. The tabHost is setup already. – Azurespot Apr 24 '14 at 02:47
  • would this help you? [link](http://stackoverflow.com/questions/3272500/android-exception-did-you-forget-to-call-public-void-setup-localactivitymanag) – Jiang YD Apr 24 '14 at 02:53
  • thanks Jiang for the reference... it is tricky because I have to keep the Fragment extensions, since the tab is part of a fragment. but i will look it over... it's weird because LocalActivityManager was never used in my Activity. – Azurespot Apr 24 '14 at 02:57
  • Thanks Jiang, I chose the other answer as it went into a little more detail about why the solution worked. Maybe other StackO people would benefit from that. But your answer was first, and very helpful too, so I upgraded yours +1. Thanks very much for your help. – Azurespot Apr 24 '14 at 03:42
1

Actually your error is line 13 in MainSelectorActivity. Line 81 is where the null pointer exception occurs in ContextWrapper which originates from a call in line 13 in your activity class.

Line 13 is

Resources resrc = getResources();

Why are you getting an error here? Since you are calling getResources as a declaration, this call happens before the onCreate of your activity.

getResources requires a context which in this case is from your activity, however since the context has not been properly initialized yet, you will get a null pointer exception.

So if you still want to keep your global resrc variable, you will need to simply set it in the onCreate method.

Resources resrc;

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    resrc = getResources();
    ...
}
Community
  • 1
  • 1
singularhum
  • 5,072
  • 2
  • 24
  • 32
  • Thanks so much, that is a helpful explanation. although the poster above did offer the same solution. the only problem is there is a new error that cause the crash, but it does not make sense to me, as I'm still a beginner. :( Would you have an idea about this one? posted above in the comments section of the first answer. – Azurespot Apr 24 '14 at 02:53
  • 'Unable to start activity ComponentInfo{com.azurespot.disastertimer.app/com.azurespot.disastertimer.app.Ma‌​inSelectorActivity}: java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?' with the caused by reading: 'Caused by: java.lang.IllegalStateException: Did you forget to call 'public void setup(LocalActivityManager activityGroup)'?' – Azurespot Apr 24 '14 at 02:54
  • @NoniA. Yeah it is the same solution but I wanted to provide an explanation for you to learn, not just a solution . Anyway for that issue, your activity needs to extend ActivityGroup. If you don't want it to extend that then you will need to use a `LocalActivityManager` as stated [here](http://stackoverflow.com/a/8572214/3286163). – singularhum Apr 24 '14 at 03:06
  • Thanks sing, I do appreciate a good explanation so I can learn. I did try to use the LocalActivityManager, but it has been depreciated, so gets crossed out in Android Studio. I read on the Android Developer pages to use Fragment or FragmentManager, but I do not see how to use tabs with these. The tutorials I followed used FragmentActivity, but these errors are are not mentioned in the tutorials. ugh. – Azurespot Apr 24 '14 at 03:18
  • Here is one of the tutorials I used, but had to change the extension to FragmentActivity, instead of TabActivity (depreciated). Just trying to get simple tabs (non-ActionBar) that I can click on an icon in the tab to change between them. [link](http://www.mkyong.com/android/android-tablayout-example/) – Azurespot Apr 24 '14 at 03:21
  • @NoniA. I see, I'm not too familiar with using `TabHost` so it may be worthwhile for you to create a new question since the error is not relevant to this question anymore now that it has been resolved. I would look into it more but don't have the time at the moment. – singularhum Apr 24 '14 at 03:31
  • Sure, I understand, that is true too the original error was solved. Thanks so much for your input. – Azurespot Apr 24 '14 at 03:37
  • UPDATE: I was getting the 2nd error because my fragments were not activities, but rather classes with accompanying xmls (hence not in the AndroidManifest.xml). Therefore the Intent was not working, because that will only work when you have an activity to go to. So I took out the Intent and it is visible again. – Azurespot Apr 24 '14 at 04:42
  • 1
    @NoniA. Ah that makes sense, glad you figured it out! – singularhum Apr 24 '14 at 11:02