Android应用程序在扩展到FragmentActivity时崩溃

时间:2015-01-17 04:20:45

标签: java android android-fragments

所以我对Android开发很新。我一直在开发一个Android Prayer Times应用程序,它一直工作得非常好,直到我想整合Google Play Services for Location。当我跟随Accessing Location Guide时,我被指示首先设置(我已经完成)然后connect to Google Play Services。这就是问题所在。我浏览了整个页面,了解如何连接到Google API并正确遵循指示。然后我意识到我必须改变我的

public class MainActivity extends Activity

public class MainAcitvity extends FragmentActivity

根据developer.android.com上的指南。之后,当我尝试使用手机时,我的应用程序不再运行。

我对Android中的Fragment一点都不熟悉。我需要在我的xml文件中放一个Fragment吗?

继承我的MainActivity.java文件:

package com.ahmed.omar.tawheed;

import android.app.Activity;
import android.app.Dialog;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.IntentSender;
import android.os.Bundle;
import android.support.v4.app.DialogFragment;
import android.support.v4.app.FragmentActivity;
import android.view.Menu;
import android.view.MenuInflater;
import android.view.MenuItem;
import android.widget.TextView;
import android.widget.Toast;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.GooglePlayServicesUtil;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationServices;

import android.support.v4.app.FragmentActivity;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.Date;

