2015-11-16 22 views
18

Voglio mostrare la mia posizione su una mappa e ingrandirla. Voglio usare GoolgeAPIClient. La mappa esegue il rendering e il puntatore viene creato ma la posizione è sbagliata. Sento che onMapReady viene eseguito prima ancora che venga chiamato il metodo onConnected di GoogleAPIClient. Si prega di aiutare questo è il mio codice.Come mostrare la mia posizione corrente in Google Maps Android utilizzando il client API google

import android.location.Location; 
import android.support.v4.app.FragmentActivity; 
import android.os.Bundle; 
import android.util.Log; 
import android.widget.TextView; 
import android.widget.Toast; 

import com.google.android.gms.common.ConnectionResult; 
import com.google.android.gms.common.api.GoogleApiClient; 
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.LatLngBounds; 
import com.google.android.gms.maps.model.MarkerOptions; 


public class MapsActivity extends FragmentActivity implements OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener { 
    protected static final String TAG = "MainActivity"; 

    /** 
    * Provides the entry point to Google Play services. 
    */ 
    protected GoogleApiClient mGoogleApiClient; 

    /** 
    * Represents a geographical location. 
    */ 
    protected Location mLastLocation; 

    protected String mLatitudeLabel; 
    protected String mLongitudeLabel; 
    protected TextView mLatitudeText; 
    protected TextView mLongitudeText; 
    protected double dLat; 
    protected double dLong; 



    private GoogleMap mMap; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_maps); 

     buildGoogleApiClient(); 
     // Obtain the SupportMapFragment and get notified when the map is ready to be used. 
     SupportMapFragment mapFragment = (SupportMapFragment) getSupportFragmentManager() 
       .findFragmentById(R.id.map); 
     mapFragment.getMapAsync(this); 
    } 


    /** 
    * Manipulates the map once available. 
    * This callback is triggered when the map is ready to be used. 
    * This is where we can add markers or lines, add listeners or move the camera. In this case, 
    * we just add a marker near Sydney, Australia. 
    * If Google Play services is not installed on the device, the user will be prompted to install 
    * it inside the SupportMapFragment. This method will only be triggered once the user has 
    * installed Google Play services and returned to the app. 
    */ 
    @Override 
    public void onMapReady(GoogleMap googleMap) { 
     mMap = googleMap; 

     LatLng myLocation = new LatLng(dLat, dLong); 
     mMap.addMarker(new MarkerOptions().position(myLocation).title("You are here")); 
     mMap.moveCamera(CameraUpdateFactory.newLatLng(myLocation)); 
    } 

    /** 
    * BEGIN 
    */ 
    /** 
    * Builds a GoogleApiClient. Uses the addApi() method to request the LocationServices API. 
    */ 
    protected synchronized void buildGoogleApiClient() { 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 
    } 

    @Override 
    protected void onStart() { 
     super.onStart(); 
     mGoogleApiClient.connect(); 
    } 

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

    /** 
    * Runs when a GoogleApiClient object successfully connects. 
    */ 
    @Override 
    public void onConnected(Bundle connectionHint) { 
     // Provides a simple way of getting a device's location and is well suited for 
     // applications that do not require a fine-grained location and that do not need location 
     // updates. Gets the best and most recent location currently available, which may be null 
     // in rare cases when a location is not available. 
     mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
     if (mLastLocation != null) { 

      dLat = mLastLocation.getLatitude(); 


      dLong = mLastLocation.getLongitude(); 
     } else { 
      Toast.makeText(this, R.string.no_location_detected, Toast.LENGTH_LONG).show(); 
     } 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult result) { 
     // Refer to the javadoc for ConnectionResult to see what error codes might be returned in 
     // onConnectionFailed. 
     Log.i(TAG, "Connection failed: ConnectionResult.getErrorCode() = " + result.getErrorCode()); 
    } 


    @Override 
    public void onConnectionSuspended(int cause) { 
     // The connection to Google Play services was lost for some reason. We call connect() to 
     // attempt to re-establish the connection. 
     Log.i(TAG, "Connection suspended"); 
     mGoogleApiClient.connect(); 
    } 
} 



