2016-12-16 85 views
0

我正在嘗試在我正在處理的項目中使用Google地圖,並且無法將地圖作爲片段工作。我想將地圖作爲片段使用,並將片段添加到我的主要活動中(假設我可以在需要的地方重新使用此片段),但應用程序崩潰或無法執行除加載地圖以外的任何操作,具體取決於在我嘗試和改變。在片段中使用Google地圖

下面是我用作我的MapsFragment.java文件中代碼基礎的教程。 https://developers.google.com/maps/documentation/android-api/current-places-tutorial

下面是我使用的嘗試,並從我activity_main.xml

<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android" 
      android:id="@+id/fragment_container" 
      android:orientation="vertical" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent"> 

<Button 
    android:layout_height="wrap_content" 
    android:layout_width="match_parent" 
    android:text="text"/> 

<fragment xmlns:android="http://schemas.android.com/apk/res/android" 
      xmlns:tools="http://schemas.android.com/tools" 
      android:id="@+id/map_fragment" 
      android:name="com.google.android.gms.maps.SupportMapFragment" 
      android:layout_width="match_parent" 
      android:layout_height="match_parent" 
      tools:context="[path info].MapsFragment"/> 
</LinearLayout> 

    @Override 
    public void onConnected(Bundle connectionHint) { 
     getDeviceLocation(); 
     SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map_fragment); 
     mapFragment.getMapAsync(this); 
    } 

有了這個XML地圖將加載內顯示地圖的基本標籤,但它似乎並沒有調用任何我的Fragment類中的方法。它當然不會調用onCreate,onCreateView或onConnected。

下面是我的片段類的代碼,MapsFragment.java

import android.Manifest; 
import android.app.Activity; 
import android.content.pm.PackageManager; 
import android.location.Location; 
import android.support.annotation.NonNull; 
import android.support.v4.app.ActivityCompat; 
import android.support.v4.app.Fragment; 
import android.support.v4.app.FragmentActivity; 
import android.os.Bundle; 
import android.support.v4.app.FragmentManager; 
import android.support.v4.content.ContextCompat; 
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.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.OnMapReadyCallback; 
import com.google.android.gms.maps.SupportMapFragment; 
import com.google.android.gms.maps.model.CameraPosition; 
import com.google.android.gms.maps.model.LatLng; 
import com.google.android.gms.maps.model.Marker; 
import com.google.android.gms.maps.model.MarkerOptions; 
import com.google.android.gms.location.LocationListener; 