public class MainActivity extends FragmentActivity
        implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener {

    private TextView txtPrayerNames;
    private TextView txtPrayerTimes;

    private GoogleApiClient mGoogleApiClient;

    // Request code to use when launching the resolution activity
    private static final int REQUEST_RESOLVE_ERROR = 1001;
    // Unique tag for the error dialog fragment
    private static final String DIALOG_ERROR = "dialog_error";
    // Bool to track whether the app is already resolving an error
    private boolean mResolvingError = false;

    private static final String STATE_RESOLVING_ERROR = "resolving_error";

    @Override
    protected void onCreate(Bundle savedInstanceState) {

        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        txtPrayerNames = (TextView) findViewById(R.id.txtPrayerNames);
        txtPrayerTimes = (TextView) findViewById(R.id.txtPrayerTimes);

        getTimes();

        GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) //used to connect
                .addConnectionCallbacks(this)                               // to Google Play Services
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

        mResolvingError = savedInstanceState != null
                && savedInstanceState.getBoolean(STATE_RESOLVING_ERROR, false);

    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) { //Used to Create App Bar

        // Inflate the menu items for use in the action bar
        MenuInflater inflater = getMenuInflater();
        inflater.inflate(R.menu.main_activity_actions, menu);

        return super.onCreateOptionsMenu(menu);
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) { //Used to Handle Presses on App Bar Items
        // Handle presses on the action bar items
        switch (item.getItemId()) {
            case R.id.action_refresh:
                getTimes();
                return true;
            case R.id.action_settings:
                openSettings();
                return true;
            default:
                return super.onOptionsItemSelected(item);
        }
    }

    private void openSettings() { //misc
        Toast.makeText(this, "Settings button pressed", Toast.LENGTH_SHORT).show();
    }

    /********************************************************************/

    @Override
    public void onConnected(Bundle connectionHint) {
        // Connected to Google Play services!
        // The good stuff goes here.
    }

    @Override
    public void onConnectionSuspended(int cause) {
        // The connection has been interrupted.
        // Disable any UI components that depend on Google APIs
        // until onConnected() is called.
    }

    @Override
    public void onConnectionFailed(ConnectionResult result) {
        // This callback is important for handling errors that
        // may occur while attempting to connect with Google.
        //
        if (mResolvingError) {
            // Already attempting to resolve an error.
            return;
        } else if (result.hasResolution()) {
            try {
                mResolvingError = true;
                result.startResolutionForResult(this, REQUEST_RESOLVE_ERROR);
            } catch (IntentSender.SendIntentException e) {
                // There was an error with the resolution intent. Try again.
                mGoogleApiClient.connect();
            }
        } else {
            // Show dialog using GooglePlayServicesUtil.getErrorDialog()
            showErrorDialog(result.getErrorCode());
            mResolvingError = true;
        }

    }

    /**----------------------------------------------------------------**/

    /* Creates a dialog for an error message */
    private void showErrorDialog(int errorCode) {
        // Create a fragment for the error dialog
        ErrorDialogFragment dialogFragment = new ErrorDialogFragment();
        // Pass the error that should be displayed
        Bundle args = new Bundle();
        args.putInt(DIALOG_ERROR, errorCode);
        dialogFragment.setArguments(args);
        dialogFragment.show(getSupportFragmentManager(), "errordialog");
    }

    /* Called from ErrorDialogFragment when the dialog is dismissed. */
    public void onDialogDismissed() {
        mResolvingError = false;
    }

    /* A fragment to display an error dialog */
    public static class ErrorDialogFragment extends DialogFragment {
        public ErrorDialogFragment() { }

        @Override
        public Dialog onCreateDialog(Bundle savedInstanceState) {
            // Get the error code and retrieve the appropriate dialog
            int errorCode = this.getArguments().getInt(DIALOG_ERROR);
            return GooglePlayServicesUtil.getErrorDialog(errorCode,
                    this.getActivity(), REQUEST_RESOLVE_ERROR);
        }

        @Override
        public void onDismiss(DialogInterface dialog) {
            ((MainActivity)getActivity()).onDialogDismissed();
        }
    }

    /**----------------------------------------------------------------**/

    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {
        if (requestCode == REQUEST_RESOLVE_ERROR) {
            mResolvingError = false;
            if (resultCode == RESULT_OK) {
                // Make sure the app is not already connected or attempting to connect
                if (!mGoogleApiClient.isConnecting() &&
                        !mGoogleApiClient.isConnected()) {
                    mGoogleApiClient.connect();
                }
            }
        }
    }

    /**----------------------------------------------------------------**/

    @Override
    protected void onSaveInstanceState(Bundle outState) {
        super.onSaveInstanceState(outState);
        outState.putBoolean(STATE_RESOLVING_ERROR, mResolvingError);
    }

    /**----------------------------------------------------------------**/

    @Override
    protected void onStart() {
        super.onStart();
        if (!mResolvingError) {  // more about this later
            mGoogleApiClient.connect();
        }
    }

    @Override
    protected void onStop() {
        mGoogleApiClient.disconnect();
        super.onStop();
    }

    /********************************************************************/


    // method to append Updated prayer times into TextView in activity_main
    public void getTimes() {

        // Retrieve LATITUDE, LONGITUDE, and TIMEZONE using location API. Currently set for Detroit
        double latitude = 42.3314;
        double longitude = -83.0458;
        double timezone = -5;

        String sFajr, sSunrise, sDhuhr, sAsr, sSunset, sMaghrib, sIsha;

        PrayTime prayers = new PrayTime();

        prayers.setTimeFormat(prayers.Time12);
        prayers.setCalcMethod(prayers.ISNA);
        prayers.setAsrJuristic(prayers.Hanafi);
        prayers.setAdjustHighLats(prayers.None);
        int[] offsets = { 0, 0, 0, 0, 0, 0, 0 }; // {Fajr,Sunrise,Dhuhr,Asr,Sunset,Maghrib,Isha}
        prayers.tune(offsets);

        Date now = new Date();
        Calendar cal = Calendar.getInstance();
        cal.setTime(now);

        ArrayList prayerTimes = prayers.getPrayerTimes(cal, latitude,
                longitude, timezone);
        ArrayList prayerNames = prayers.getTimeNames();


        sFajr = ""+prayerTimes.get(0);
        sSunrise = ""+prayerTimes.get(1);
        sDhuhr = ""+prayerTimes.get(2);
        sAsr = ""+prayerTimes.get(3);
        sSunset = ""+prayerTimes.get(4);
        sMaghrib = ""+prayerTimes.get(5);
        sIsha = ""+prayerTimes.get(6);

        txtPrayerNames.setText("");
        txtPrayerTimes.setText("");

        for (int i = 0; i < 7; i++) {
            txtPrayerNames.append("\n"+prayerNames.get(i));
            txtPrayerTimes.append("\n"+prayerTimes.get(i));
        }

        Toast.makeText(this, "Prayer Times Updated", Toast.LENGTH_SHORT).show();

    }
}

