我的Android应用程序适用于KitKat但不适用于Lollipop

时间:2016-02-18 14:30:37

标签: android android-manifest android-5.0-lollipop android-4.4-kitkat

我正在制作一款Android应用,我决定添加一个联系人列表。

我跟随this lesson from Google并且我已复制代码并将所有功能添加到我的应用程序中,位于目录:xml/layout/images/javacode etc中,并在我的主要活动中调用联系人列表活动。如果我在手机上通过Android Studio上的调试运行KitKat 4.4.2,我的应用程序可以工作。但是,如果我运行Lollipop 5.1.1,则在尝试访问联系人活动时应用程序会崩溃。

似乎有问题的代码:

if (Utils.hasHoneycomb()) {
    // Enables action bar "up" navigation
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

logcat的:

02-18 13:41:15.304 31435-31435/todonotes.com.todonotes_buildfinale E/AndroidRuntime: FATAL EXCEPTION: main
Process: todonotes.com.todonotes_buildfinale, PID: 31435
java.lang.RuntimeException: Unable to start activity ComponentInfo{todonotes.com.todonotes_buildfinale/todonotes.com.todonotes_buildfinale.ContactDetailActivity}: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setDisplayHomeAsUpEnabled(boolean)' on a null object reference

at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2378)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2440)
at android.app.ActivityThread.access$800(ActivityThread.java:162)
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1348)
at android.os.Handler.dispatchMessage(Handler.java:102)
at android.os.Looper.loop(Looper.java:135)
at android.app.ActivityThread.main(ActivityThread.java:5422)
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:914)
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)

Caused by: java.lang.NullPointerException: Attempt to invoke virtual method 'void android.app.ActionBar.setDisplayHomeAsUpEnabled(boolean)' on a null object reference
at todonotes.com.todonotes_buildfinale.ContactDetailActivity.onCreate(ContactDetailActivity.java:59)
at android.app.Activity.performCreate(Activity.java:6057)
at android.app.Instrumentation.callActivityOnCreate(Instrumentation.java:1106)
at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2331)
at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2440) 
at android.app.ActivityThread.access$800(ActivityThread.java:162) 
at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1348) 
at android.os.Handler.dispatchMessage(Handler.java:102) 
at android.os.Looper.loop(Looper.java:135) 
at android.app.ActivityThread.main(ActivityThread.java:5422) 
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:914) 
at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:707)

我的文件:

<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_CONTACTS"/>

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:supportsRtl="true"
    android:theme="@style/Theme.AppCompat.NoActionBar">

    <activity android:name="todonotes.com.todonotes_buildfinale.SplashScreen"
        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="todonotes.com.todonotes_buildfinale.LoginActivity" android:theme="@style/AppTheme.Dark"
        android:label="@string/app_name">
        <intent-filter>
            <action android:name="todonotes.com.todonotes_buildfinale.SIGNUPACTIVITY"/>

            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
    </activity>


    <activity
        android:name="todonotes.com.todonotes_buildfinale.ContactsListActivity" android:theme="@style/AppTheme"
        android:label="@string/activity_contacts_list"
        android:windowSoftInputMode="adjustResize">

        <intent-filter>
            <action android:name="android.intent.action.MAIN" />
            <category android:name="android.intent.category.DEFAULT" />
        </intent-filter>
        <!-- Add intent-filter for search intent action and specify searchable configuration
             via meta-data tag. This allows this activity to receive search intents via the
             system hooks. In this sample this is only used on older OS versions (pre-Honeycomb)
             via the activity search dialog. See the Search API guide for more information:
             http://developer.android.com/guide/topics/search/search-dialog.html -->
        <intent-filter>
            <action android:name="android.intent.action.SEARCH" />
        </intent-filter>
        <meta-data android:name="android.app.searchable"
            android:resource="@xml/searchable_contacts" />
    </activity>
    <activity
        android:name="todonotes.com.todonotes_buildfinale.ContactDetailActivity"  android:theme="@style/AppTheme"
        android:label="@string/activity_contact_detail"
        android:parentActivityName="todonotes.com.todonotes_buildfinale.ContactDetailActivity">
        <!-- Define hierarchical parent of this activity, both via the system
             parentActivityName attribute (added in API Level 16) and via meta-data annotation.
             This allows use of the support library NavUtils class in a way that works over
             all Android versions. See the "Tasks and Back Stack" guide for more information:
             http://developer.android.com/guide/components/tasks-and-back-stack.html
        -->
        <meta-data android:name="android.support.PARENT_ACTIVITY"
            android:value="todonotes.com.todonotes_buildfinale.ContactDetailActivity" />
    </activity>
    <activity android:name="todonotes.com.todonotes_buildfinale.SignupActivity" android:theme="@style/AppTheme.Dark"></activity>
    <activity android:name="todonotes.com.todonotes_buildfinale.ConfirmActivity" android:theme="@style/AppTheme.Dark"></activity>
    <activity android:name="todonotes.com.todonotes_buildfinale.ListNoteActivity" android:theme="@style/AppTheme.Dark"></activity>