11-17 01:30:39.482 30546-30546/com.gioinout.giohanda E/dalvikvm: Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.common.GooglePlayServicesUtil.zzb 
11-17 01:30:39.538 30546-30569/com.gioinout.giohanda E/GMPM: getGoogleAppId failed with status: 10 
11-17 01:30:39.539 30546-30569/com.gioinout.giohanda E/GMPM: Uploading is not possible. App measurement disabled 
11-17 01:30:39.579 30546-30546/com.gioinout.giohanda E/dalvikvm: Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.common.ma.a 
11-17 01:30:39.684 30546-30546/com.gioinout.giohanda E/dalvikvm: Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.common.lt.a 
11-17 01:30:40.226 30546-30577/com.gioinout.giohanda E/NativeCrypto: ssl=0x5d26beb8 cert_verify_callback x509_store_ctx=0x60700ab0 arg=0x0 
11-17 01:30:40.227 30546-30577/com.gioinout.giohanda E/NativeCrypto: ssl=0x5d26beb8 cert_verify_callback calling verifyCertificateChain authMethod=ECDHE_ECDSA 
11-17 01:30:42.982 30546-30579/com.gioinout.giohanda E/NativeCrypto: ssl=0x6151f770 cert_verify_callback x509_store_ctx=0x60910ab0 arg=0x0 
11-17 01:30:42.983 30546-30579/com.gioinout.giohanda E/NativeCrypto: ssl=0x6151f770 cert_verify_callback calling verifyCertificateChain authMethod=ECDHE_ECDSA 
+0

Basta collegarlo subito dopo lo costruisci. Quindi in te onStart() controlla solo se è connesso prima di collegarlo. – Xjasz

+0

Sono totalmente confuso dopo aver attraversato dozzine di esempi ciascuno di diverse implementazioni. Se puoi mostrarmi come collegarlo con uno snippet applicabile al mio codice, lo apprezzerò molto. – TwoThumbSticks

risposta

48

per il targeting api-23 e superiori:

vedere la risposta here.

per il targeting api-22 e inferiore:

Ecco il codice completo di attività che fa quello che avete bisogno, una versione modificata di my other answer here. Registra un listener di posizione quando viene caricata l'attività, quindi quando si verifica un evento di ogni posizione, aggiungerà un indicatore e animerà anche la mappa per centrare la posizione corrente.

La chiave qui è attendere fino a quando si è verificato il callback onMapReady() prima di richiedere gli aggiornamenti di posizione.

Ecco il codice di piena attività:

public class MainActivity extends AppCompatActivity implements 
     OnMapReadyCallback, GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener { 

    LocationRequest mLocationRequest; 
    GoogleApiClient mGoogleApiClient; 

    LatLng latLng; 
    GoogleMap mGoogleMap; 
    SupportMapFragment mFragment; 
    Marker currLocationMarker; 

    @Override 
    protected void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.activity_main); 

     mFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.map); 
     mFragment.getMapAsync(this); 
    } 

    @Override 
    public void onMapReady(GoogleMap gMap) { 
     mGoogleMap = gMap; 
     mGoogleMap.setMyLocationEnabled(true); 

     buildGoogleApiClient(); 

     mGoogleApiClient.connect(); 

    } 

    protected synchronized void buildGoogleApiClient() { 
     Toast.makeText(this,"buildGoogleApiClient",Toast.LENGTH_SHORT).show(); 
     mGoogleApiClient = new GoogleApiClient.Builder(this) 
       .addConnectionCallbacks(this) 
       .addOnConnectionFailedListener(this) 
       .addApi(LocationServices.API) 
       .build(); 
    } 

    @Override 
    public void onConnected(Bundle bundle) { 
     Toast.makeText(this,"onConnected",Toast.LENGTH_SHORT).show(); 
     Location mLastLocation = LocationServices.FusedLocationApi.getLastLocation(
       mGoogleApiClient); 
     if (mLastLocation != null) { 
      //place marker at current position 
      //mGoogleMap.clear(); 
      latLng = new LatLng(mLastLocation.getLatitude(), mLastLocation.getLongitude()); 
      MarkerOptions markerOptions = new MarkerOptions(); 
      markerOptions.position(latLng); 
      markerOptions.title("Current Position"); 
      markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)); 
      currLocationMarker = mGoogleMap.addMarker(markerOptions); 
     } 

     mLocationRequest = new LocationRequest(); 
     mLocationRequest.setInterval(5000); //5 seconds 
     mLocationRequest.setFastestInterval(3000); //3 seconds 
     mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY); 
     //mLocationRequest.setSmallestDisplacement(0.1F); //1/10 meter 

     LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, this); 



    } 

    @Override 
    public void onConnectionSuspended(int i) { 
     Toast.makeText(this,"onConnectionSuspended",Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public void onConnectionFailed(ConnectionResult connectionResult) { 
     Toast.makeText(this,"onConnectionFailed",Toast.LENGTH_SHORT).show(); 
    } 

    @Override 
    public void onLocationChanged(Location location) { 

     //place marker at current position 
     //mGoogleMap.clear(); 
     if (currLocationMarker != null) { 
      currLocationMarker.remove(); 
     } 
     latLng = new LatLng(location.getLatitude(), location.getLongitude()); 
     MarkerOptions markerOptions = new MarkerOptions(); 
     markerOptions.position(latLng); 
     markerOptions.title("Current Position"); 
     markerOptions.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)); 
     currLocationMarker = mGoogleMap.addMarker(markerOptions); 

     Toast.makeText(this,"Location Changed",Toast.LENGTH_SHORT).show(); 

     //zoom to current position: 
     mGoogleMap.moveCamera(CameraUpdateFactory.newLatLngZoom(latLng,11)); 

     //If you only need one location, unregister the listener 
     //LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this); 

    } 

} 
+0