这是我的activity_main.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"
    android:orientation="horizontal" >

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:text="Detroit, MI"
        android:gravity="center"
        android:layout_centerHorizontal="true"
        android:textSize="40sp"
        android:layout_margin="32dp"/>

    <TextView
        android:id="@+id/txtPrayerNames"
        android:gravity="left"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_centerVertical="true"
        android:textSize="35sp"
        android:layout_margin="32dp"/>

    <TextView
        android:id="@+id/txtPrayerTimes"
        android:gravity="right"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_alignParentRight="true"
        android:layout_centerVertical="true"
        android:textSize="35sp"
        android:layout_margin="32dp"/>


</RelativeLayout>

最后是logcat:

01-16 23:16:18.457    2030-2030/com.ahmed.omar.tawheed I/art﹕ Late-enabling -Xcheck:jni
01-16 23:16:18.643    2030-2030/com.ahmed.omar.tawheed D/AndroidRuntime﹕ Shutting down VM
01-16 23:16:18.644    2030-2030/com.ahmed.omar.tawheed E/AndroidRuntime﹕ FATAL EXCEPTION: main
    Process: com.ahmed.omar.tawheed, PID: 2030
    java.lang.RuntimeException: Unable to start activity ComponentInfo{com.ahmed.omar.tawheed/com.ahmed.omar.tawheed.MainActivity}: java.lang.NullPointerException: Attempt to invoke interface method 'void com.google.android.gms.common.api.GoogleApiClient.connect()' on a null object reference
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2298)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            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:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)
     Caused by: java.lang.NullPointerException: Attempt to invoke interface method 'void com.google.android.gms.common.api.GoogleApiClient.connect()' on a null object reference
            at com.ahmed.omar.tawheed.MainActivity.onStart(MainActivity.java:201)
            at android.app.Instrumentation.callActivityOnStart(Instrumentation.java:1220)
            at android.app.Activity.performStart(Activity.java:5949)
            at android.app.ActivityThread.performLaunchActivity(ActivityThread.java:2261)
            at android.app.ActivityThread.handleLaunchActivity(ActivityThread.java:2360)
            at android.app.ActivityThread.access$800(ActivityThread.java:144)
            at android.app.ActivityThread$H.handleMessage(ActivityThread.java:1278)
            at android.os.Handler.dispatchMessage(Handler.java:102)
            at android.os.Looper.loop(Looper.java:135)
            at android.app.ActivityThread.main(ActivityThread.java:5221)
            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:899)
            at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:694)

如果您需要任何其他文件,请告诉我们。提前谢谢。

3 个答案:

答案 0 :(得分:0)

  

NullPointerException:尝试调用接口方法'void   com.google.android.gms.common.api.GoogleApiClient.connect()'上的null   对象参考

当您调用mGoogleApiClient方法时,null对象为connect()

您正在mGoogleApiClient中创建单独的onCreate对象,并使用未初始化的对象来调用connect方法。因此,请使用在onCreate方法之前声明并在onStart方法中使用的相同对象:

  mGoogleApiClient = new GoogleApiClient.Builder(this)  
                .addConnectionCallbacks(this)   
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

答案 1 :(得分:0)

虽然您已在GoogleApiClient方法中新建了具有相同名称的对象,但您已在声明部分中创建了onCreate()的实例。

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) //used to connect
            .addConnectionCallbacks(this)                               // to Google Play Services
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();

所以你需要像

一样更改上面的代码
mGoogleApiClient = new GoogleApiClient.Builder(this) //used to connect
            .addConnectionCallbacks(this)                               // to Google Play Services
            .addOnConnectionFailedListener(this)
            .addApi(LocationServices.API)
            .build();

答案 2 :(得分:0)

您的全局变量mGoogleApiClient未定义。 oncreate()调用后它仍然为空。因此mGoogleApiClient.connect();会抛出nullpointerexception

更改此

GoogleApiClient mGoogleApiClient = new GoogleApiClient.Builder(this) //used to connect
                .addConnectionCallbacks(this)                               // to Google Play Services
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();

mGoogleApiClient = new GoogleApiClient.Builder(this) //used to connect
                .addConnectionCallbacks(this)                               // to Google Play Services
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();