android - 导航栏 fragment 内的 Google Map API 错误

标签 android google-maps android-fragments android-fragmentactivity google-api-client

我正在尝试构建一个带有导航栏和 Google Map API 的应用程序。

我遵循了这两个:

http://www.androidhive.info/2015/04/android-getting-started-with-material-design/

http://blog.teamtreehouse.com/beginners-guide-location-android

教程,当我将 map 教程放入导航栏中的一个 fragment 时,我收到以下错误:

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

错误出在构建器内的“this”中。

这是我完整的类代码:

package com.clark.androbotics.projectapp;

import android.app.Activity;
import android.content.IntentSender;
import android.location.Location;
import android.os.Bundle;
import android.support.v4.app.Fragment;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;

import com.google.android.gms.common.ConnectionResult;
import com.google.android.gms.common.api.GoogleApiClient;
import com.google.android.gms.location.LocationListener;
import com.google.android.gms.location.LocationRequest;
import com.google.android.gms.location.LocationServices;
import com.google.android.gms.maps.CameraUpdateFactory;
import com.google.android.gms.maps.GoogleMap;
import com.google.android.gms.maps.SupportMapFragment;
import com.google.android.gms.maps.UiSettings;
import com.google.android.gms.maps.model.LatLng;
import com.google.android.gms.maps.model.MarkerOptions;

public class MapFragment extends Fragment implements
    GoogleApiClient.ConnectionCallbacks,
    GoogleApiClient.OnConnectionFailedListener,
    LocationListener {

public static final String TAG = MapFragment.class.getSimpleName();

private final static int CONNECTION_FAILURE_RESOLUTION_REQUEST = 9000;

private GoogleApiClient myGoogleApiClient;
private LocationRequest myLocationRequest;

private GoogleMap mMap; // Might be null if Google Play services APK is not available.

public MapFragment() {
    // Required empty public constructor
}

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    setUpMapIfNeeded();

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

    // Create the LocationRequest object
    myLocationRequest = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(10 * 1000)         // 10 seconds, in milliseconds
            .setFastestInterval(1 * 1000);  // 1 second, in milliseconds

}

@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container,
                         Bundle savedInstanceState) {
    View rootView = inflater.inflate(R.layout.fragment_map, container, false);

    // Inflate the layout for this fragment
    return rootView;
}

@Override
public void onResume() {
    super.onResume();
    setUpMapIfNeeded();

    myGoogleApiClient.connect();
}

@Override
public void onPause() {
    super.onPause();
    if (myGoogleApiClient.isConnected()) {
        LocationServices.FusedLocationApi.removeLocationUpdates(myGoogleApiClient, this);
        myGoogleApiClient.disconnect();
    }
}

/**
 * Sets up the map if it is possible to do so (i.e., the Google Play services APK is correctly
 * installed) and the map has not already been instantiated.. This will ensure that we only ever
 * call {@link #setUpMap()} once when {@link #mMap} is not null.
 * <p/>
 * If it isn't installed {@link com.google.android.gms.maps.SupportMapFragment} (and
 * {@link com.google.android.gms.maps.MapView MapView}) will show a prompt for the user to
 * install/update the Google Play services APK on their device.
 * <p/>
 * A user can return to this FragmentActivity after following the prompt and correctly
 * installing/updating/enabling the Google Play services. Since the FragmentActivity may not
 * have been completely destroyed during this process (it is likely that it would only be
 * stopped or paused), {@link #onCreate(Bundle)} may not be called again so we should call this
 * method in {@link #onResume()} to guarantee that it will be called.
 */
private void setUpMapIfNeeded() {
    // Do a null check to confirm that we have not already instantiated the map.
    if (mMap == null) {
        // Try to obtain the map from the SupportMapFragment.
        mMap = ((SupportMapFragment) getFragmentManager().findFragmentById(R.id.map))
                .getMap();
        // Check if we were successful in obtaining the map.
        if (mMap != null) {
            setUpMap();
        }
    }
}

/**
 * This is where we can add markers or lines, add listeners or move the camera. In this case, we
 * just add a marker near Africa.
 * <p/>
 * This should only be called once and when we are sure that {@link #mMap} is not null.
 */
private void setUpMap() {
    UiSettings mapSettings;
    mapSettings = mMap.getUiSettings();

    mapSettings.setZoomControlsEnabled(true);

    mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
}

