简体   繁体   English

getAastLocation()在GoogleApiClient中始终为null

[英]getLastLocation() always null in GoogleApiClient

Am trying to build an application that requests the current location using the GoogleClientApi and LocationServices, but the Location is always null even that I enabled the WiFi,Mobile Data and GPS , tested it on several devices all the same 我正在尝试构建一个使用GoogleClientApi和LocationServices请求当前位置的应用程序,但即使我启用了WiFi,移动数据和GPS,在所有相同的设备上对其进行了测试,该位置始终为空

the permissions from the manifest.xml : manifest.xml的权限:

<uses-permission android:name="com.google.android.providers.gsf.permission.READ_GSERVICES" />
<uses-permission android:name="android.permission.ACCESS_COARSE_LOCATION" />
<uses-permission android:name="android.permission.ACCESS_FINE_LOCATION" />

Activity: 活动:

public class FindStation extends Fragment implements GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,com.google.android.gms.location.LocationListener
{

    public static FragmentManager fragmentManager;
    Button goButton;
    Spinner spinner;
    SupportMapFragment mapFragment;
    GoogleMap map;
    List<Stations> stationsList;
    ArrayList<String> stationsAddresses;

    private static View view;
    ArrayList<MarkerOptions> markers;
    GoogleApiClient mGoogleApiClient;
    LocationServices locationServices;
    Location location;
    private static String TAG="FIND_STATION";

    Context context;
    LocationRequest mLocationRequest;
    LocationListener locationListener;
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        context= getActivity();
        locationListener=this;
        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(10000);
        mLocationRequest.setFastestInterval(5000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        mLocationRequest.setSmallestDisplacement(10);
        /*mGoogleApiClient = new GoogleApiClient.Builder(getActivity())
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();*/

        buildGoogleApiClient();




        if (view != null) {
            ViewGroup parent = (ViewGroup) view.getParent();
            if (parent != null)
                parent.removeView(view);
        }
        try {
            view = inflater.inflate(R.layout.activity_find_station, container, false);
        } catch (InflateException e) {

        }

              inflater.inflate(R.layout.activity_find_station,container,false);
        stationsAddresses = new ArrayList<>();
        goButton= (Button) view.findViewById(R.id.button);
        //goButton.setVisibility(View.INVISIBLE);
        spinner= (Spinner) view.findViewById(R.id.spinner);
        stationsList = Stations.listAll(Stations.class);
        markers = new ArrayList<>();
        for (int i = 0; i <stationsList.size() ; i++) {
            stationsAddresses.add(stationsList.get(i).getStationLocation());
            markers.add(new MarkerOptions().position(new LatLng(stationsList.get(i).getStationLat(), stationsList.get(i).getStationLong())).title(stationsList.get(i).getStationName()));
        }
        goButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                //location= LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);



            }
        });


        try {
            initialize();
        } catch (Exception e) {
            e.printStackTrace();
        }


        try {
           // map.setMyLocationEnabled(true);
        } catch (Exception e) {
            e.printStackTrace();
        }

        /*thread = new Thread(new MyThread());
        thread.start();*/
        return view;
    }

    private void initialize() {
        if (map==null) {
            Fragment fragment= getChildFragmentManager().findFragmentById(R.id.map);
            mapFragment= (SupportMapFragment) fragment;
            map=mapFragment.getMap();
            for (int i = 0; i <markers.size() ; i++) {
              map.addMarker(markers.get(i));
            }
            // check if map is created successfully or not
            if (map==null) {
                Toast.makeText(super.getActivity(),
                        "Sorry! unable to create maps", Toast.LENGTH_SHORT)
                        .show();
            }
        }


    }

    public void onDestroyView() {
        super.onDestroyView();


        android.support.v4.app.FragmentManager fm = getActivity().getSupportFragmentManager();
        SupportMapFragment fragment = (SupportMapFragment) fm.findFragmentById(R.id.map);

        if (fragment!=null) {
                android.support.v4.app.FragmentTransaction ft = fm.beginTransaction();
                ft.remove(fragment);
                ft.commit();

        }

    }

    @Override
    public void onConnected(Bundle bundle) {
        location= LocationServices.FusedLocationApi.getLastLocation(mGoogleApiClient);
        if (location!=null){
            Log.d(TAG,location.toString());
        CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(),location.getLongitude()),3f);
        map.animateCamera(update);
        }
        Log.d(TAG,"connected");

    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d(TAG,"connection suspended "+String.valueOf(i));
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
        Log.d(TAG,"connection failed");
    }


    @Override
    public void onLocationChanged(Location location) {`enter code here`
        Log.d(TAG,location.toString());
        this.location=location;
        if (location!=null) {
            CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(), location.getLongitude()), 3f);
            map.animateCamera(update);
            Log.d(TAG, "camera updated to new position");
            goButton.setVisibility(View.VISIBLE);
        }
    }



    @Override
    public void onStart() {
        super.onStart();
        mGoogleApiClient.connect();
        Log.d(TAG,"connect() was called");
    }
    protected synchronized void buildGoogleApiClient() {
        mGoogleApiClient = new GoogleApiClient.Builder(context)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .addApi(LocationServices.API)
                .build();
    }

}

the strange thing is that the onConnect() method is called but after that the Location is always null and onLocationChanged() is never called 奇怪的是,onConnect()方法被调用,但之后,Location始终为null,并且永远不会调用onLocationChanged()

using the maps, i tried the enabling my location and it works when you have the button on the right top corner it returns the location and animates the camera. 使用地图,我尝试启用我的位置,当你有右上角的按钮它返回位置并动画相机时,它工作。

