所以我对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)
如果您需要任何其他文件,请告诉我们。提前谢谢。
答案 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();