3

我正在尝试构建一个使用 GoogleClientApi 和 LocationServices 请求当前位置的应用程序,但即使我启用了 WiFi、Mobile Data 和 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 有什么不同吗?

4

1 回答 1

4

您需要调用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)));

            }
        });

    }
}
于 2015-09-14T15:05:36.670 回答