GoogleApiClient 中的 getLastLocation() 始终为空

Posted

技术标签:

【中文标题】GoogleApiClient 中的 getLastLocation() 始终为空【英文标题】:getLastLocation() always null in GoogleApiClient 【发布时间】:2015-12-10 15:13:07 【问题描述】:

我正在尝试构建一个使用 GoogleClientApi 和 LocationServices 请求当前位置的应用程序,但即使我启用了 WiFi、移动数据和 GPS,位置始终为空,并在多个设备上进行了相同的测试

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" />

活动:

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


奇怪的是 onConnect() 方法被调用,但之后 Location 始终为 null 并且永远不会调用 onLocationChanged()

使用地图,我尝试启用我的位置,当您在右上角有按钮时,它会返回位置并为相机设置动画。

更新 1

更新了 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");

然后我用一个按钮调用 lastKnownLocation() 因为 onLocationChanged() 仍然没有被调用,并且返回的 Location 仍然是 null

更新 2:

同样的代码在 Android 5.0.1 上运行并且完美运行 所有其他设备都在 android 2.3.7,4.0.1 上,它们都没有工作,

您知道 Android API 在位置方面有何不同吗?

【问题讨论】:

嗨,您没有在 onConnect() 中请求位置。 我做了,但没用 有什么奇怪的,requestLocationUpdates() 的方法被调用了,但是 onLocationChanged() 从来没有被调用过 你找到这个问题的好答案了吗?我也有类似的问题...***.com/q/41216063/6144372 【参考方案1】:

您需要调用requestLocationUpdates() 来注册监听器并调用onLocationChanged()

请务必尽快取消注册监听器以避免过度消耗电池电量。

另请注意,getLastLocation() 方法可以并且将返回 null。主要问题是它不会提示操作系统请求新的位置锁定,而只是检查是否有来自其他应用程序的位置请求的最后一个已知位置。如果最近没有其他应用发出位置请求,那么您会收到一个空位置返回给您。

保证您实际获得位置的唯一方法是请求一个位置,这是通过调用 requestLocationUpdates() 来完成的。

这是一个工作示例供参考:

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

    


还有一点,如果你的地图是在 Fragment 中,就不需要嵌套 SupportMapFragment。您可以让您的 Fragment 扩展 SupportMapFragment。这消除了嵌套 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)));

            
        );

    

【讨论】:

嘿.. 我按照你的回答,但我的问题没有解决。请查看:***.com/q/41216063/6144372

以上是关于GoogleApiClient 中的 getLastLocation() 始终为空的主要内容,如果未能解决你的问题,请参考以下文章

GoogleApiClient:多线程Android应用程序中的“结果已被使用”

没有 GET_ACCOUNTS 权限的 Android 中的 Google Cloud Endpoints + GoogleApiClient

Android - GoogleApiClient 实例在 IntentService 中的 .connect() 和 onConnected() 之间丢失

如何将 GoogleApiClient 位置服务与 Google Api 一起使用?

谷歌排行榜提交分数错误:必须连接GoogleApiClient

GoogleApiClient 在调用 onConnected 函数后抛出“GoogleApiClient 尚未连接”