UPDATE 1 更新1

updated the onConnected() method and made it request locations updates, 更新了onConnected()方法并使其请求位置更新,

public void onConnected(Bundle bundle) {
    LocationServices.FusedLocationApi.requestLocationUpdates(mGoogleApiClient, mLocationRequest, locationListener);

    if (location!=null){
        Log.d(TAG,location.toString());
    CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(),location.getLongitude()),3f);
    map.animateCamera(update);
    }
    Log.d(TAG,"connected");}

then with a button i call lastKnownLocation() since the onLocationChanged() is not called still, and still the returned Location is null 然后用一个按钮我调用lastKnownLocation(),因为onLocationChanged()没有被调用,仍然返回的Location是null

UPDATE 2 : 更新2:

The very same code worked on Android 5.0.1 and worked perfectly all the other devices was on android 2.3.7,4.0.1 none of them worked, 完全相同的代码适用于Android 5.0.1并完美地工作所有其他设备在Android 2.3.7,4.0.1上没有一个工作,

Any idea about what difference in the Android APIs regarding the location? 有关Android API的位置有何不同之处?

You need to call requestLocationUpdates() in order to register the listener and have onLocationChanged() invoked. 您需要调用requestLocationUpdates()以注册侦听器并调用onLocationChanged()

Be sure to un-register the listener as soon as possible to avoid excessive battery drain. 请务必尽快取消注册听众,以免电池耗尽过多。

Also note that the getLastLocation() method can and will return null. 另请注意,getLastLocation()方法可以并且将返回null。 The main problem is that it doesn't prompt a request to the OS for a new location lock, instead it just checks if there was a last known location from some other app's location request. 主要问题是它不会向操作系统提示请求新的位置锁定,而只是检查是否有来自其他应用程序位置请求的最后一个已知位置。 If no other app had recently made a location request, then you get a null location returned to you. 如果最近没有其他应用程序发出了位置请求,那么您将获得一个返回给您的空位置。

The only way to guarantee that you actually get a location is to request one, and this is done with a call to requestLocationUpdates(). 保证实际获得位置的唯一方法是请求一个,这是通过调用requestLocationUpdates()来完成的。

Here is a working example for reference: 以下是一个可供参考的工作示例:

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

    private GoogleMap map;
    private LocationRequest mLocationRequest;
    private GoogleApiClient mGoogleApiClient;
    private Location mLastLocation;
    private Marker marker;

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

    @Override
    protected void onResume() {
        super.onResume();

        buildGoogleApiClient();
        mGoogleApiClient.connect();

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

            mapFragment.getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap retMap) {

        map = retMap;

        setUpMap();

    }

    public void setUpMap(){

        map.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        map.setMyLocationEnabled(true);
    }

    @Override
    protected void onPause(){
        super.onPause();
        if (mGoogleApiClient != null) {
            LocationServices.FusedLocationApi.removeLocationUpdates(mGoogleApiClient, this);
        }
    }

    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();

        mLocationRequest = new LocationRequest();
        mLocationRequest.setInterval(1000);
        mLocationRequest.setFastestInterval(1000);
        mLocationRequest.setPriority(LocationRequest.PRIORITY_BALANCED_POWER_ACCURACY);

        //mLocationRequest.setSmallestDisplacement(0.1F);

        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) {
        mLastLocation = location;

        //remove previous current location Marker
        if (marker != null){
            marker.remove();
        }

        double dLatitude = mLastLocation.getLatitude();
        double dLongitude = mLastLocation.getLongitude();
        marker = map.addMarker(new MarkerOptions().position(new LatLng(dLatitude, dLongitude))
                .title("My Location").icon(BitmapDescriptorFactory
                        .defaultMarker(BitmapDescriptorFactory.HUE_RED)));
        map.moveCamera(CameraUpdateFactory.newLatLngZoom(new LatLng(dLatitude, dLongitude), 8));

    }

}

One more thing, if your map is in a Fragment, there is no need to have a nested SupportMapFragment. 还有一件事,如果您的地图位于片段中,则无需使用嵌套的SupportMapFragment。 You can just have your Fragment extend SupportMapFragment. 你可以让你的Fragment扩展SupportMapFragment。 This removes the need of having a nested Fragment, and you don't even need to inflate any layout xml, here is a simple example: 这样就无需使用嵌套的Fragment,甚至不需要为任何布局xml充气,这里有一个简单的例子:

public class MapTabFragment extends SupportMapFragment 
                                    implements OnMapReadyCallback {

    private GoogleMap mMap;
    private Marker marker;


    public MapTabFragment() {
    }

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

        setUpMapIfNeeded();
    }

    private void setUpMapIfNeeded() {

        if (mMap == null) {

            getMapAsync(this);
        }
    }

    @Override
    public void onMapReady(GoogleMap googleMap) {

        mMap = googleMap;
        setUpMap();
    }

    private void setUpMap() {

        mMap.setMyLocationEnabled(true);
        mMap.setMapType(GoogleMap.MAP_TYPE_HYBRID);
        mMap.getUiSettings().setMapToolbarEnabled(false);


        mMap.setOnMapClickListener(new GoogleMap.OnMapClickListener() {

            @Override
            public void onMapClick(LatLng point) {

                //remove previously placed Marker
                if (marker != null) {
                    marker.remove();
                }

                //place marker where user just clicked
                marker = mMap.addMarker(new MarkerOptions().position(point).title("Marker")
                        .icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));

            }
        });

    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM