2015-11-16 2 views
18

Я хочу показать свое местоположение на карте и увеличить его. Я хочу использовать GoolgeAPIClient. Отображается карта, и указатель создается, но местоположение так неправильно. Я чувствую, что onMapReady выполняется сначала еще до того, как вызывается метод onConnected объекта GoogleAPIClient. Пожалуйста, помогите, это мой код.Как показать свое текущее местоположение в Google Map Android с помощью Google API-клиента

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

Просто подключите его сразу же после его создания. Затем в вас onStart() просто проверьте, не подключено ли оно до его подключения. – Xjasz

+0

Я полностью смущен, пройдя десятки примеров каждой из разных реализаций. Если вы можете показать мне, как подключить его со сниппетом, применимым для моего кода, я буду очень благодарен. – TwoThumbSticks

ответ

48

Для ориентации Апи-23 и выше:

Смотрите ответ here.

Для ориентации Апи-22 и ниже:

Вот полный код активности, который делает то, что вам нужно, модифицированную версию my other answer here. Он регистрирует приемник местоположения при загрузке Activity, а затем, когда происходит каждое событие с изменением местоположения, он добавляет маркер, а также анимирует карту в центр в текущем местоположении.

Ключ здесь - дождаться, когда произошел обратный вызов onMapReady(), прежде чем запрашивать обновления местоположения.

Вот полный код активность:

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

Если когда-либо я попытаюсь добавить несколько маркеров на этой карте, будет отображаться местоположение onChange стереть другие маркеры? Где самое безопасное место для размещения моих других маркеров – TwoThumbSticks

+0

@TwoThumbSticks Я только что обновил ответ. С обновленным кодом он удалит/повторно добавит текущий маркер местоположения и не повлияет на другие маркеры на карте. См. Новую переменную-член 'currLocationMarker' и вызов' currLocationMarker.remove() 'вместо вызова' mGoogleMap.clear() '. –

+0

Я получаю эту ошибку 11-17 04: 09: 19.901 23229-23229 /? E/NetworkScheduler.SchedulerReceiver: неверное приложение параметра 11-17 04: 09: 19.901 23229-23229 /? E/NetworkScheduler.SchedulerReceiver: Недопустимое имя пакета. Возможно, вы не включили PendingIntent в дополнительные функции? – TwoThumbSticks

1

ли эта работа

Следуйте по этой ссылке: 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

Я заменил свой BuildGoogleApiClient и onStart на ваш код, но он по-прежнему указывает на Нигерию :( – TwoThumbSticks

+0

@TwoThumbSticks - вам нужно просто анимировать карту тогда. Вы вернетесь прямо вправо? – Xjasz

+0

Место неправильное, потому что маркер находится на Нигерии Im из Азии :( Его так просто использовать map.getMyLocation(), чтобы получить мое правильное местоположение, но проблема в том, что он не будет масштабироваться, потому что вам все равно понадобится длинное значение lat – TwoThumbSticks