ActionBarCompat + NavigationDrawerFragment не работает на Android 4.0 и 4.1

Очень странная проблема! Я создал новый проект через нового мастера проекта в андроид-студии. Я решил включить библиотеки поддержки для GridLayout, Fragments, NavigationDrawer и ActionBar. На следующем шаге я выбрал шаблон BlankActivity с навигацией NavigationDrawer. Мастер прекрасно создал мой проект и без проблем создал его.

Проблема в том, что когда вы пытаетесь запустить его, он отлично работает на Android 4.3, 4.2 и 2.3.3, но он падает с 4.0 и 4.1.

Трассировка стека:

10-30 13:11:31.024    2136-2136/? E/AndroidRuntime﹕ FATAL EXCEPTION: main
java.lang.RuntimeException: Unable to start activity ComponentInfo{com.navdrawer/com.navdrawer.MainActivity}: android.view.InflateException: Binary XML file line #24: Error inflating class fragment
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2059)
        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: android.view.InflateException: Binary XML file line #24: Error inflating class fragment
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:704)
        at android.view.LayoutInflater.rInflate(LayoutInflater.java:746)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:489)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:396)
        at android.view.LayoutInflater.inflate(LayoutInflater.java:352)
        at com.android.internal.policy.impl.PhoneWindow.setContentView(PhoneWindow.java:256)
        at android.app.Activity.setContentView(Activity.java:1867)
        at android.support.v7.app.ActionBarActivity.superSetContentView(ActionBarActivity.java:208)
        at android.support.v7.app.ActionBarActivityDelegateICS.setContentView(ActionBarActivityDelegateICS.java:111)
        at android.support.v7.app.ActionBarActivity.setContentView(ActionBarActivity.java:76)
        at com.navdrawer.MainActivity.onCreate(MainActivity.java:37)
        at android.app.Activity.performCreate(Activity.java:5008)
        at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1079)
        at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2023)
            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 com.navdrawer.MainActivity.onCreateOptionsMenu(MainActivity.java:82)
        at android.app.Activity.onCreatePanelMenu(Activity.java:2476)
        at android.support.v4.app.FragmentActivity.onCreatePanelMenu(FragmentActivity.java:224)
        at android.support.v7.app.ActionBarActivity.superOnCreatePanelMenu(ActionBarActivity.java:224)
        at android.support.v7.app.ActionBarActivityDelegateICS.onCreatePanelMenu(ActionBarActivityDelegateICS.java:141)
        at android.support.v7.app.ActionBarActivity.onCreatePanelMenu(ActionBarActivity.java:199)
        at android.support.v7.app.ActionBarActivityDelegateICS$WindowCallbackWrapper.onCreatePanelMenu(ActionBarActivityDelegateICS.java:280)
        at com.android.internal.policy.impl.PhoneWindow.preparePanel(PhoneWindow.java:393)
        at com.android.internal.policy.impl.PhoneWindow.invalidatePanelMenu(PhoneWindow.java:747)
        at android.app.Activity.invalidateOptionsMenu(Activity.java:2595)
        at android.support.v4.app.ActivityCompatHoneycomb.invalidateOptionsMenu(ActivityCompatHoneycomb.java:29)
        at android.support.v4.app.FragmentActivity.supportInvalidateOptionsMenu(FragmentActivity.java:633)
        at android.support.v7.app.ActionBarActivity.supportInvalidateOptionsMenu(ActionBarActivity.java:170)
        at android.support.v4.app.Fragment.setHasOptionsMenu(Fragment.java:781)
        at com.navdrawer.NavigationDrawerFragment.onCreate(NavigationDrawerFragment.java:82)
        at android.support.v4.app.Fragment.performCreate(Fragment.java:1455)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:893)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1082)
        at android.support.v4.app.FragmentManagerImpl.addFragment(FragmentManager.java:1184)
        at android.support.v4.app.FragmentActivity.onCreateView(FragmentActivity.java:285)
        at android.view.LayoutInflater.createViewFromTag(LayoutInflater.java:676)
... 24 mo

Это onCreateOptionsMenu в фрагменте

 public void onCreateOptionsMenu(Menu menu, MenuInflater inflater) {
        // If the drawer is open, show the global app actions in the action bar. See also
        // showGlobalContextActionBar, which controls the top-left area of the action bar.
        if (mDrawerLayout != null && isDrawerOpen()) {
            inflater.inflate(R.menu.global, menu);
            showGlobalContextActionBar();
        }
        super.onCreateOptionsMenu(menu, inflater);
    }

Этот находится в MainActivity

 @Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (!mNavigationDrawerFragment.isDrawerOpen()) {
            // Only show items in the action bar relevant to this screen
            // if the drawer is not showing. Otherwise, let the drawer
            // decide what to show in the action bar.
            getMenuInflater().inflate(R.menu.main, menu);
            restoreActionBar();
            return true;
        }
        return super.onCreateOptionsMenu(menu);
    }

Ответ 1

Просто столкнулся с этой же самой точной проблемой. ТОЧНЫЙ ВЫПУСК.

Проблема заключается в том, что setHasOptionsMenu(true); вызывается в onCreate вместо onActivityCreated в фрагменте. Кажется, что ошибка в Мастере, если вы спросите меня.

Чтобы решить эту проблему, переместите вызов setHasOptionsMenu(true); с onCreate() на onActivityCreated().

Это решит проблему. К моменту, когда вызов достигнет Activity#onCreateOptionsMenu, экземпляр фрагмента будет создан.

Ответ 2

Я решил проблему. Трассировка стека была для меня скупой...

Проблема была в том, что eee предложил в onCreateOptionsMenu() в активности...

@Override
    public boolean onCreateOptionsMenu(Menu menu) {
        if (!mNavigationDrawerFragment.isDrawerOpen()) {
            // Only show items in the action bar relevant to this screen
            // if the drawer is not showing. Otherwise, let the drawer
            // decide what to show in the action bar.
            getMenuInflater().inflate(R.menu.main, menu);
            restoreActionBar();
            return true;
        }
        return super.onCreateOptionsMenu(menu);
    }

как-то только на Android 4.1 и 4.0 mNavigationDrawerFragment имеет значение null, но инициализируется в onCreate(), поэтому я помещаю это

if(mNavigationDrawerFragment == null )
            mNavigationDrawerFragment = (NavigationDrawerFragment)
                    getSupportFragmentManager().findFragmentById(R.id.navigation_drawer);

как в onCreate(), так и в методе onCreateOptionsMenu()

Ответ 3

Я решил эту проблему, просто поставив блок catch try для

setHasOptionsMenu(true); 

Как объяснил Донн Фелкер, исключение возникает из-за вызова до создания активности. Обработка этого исключения может решить проблему.