private void handleNewLocation(Location myLocation) {
    double currentLatitude = myLocation.getLatitude();
    double currentLongitude = myLocation.getLongitude();
    LatLng latLng = new LatLng(currentLatitude, currentLongitude);

    MarkerOptions options = new MarkerOptions().position(latLng).title("I am here!");
    mMap.addMarker(options);
    mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, 17));
}

@Override
public void onAttach(Activity activity) {
    super.onAttach(activity);
}

@Override
public void onDetach() {
    super.onDetach();
}

@Override
public void onConnected(Bundle bundle) {
    Location myLocation = LocationServices.FusedLocationApi.getLastLocation(myGoogleApiClient);

    if (myLocation == null) {
        LocationServices.FusedLocationApi.requestLocationUpdates(myGoogleApiClient, myLocationRequest, this);
    }
    else {
        handleNewLocation(myLocation);
    };
}

@Override
public void onConnectionSuspended(int i) {

}

@Override
public void onLocationChanged(Location location) {

}

@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
    if (connectionResult.hasResolution()) {
        try {
            // Start an Activity that tries to resolve the error
            connectionResult.startResolutionForResult(this, CONNECTION_FAILURE_RESOLUTION_REQUEST);
        } catch (IntentSender.SendIntentException e) {
            e.printStackTrace();
        }
    } else {
        Log.i(TAG, "Location services connection failed with code " + connectionResult.getErrorCode());
    }

}
}

我相信我添加了必要的导入,但我似乎无法修复它。

我是 Android 开发新手,所以我不太确定问题所在。

编辑:应用程序运行,但每当我转到此 fragment 时就会强制关闭。

似乎存在有关空对象引用的错误。

这是我的日志:

    05-08 15:42:20.468  24080-24080/com.clark.androbotics.projectapp E/AndroidRuntime﹕ FATAL EXCEPTION: main
Process: com.clark.androbotics.projectapp, PID: 24080
java.lang.NullPointerException: Attempt to invoke virtual method 'com.google.android.gms.maps.GoogleMap com.google.android.gms.maps.SupportMapFragment.getMap()' on a null object reference
        at com.clark.androbotics.projectapp.MapFragment.setUpMapIfNeeded(MapFragment.java:108)
        at com.clark.androbotics.projectapp.MapFragment.onCreate(MapFragment.java:46)
        at android.support.v4.app.Fragment.performCreate(Fragment.java:1763)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:915)
        at android.support.v4.app.FragmentManagerImpl.moveToState(FragmentManager.java:1136)
        at android.support.v4.app.BackStackRecord.run(BackStackRecord.java:739)
        at android.support.v4.app.FragmentManagerImpl.execPendingActions(FragmentManager.java:1499)
        at android.support.v4.app.FragmentManagerImpl$1.run(FragmentManager.java:456)
        at android.os.Handler.handleCallback(Handler.java:739)
        at android.os.Handler.dispatchMessage(Handler.java:95)
        at android.os.Looper.loop(Looper.java:135)
        at android.app.ActivityThread.main(ActivityThread.java:5293)
        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:904)
        at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:699)

我相信这与 fragment 上的 .getMap 有关,但我不确定。我也尝试将其放入 OnCreateView 中,但仍然有相同的错误。

非常感谢任何帮助。

最佳答案

GoogleApiClient.Builder构造函数采用 Context例如 ActivityService 等,但您传递的 this 在本例中是一个 Fragment (它不会扩展Context)。

相反,您传入 getActivity(),它返回 fragment 当前附加到的 Activity:

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

关于android - 导航栏 fragment 内的 Google Map API 错误,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/29934142/

相关文章:

android - 如何使用 AccessibilityService 在 Android 中模拟按键

google-maps - 有一些限制的旅行推销员

android - 在 Fragment 中关闭软键盘

android - 什么是永久广播?

android - 将 FragmentPagerAdapter 作为 fragment 本身的 ViewPager?

iphone - 从我的应用程序中打开 map iPhone应用程序,将大头针放在坐标处

java - 相对布局中的 ViewPager 消耗完整高度(选项卡)

android - editTexts 在旋转设备时更改其值

java - Android Volley 发布请求不起作用

javascript - 谷歌浏览器 84 + 谷歌地图信息窗口 : Prevent webpage jump when clicking close button