getLastLocation()在GoogleApiClient中始终为空 [英] getLastLocation() always null in GoogleApiClient

查看:652
本文介绍了getLastLocation()在GoogleApiClient中始终为空的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我试图建立一个使用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实现GoogleApiClient.ConnectionCallbacks,GoogleApiClient.OnConnectionFailedListener,com.google.android.gms.location.LocationListener 
{

public static FragmentManager fragmentManager;
按钮goButton;
Spinner旋转器;
SupportMapFragment mapFragment;
GoogleMap地图;
列表<电台> stationsList;
ArrayList< String> stationsAddresses;

private static View view;
ArrayList< MarkerOptions>标记;
GoogleApiClient mGoogleApiClient;
LocationServices locationServices;
位置位置;
private static String TAG =FIND_STATION;

上下文环境;
LocationRequest mLocationRequest;
LocationListener locationListener;
@Override
public View onCreateView(LayoutInflater inflater,@Nullable ViewGroup容器,@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);
}
尝试{
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 =(微调)view.findViewById(R.id.spinner);
stationsList = Stations.listAll(Stations.class);
markers = new ArrayList<>(); (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);




});


尝试{
initialize();
} catch(Exception e){
e.printStackTrace();
}


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

/ * thread = new Thread(new MyThread());
thread.start(); * /
返回视图;


private void initialize(){
if(map == null){
Fragment fragment = getChildFragmentManager()。findFragmentById(R.id.map) ;
mapFragment =(SupportMapFragment)片段;
map = mapFragment.getMap();
for(int i = 0; i< markers.size(); i ++){
map.addMarker(markers.get(i));
}
//检查映射是否成功创建
if(map == null){
Toast.makeText(super.getActivity(),
)抱歉!无法创建地图,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();


$ b}

@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(更新);
}
Log.d(TAG,connected);



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

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



@Override
public void onLocationChanged(位置位置){`在此输入代码`
Log.d(TAG,location.toString( ));
this.location = location;
if(location!= null){
CameraUpdate update = CameraUpdateFactory.newLatLngZoom(new LatLng(location.getLatitude(),location.getLongitude()),3f);
map.animateCamera(更新);
Log.d(标签,相机更新到新位置);
goButton.setVisibility(View.VISIBLE);




$ b @Override
public void onStart(){
super.onStart();
mGoogleApiClient.connect();
Log.d(TAG,connect()called);

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

}

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



使用地图,我尝试启用我的位置,



更新1


$在右上角有按钮,它会返回位置并为相机添加动画。 b $ b

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

Log.d(TAG,connected);}

然后用一个我调用lastKnownLocation()的按钮,因为onLocationChanged()没有被调用,仍然返回的位置是空的



更新2:

完全相同的代码在Android 5.0.1上运行,并且完美地运行在$ 2.3
上,所有其他设备在android 2.3.7,4.0.1上都没有工作,

任何关于Android API关于位置的差异的想法?

解决方案您需要调用 requestLocationUpdates()来注册侦听器,并调用 onLocationChanged()



请务必尽快取消注册听众,以避免电量过多。

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



确保实际获取位置的唯一方法是请求这是通过调用requestLocationUpdates()来完成的。



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

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

private GoogleMap地图;
private LocationRequest mLocationRequest;
私有GoogleApiClient mGoogleApiClient;
私人位置mLastLocation;
私人标记标记;

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


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


$ b保护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();

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

@Override
public void onLocationChanged(Location location){
mLastLocation = location;

//删除以前的当前位置标记
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));

}

}

还有一件事,如果您的地图位于片段中,则不需要嵌套的SupportMapFragment。你可以让你的片段扩展SupportMapFragment。这消除了嵌套Fragment的需要,甚至不需要膨胀任何布局xml,这里是一个简单的例子:

  public class MapTabFragment extends SupportMapFragment 
implements OnMapReadyCallback {

private GoogleMap mMap;
私人标记标记;

$ b public MapResponse(){


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

setUpMapIfNeeded();

$ b $ 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(){
$ b @Override
public void onMapClick(LatLng point){

//删除先前放置的标记
if(marker!= null){
marker.remove();
}

//将标记放置在用户只需点击
marker = mMap.addMarker(new MarkerOptions()。position(point).title(Marker)
.icon(BitmapDescriptorFactory.defaultMarker(BitmapDescriptorFactory.HUE_MAGENTA)));

}
});

}
}


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

the permissions from the 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

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

updated the onConnected() method and made it request locations updates,

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

UPDATE 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,

Any idea about what difference in the Android APIs regarding the location?

解决方案

You need to call requestLocationUpdates() in order to register the listener and have onLocationChanged() invoked.

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

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. You can just have your Fragment extend 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:

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

            }
        });

    }
}

这篇关于getLastLocation()在GoogleApiClient中始终为空的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