Se mai provo ad aggiungere più marcatori su questa mappa, la posizione di onChange cancellare gli altri marcatori? Dove è il posto più sicuro dove mettere gli altri miei marcatori – TwoThumbSticks

+0

@TwoThumbSticks Ho appena aggiornato la risposta. Con il codice aggiornato, rimuoverà/aggiungerà nuovamente l'indicatore di posizione corrente e non influenzerà nessun altro Indicatore sulla mappa. Vedi la nuova variabile membro 'currLocationMarker' e la chiamata a' currLocationMarker.remove() 'invece della chiamata a' mGoogleMap.clear() '. –

+0

Ricevo ora questo errore 11-17 04: 09: 19.901 23229-23229 /? E/NetworkScheduler.SchedulerReceiver: App parametri non valida 11-17 04: 09: 19.901 23229-23229 /? E/NetworkScheduler.SchedulerReceiver: nome pacchetto non valido: forse non hai incluso un PendingIntent negli extra? – TwoThumbSticks

1

sarebbe questo lavoro

Seguite questo link: Getting error: Could not find class 'android.app.AppOpsManager', referenced from method com.google.android.gms.common.GooglePlayServicesUtil.zza

protected synchronized void buildGoogleApiClient() { 
    mGoogleApiClient = new GoogleApiClient.Builder(this) 
     .addConnectionCallbacks(this) 
     .addOnConnectionFailedListener(this) 
     .addApi(LocationServices.API) 
     .build(); 
    mGoogleApiClient.connect(); 
} 

@Override 
protected void onStart() { 
    super.onStart(); 
     if (mGoogleApiClient!= null && !mGoogleApiClient.isConnected()) 
      mGoogleApiClient.connect(); 
} 

@Override 
public void onConnected(Bundle connectionHint) { 
    mLastLocation = LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient); 
    if (mLastLocation != null) { 
     dLat = mLastLocation.getLatitude(); 
     dLong = mLastLocation.getLongitude(); 
     //Does this log? 
     Log.d(getClass().getSimpleName(), String.valueOf(dLat) + ", " + String.valueOf(dLong)); 
    } else { 
     Toast.makeText(this, R.string.no_location_detected, Toast.LENGTH_LONG).show(); 
    } 
} 
+0

Ho sostituito il mio BuildGoogleApiClient e onStart con il tuo codice, ma punta ancora alla Nigeria :( – TwoThumbSticks

+0

@TwoThumbSticks: devi solo animare la mappa, quindi riprendi una posizione giusta? – Xjasz

+0

La posizione è sbagliata perché il marcatore è in Nigeria dall'Asia :( E 'così semplice usare map.getMyLocation() per ottenere la mia posizione corretta ma il problema è che non si ingrandirà perché saranno ancora necessari i valori lat a lat – TwoThumbSticks