import java.util.Date; 

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

    private static final String TAG = MapsActivity.class.getSimpleName(); 
    private GoogleMap mMap; 

    // A default location (Sydney, Australia) and default zoom to use when location permission is 
    // not granted. 
    private final LatLng mDefaultLocation = new LatLng(-33.8523341, 151.2106085); 
    private static final int DEFAULT_ZOOM = 15; 
    private static final int PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION = 1; 
    private boolean mLocationPermissionGranted; 


    private Location mCurrentLocation; 
    private Marker mCurrentLocationMarker; 

    private CameraPosition mCameraPosition; 

    private GoogleApiClient mGoogleApiClient; 
    private LocationRequest mLocationRequest; 
    private static final long UPDATE_INTERVAL_IN_MILLISECONDS = 10000; 
    private static final long FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS = 
      UPDATE_INTERVAL_IN_MILLISECONDS/2; 

    // Keys for storing activity state. 
    private static final String KEY_CAMERA_POSITION = "camera_position"; 
    private static final String KEY_LOCATION = "location"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     // initialize GoogleAPIClient 
     Activity parentActivity = this.getActivity(); 
     if (parentActivity != null) { 
      mGoogleApiClient = new GoogleApiClient.Builder(this.getActivity()) 
        .addConnectionCallbacks(this) 
        .addOnConnectionFailedListener(this) 
        .addApi(LocationServices.API) 
        .build(); 
      createLocationRequest(); 

     } 
    } 

    public View onCreateView(LayoutInflater inflater, ViewGroup container, 
     Bundle savedInstanceState) { 
     // Inflate the layout for this fragment 
     return inflater.inflate(R.layout.activity_maps, container, false); 
    } 

    @Override 
    public void onResume() { 
     super.onResume(); 
     //setUpMapIfNeeded(); 
     if (mGoogleApiClient.isConnected()) { 
      getDeviceLocation(); 
     } else { 
      mGoogleApiClient.connect(); 
     } 
    } 

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

    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     mMap = googleMap; 

     if (mCurrentLocation != null) { 
      LatLng latLng = new LatLng(mCurrentLocation.getLatitude(), mCurrentLocation.getLongitude()); // maybe add default zoom? 
      mMap.addMarker(new MarkerOptions().position(latLng).title("You")); //(latLng).title("Marker")); 
      mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM)); 
     } else { 
      Log.d(TAG, "Current location is null. Using defaults."); 
      mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(mDefaultLocation, 10));  //zoom to Sydney, Australia 
     } 
    } 

    @Override 
    public void onConnected(Bundle connectionHint) { 
     getDeviceLocation(); 
     SupportMapFragment mapFragment = (SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map_fragment); 
     mapFragment.getMapAsync(this); 
    } 

    @Override 
    public void onConnectionFailed(@NonNull ConnectionResult result) { 
     // Refer to the reference doc for ConnectionResult to see what error codes might 
     // be returned in onConnectionFailed. 
     Log.d(TAG, "Play services connection failed: ConnectionResult.getErrorCode() = " 
     + result.getErrorCode()); 
    } 

    @Override 
    public void onConnectionSuspended(int cause) { 
     Log.d(TAG, "Play services connection suspended"); 
    } 

    @Override 
    public void onLocationChanged(Location location) { 
     mCurrentLocation = location; 
     //updateMarkers(); 
     if (mCurrentLocationMarker != null) { 
      mCurrentLocationMarker.remove(); 
     } 
     LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude()); 
     // DEBUG 
     Date date = new Date(); 
     int hour = date.getHours(); 
     int minutes = date.getMinutes(); 
     String time = String.valueOf(hour) + ":" + String.valueOf(minutes); 
     // 
     mMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng, DEFAULT_ZOOM)); 
     // might need mMap.animateCamera(CameraUpdateFactory.zoomTo(11)) to animate transition. Not sure. 
     MarkerOptions markerOptions = new MarkerOptions(); 
     markerOptions.position(latLng); 
     markerOptions.title(time); 
     mCurrentLocationMarker = mMap.addMarker(markerOptions); 

     Log.d(TAG, latLng.toString() + ", Time: " + time); 
    } 

    private void getDeviceLocation() { 
     if (ContextCompat.checkSelfPermission(this.getContext(), 
      Manifest.permission.ACCESS_FINE_LOCATION) == PackageManager.PERMISSION_GRANTED) 
     { 
      mLocationPermissionGranted = true; 
     } else { 
      ActivityCompat.requestPermissions(this.getActivity(), 
       new String[] {Manifest.permission.ACCESS_FINE_LOCATION}, 
       PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION); 
     } 

     if (mLocationPermissionGranted) { 
      mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
      LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, 
      mLocationRequest, this); 
     } 
    } 

    @Override 
    public void onRequestPermissionsResult(int requestCode, 
    @NonNull String permissions[], 
    @NonNull int[] grantResults) { 
     mLocationPermissionGranted = false; 
     switch (requestCode) { 
      case PERMISSIONS_REQUEST_ACCESS_FINE_LOCATION: { 
       // If request is cancelled, the result arrays are empty. 
       if (grantResults.length > 0 
         && grantResults[0] == PackageManager.PERMISSION_GRANTED) { 
        mLocationPermissionGranted = true; 
       } 
      } 
     } 
     updateLocationUI(); 
    } 

    @SuppressWarnings("MissingPermission") 
    private void updateLocationUI() { 
     if (mMap == null) { 
      return; 
     } 

     if (mLocationPermissionGranted) { 
      mMap.setMyLocationEnabled(true); 
      mMap.getUiSettings().setMyLocationButtonEnabled(true); 
     } else { 
      mMap.setMyLocationEnabled(false); 
      mMap.getUiSettings().setMyLocationButtonEnabled(false); 
      mCurrentLocation = null; 
     } 
    } 

    private void createLocationRequest() { 
     mLocationRequest = new LocationRequest(); 

     mLocationRequest.setInterval(UPDATE_INTERVAL_IN_MILLISECONDS); 
     mLocationRequest.setFastestInterval(FASTEST_UPDATE_INTERVAL_IN_MILLISECONDS); 
     mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY); 
    } 
} 

我已經嘗試擺脫Android系統:名稱名稱 - 值對,並添加類=在「[完全合格的路徑名稱]」 XML,因爲我想我需要一種方法將類和片段綁定在一起,以便在片段被充滿時執行代碼。如果我這樣做,我的類代碼實際上是所謂的,但我得到以下錯誤,當getMapAsync內被稱爲onConnected