</application>

</manifest>

活动:

public class ContactDetailActivity extends FragmentActivity {

    // Defines a tag for identifying the single fragment that this activity holds
    private static final String TAG = "ContactDetailActivity";

    @TargetApi(Build.VERSION_CODES.HONEYCOMB)
    @Override
    protected void onCreate(Bundle savedInstanceState) {
        //setContentView(R.layout.contact_detail_fragment);


        if (BuildConfig.DEBUG) {
            // Enable strict mode checks when in debug modes
            Utils.enableStrictMode();
        }
        super.onCreate(savedInstanceState);

        // This activity expects to receive an intent that contains the uri of a contact
        if (getIntent() != null) {

            // For OS versions honeycomb and higher use action bar
            if (Utils.hasHoneycomb()) {
                // Enables action bar "up" navigation
                //getActionBar().setDisplayHomeAsUpEnabled(true);
                //((ActionBarActivity))getActivity()).getSupportActionBar();
                if(getActionBar()!=null){
                    getActionBar().setDisplayHomeAsUpEnabled(true);
                }

                //getActionBar().setDisplayHomeAsUpEnabled(true);

            }

            // Fetch the data Uri from the intent provided to this activity
            final Uri uri = getIntent().getData();

            // Checks to see if fragment has already been added, otherwise adds a new
            // ContactDetailFragment with the Uri provided in the intent
            if (getSupportFragmentManager().findFragmentByTag(TAG) == null) {
                final FragmentTransaction ft = getSupportFragmentManager().beginTransaction();

                // Adds a newly created ContactDetailFragment that is instantiated with the
                // data Uri
                ft.add(android.R.id.content, ContactDetailFragment.newInstance(uri), TAG);
                ft.commit();
            }
        } else {
            // No intent provided, nothing to do so finish()
            finish();
        }
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        switch (item.getItemId()) {
            case android.R.id.home:
                // Tapping on top left ActionBar icon navigates "up" to hierarchical parent screen.
                // The parent is defined in the AndroidManifest entry for this activity via the
                // parentActivityName attribute (and via meta-data tag for OS versions before API
                // Level 16). See the "Tasks and Back Stack" guide for more information:
                // http://developer.android.com/guide/components/tasks-and-back-stack.html
                NavUtils.navigateUpFromSameTask(this);
                return true;
        }
        // Otherwise, pass the item to the super implementation for handling, as described in the
        // documentation.
        return super.onOptionsItemSelected(item);
    }
}

我该如何解决这个问题?

更新:

在contactDetails中我修改了以下代码:

public class ContactDetailActivity extends AppCompatActivity {