java.lang.NullPointerException: Attempt to invoke virtual method 'void com.google.android.gms.maps.SupportMapFragment.getMapAsync(com.google.android.gms.maps.OnMapReadyCallback)' on a null object reference 
                     at [the path info].MapsFragment.onConnected(MapsFragment.java:163) 
                     at com.google.android.gms.common.internal.zzm.zzq(Unknown Source) 
                     at com.google.android.gms.internal.zzaal.zzo(Unknown Source) 
                     at com.google.android.gms.internal.zzaaj.zzvE(Unknown Source) 
                     at com.google.android.gms.internal.zzaaj.onConnected(Unknown Source) 
                     at com.google.android.gms.internal.zzaan.onConnected(Unknown Source) 
                     at com.google.android.gms.internal.zzzy.onConnected(Unknown Source) 
                     at com.google.android.gms.common.internal.zzl$1.onConnected(Unknown Source) 
                     at com.google.android.gms.common.internal.zzf$zzj.zzwZ(Unknown Source) 
                     at com.google.android.gms.common.internal.zzf$zza.zzc(Unknown Source) 
                     at com.google.android.gms.common.internal.zzf$zza.zzu(Unknown Source) 
                     at com.google.android.gms.common.internal.zzf$zze.zzxa(Unknown Source) 
                     at com.google.android.gms.common.internal.zzf$zzd.handleMessage(Unknown Source) 
                     at android.os.Handler.dispatchMessage(Handler.java:102) 
                     at android.os.Looper.loop(Looper.java:148) 
                     at android.app.ActivityThread.main(ActivityThread.java:5417) 
                     at java.lang.reflect.Method.invoke(Native Method) 
                     at com.android.internal.os.ZygoteInit$MethodAndArgsCaller.run(ZygoteInit.java:726) 
                     at com.android.internal.os.ZygoteInit.main(ZygoteInit.java:616) 

我一直在嘗試不同的東西,並試圖瞭解究竟是什麼原因造成我的問題,以及如何得到這個工作,但無濟於事。如果這不是我想要做的事情的正確方法,我該怎麼做呢?

我試着在這個網站上看到類似的探測問題的問題,但沒有一個人似乎對我有答案。

感謝您的幫助

回答

1

我所做的就是創建另一個XML只加載地圖佈局XML

<fragment xmlns:android="http://schemas.android.com/apk/res/android" 
xmlns:map="http://schemas.android.com/apk/res-auto" 
xmlns:tools="http://schemas.android.com/tools" 
android:id="@+id/map" 
android:name="com.google.android.gms.maps.SupportMapFragment" 
android:layout_width="match_parent" 
android:layout_height="match_parent" 
tools:context="com.example.user.myApp.Fragment.MapFragment" /> 

後膨脹,該地圖在我的片段

SupportMapFragment mapFragment; 

if (mapFragment == null) { 
     mapFragment = ((SupportMapFragment) getChildFragmentManager().findFragmentById(R.id.map)); 


     // Check if we were successful in obtaining the map. 
     if (mapFragment != null) { 
      mapFragment.getMapAsync(this); 

      if (mapFragment == null) { 

       Toast.makeText(getContext(),"Sorry! unable to create maps", Toast.LENGTH_SHORT).show(); 
      } 
     } 
    } 

連接您的api on start

@Override 
public void onStart() { 
    super.onStart(); 
    googleApiClient.connect(); 
} 

,並按照你的onCreateView線intializing的mapFragment

googleApiClient = new GoogleApiClient.Builder(getActivity()) 
      .addApi(LocationServices.API) 
      .addApi(Places.GEO_DATA_API) 
      .addApi(Places.PLACE_DETECTION_API) 
      .build(); 

告訴我,如果你發現任何問題

+0

我會盡力並在我有更多時間時進行測試。我沒有忘記標記答案,因爲我沒有在活動中實現OnMapReadyCallback,所以我只是一直專注於我的活動< – Greener

0

添加這段代碼中的onCreate您的活動後

FragmentManager myFragmentManager = getSupportFragmentManager(); 
    SupportMapFragment mapFragment = (SupportMapFragment) myFragmentManager 
      .findFragmentById(R.id.map); 
    mapFragment.getMapAsync(this); 
+0

。我在片段中實現了,並希望我可以將所有必需的代碼放入片段中,這樣我就不需要將它放入任何我想要放入地圖的活動中。 – Greener

相關問題