    if (Utils.hasHoneycomb()) {

        if(getSupportActionBar()!=null){
            getSupportActionBar().setDisplayHomeAsUpEnabled(true);
        }

        //getActionBar().setDisplayHomeAsUpEnabled(true);
    }

结果是: the bar in the list is missing

问题在于此活动:CONTACTLISTACTIVITY

public class ContactsListActivity extends FragmentActivity implements
        ContactsListFragment.OnContactsInteractionListener {

    // Defines a tag for identifying log entries
    private static final String TAG = "ContactsListActivity";

    private ContactDetailFragment mContactDetailFragment;

    // If true, this is a larger screen device which fits two panes
    private boolean isTwoPaneLayout;

    // True if this activity instance is a search result view (used on pre-HC devices that load
    // search results in a separate instance of the activity rather than loading results in-line
    // as the query is typed.
    private boolean isSearchResultView = false;



    @Override
    protected void onCreate(Bundle savedInstanceState) {


        if (BuildConfig.DEBUG) {
            Utils.enableStrictMode();

        }
        super.onCreate(savedInstanceState);

        // Set main content view. On smaller screen devices this is a single pane view with one
        // fragment. One larger screen devices this is a two pane view with two fragments.
        setContentView(R.layout.activity_main);

        // Check if two pane bool is set based on resource directories
        isTwoPaneLayout = getResources().getBoolean(R.bool.has_two_panes);

        // Check if this activity instance has been triggered as a result of a search query. This
        // will only happen on pre-HC OS versions as from HC onward search is carried out using
        // an ActionBar SearchView which carries out the search in-line without loading a new
        // Activity.
        if (Intent.ACTION_SEARCH.equals(getIntent().getAction())) {

            // Fetch query from intent and notify the fragment that it should display search
            // results instead of all contacts.
            String searchQuery = getIntent().getStringExtra(SearchManager.QUERY);
            ContactsListFragment mContactsListFragment = (ContactsListFragment)
                    getSupportFragmentManager().findFragmentById(R.id.contact_list);

            // This flag notes that the Activity is doing a search, and so the result will be
            // search results rather than all contacts. This prevents the Activity and Fragment
            // from trying to a search on search results.
            isSearchResultView = true;
            mContactsListFragment.setSearchQuery(searchQuery);

            // Set special title for search results
            String title = getString(R.string.contacts_list_search_results_title, searchQuery);
            setTitle(title);
        }

        if (isTwoPaneLayout) {
            // If two pane layout, locate the contact detail fragment
            mContactDetailFragment = (ContactDetailFragment)
                    getSupportFragmentManager().findFragmentById(R.id.contact_detail);
        }
    }

    /**
     * This interface callback lets the main contacts list fragment notify
     * this activity that a contact has been selected.
     *
     * @param contactUri The contact Uri to the selected contact.
     */
    @Override
    public void onContactSelected(Uri contactUri) {
        if (isTwoPaneLayout && mContactDetailFragment != null) {
            // If two pane layout then update the detail fragment to show the selected contact
            mContactDetailFragment.setContact(contactUri);
        } else {
            // Otherwise single pane layout, start a new ContactDetailActivity with
            // the contact Uri
            Intent intent = new Intent(this, ContactDetailActivity.class);
            intent.setData(contactUri);
            startActivity(intent);
        }
    }

    /**
     * This interface callback lets the main contacts list fragment notify
     * this activity that a contact is no longer selected.
     */
    @Override
    public void onSelectionCleared() {
        if (isTwoPaneLayout && mContactDetailFragment != null) {
            mContactDetailFragment.setContact(null);
        }
    }

    @Override
    public boolean onSearchRequested() {
        // Don't allow another search if this activity instance is already showing
        // search results. Only used pre-HC.
        return !isSearchResultView && super.onSearchRequested();
    }
}

最后修改:

<style name="AppTheme" parent="Theme.AppCompat.Light.DarkActionBar"> 
    <item name="colorPrimary">@color/primary</item>
    <item name="colorPrimaryDark">@color/primary_dark</item> 
    <item name="colorAccent">@color/accent</item>
</style> 

我已经在我的样式xml中执行此操作....在清单中我的活动使用AppTheme然后我更改了myActivity扩展AppCompatActivity。

1 个答案:

答案 0 :(得分:0)

为避免异常,请使用:

if(getActionBar()!=null){
    getActionBar().setDisplayHomeAsUpEnabled(true);
}

但最好的方法是让您的活动延长AppCompatActivity

然后使用:

if(getSupportActionBar()!=null){
    getSupportActionBar().setDisplayHomeAsUpEnabled(true);
}