使用 FusedlocationProviderClient Api 在 Android 中进行实时位置跟踪的问题

Posted

技术标签:

【中文标题】使用 FusedlocationProviderClient Api 在 Android 中进行实时位置跟踪的问题【英文标题】:Problem with real time Location tracking in Android using FusedlocationProviderClient Api 【发布时间】:2020-04-24 04:06:18 【问题描述】:

我已经在 android Studio 中的谷歌地图活动片段上尝试了下面给出的代码,我什至已经在手机上编译并运行了它,但我的位置没有显示出来。请帮我找出代码中的错误。

    package com.example.ambulance;

    import ...

public class MapsActivity extends AppCompatActivity implements OnMapReadyCallback 

private GoogleMap googleMap;
private FusedLocationProviderClient fusedLocationProviderClient;
private int REQUEST_ACCESS = 5445;
private boolean firstTimeFlag = true;
private Marker currentLocationMarker;
private static Location currentLocation;

@Override
protected void onCreate(Bundle savedInstanceState) 
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_maps);
    SupportMapFragment supportMapFragment = (SupportMapFragment) getSupportFragmentManager().findFragmentById(R.id.google_map);
    supportMapFragment.getMapAsync(this);


@Override
public void onMapReady(GoogleMap googleMap)

    this.googleMap = googleMap;


@Override
protected void onResume()

    super.onResume();
    if(isGooglePlayServicesAvailable())
    
        fusedLocationProviderClient = LocationServices.getFusedLocationProviderClient(this);
        startLocationUpdates();
    


private boolean isGooglePlayServicesAvailable()

    GoogleApiAvailability googleApiAvailability = GoogleApiAvailability.getInstance();

    int status = googleApiAvailability.isGooglePlayServicesAvailable(this);

    if(ConnectionResult.SUCCESS == status)
        return true;
    else
    
        if(googleApiAvailability.isUserResolvableError(status))
            Toast.makeText(this, "Please Install Google Play Services to Use this Application", Toast.LENGTH_LONG).show();
    
    return false;


private void startLocationUpdates()

    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(300);
    locationRequest.setSmallestDisplacement(1);

    if(Build.VERSION.SDK_INT >= Build.VERSION_CODES.M)
    
        if(ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
            ActivityCompat.requestPermissions(MapsActivity.this, new String[] Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_ACCESS);
        return;
    
    fusedLocationProviderClient.requestLocationUpdates(locationRequest, mLocationCallback, Looper.myLooper());


//Here we are defining the mLocationCallback object, that is used in the previous function.

private final LocationCallback mLocationCallback = new LocationCallback()

    @Override
    public void onLocationResult(LocationResult locationResult)
    
        super.onLocationResult(locationResult);
        if(locationResult.getLastLocation() == null)
            return;

        currentLocation = locationResult.getLastLocation();

        if(firstTimeFlag && googleMap != null)
        
            animateCamera(currentLocation);
            firstTimeFlag = true;
        
        showMarker(currentLocation);
    
;

private void animateCamera(@NonNull Location location)

    LatLng latLng = new LatLng(location.getLatitude(), location.getLongitude());
    googleMap.animateCamera(CameraUpdateFactory.newCameraPosition(getCameraPositionWithBearing(latLng)));


@NonNull
private CameraPosition getCameraPositionWithBearing(LatLng latLng) 

    return new CameraPosition.Builder().target(latLng).zoom(16).build();



private void showMarker(@NonNull Location currentLocation)

    LatLng latLng = new LatLng(currentLocation.getLatitude(), currentLocation.getLongitude());

    if(currentLocationMarker == null)
        currentLocationMarker = googleMap.addMarker(new MarkerOptions().icon(BitmapDescriptorFactory.defaultMarker()).position(latLng));
    else
        MarkerAnimation.animateMarkerToGB(currentLocationMarker, latLng, new LatLngInterpolator.Spherical());




    package com.example.ambulance;

    import ...

public interface LatLngInterpolator

LatLng interpolate(float fraction, LatLng a, LatLng b);

class Spherical implements  LatLngInterpolator

    /* From github.com/googlemaps/android-maps-utils */

    @Override
    public LatLng interpolate(float fraction, LatLng from, LatLng to)
    
        //http://en.wikipedia.org/wiki/Slerp

        double fromLat = toRadians(from.latitude);
        double fromLng = toRadians(from.longitude);
        double toLat = toRadians(to.latitude);
        double toLng = toRadians(to.longitude);
        double cosFromLat = cos(fromLat);
        double cosToLat = cos(toLat);

        //Computes Spherical interpolation co-efficients.

        double angle = computeAngleBetween(fromLat, fromLng, toLat, toLng);
        double sinAngle = sin(angle);

        if (sinAngle < 1E-6)
            return from;

        double a = sin((1 - fraction) * angle) / sinAngle;
        double b = sin(fraction * angle) / sinAngle;

        //Converts from polar to vector and interpolate.

        double x = a * cosFromLat * cos(fromLat) + b * cosToLat * cos(toLng);
        double y = a * cosFromLat * sin(fromLng) + b * cosToLat * sin(toLng);
        double z = a * sin(fromLat) + b * sin(toLat);

        //Converts interpolated vectors back to polar.

        double lat = atan2(z, sqrt(x*x + y*y));
        double lng = atan2(y, x);
        return new LatLng(toDegrees(lat), toDegrees(lng));
    

    private double computeAngleBetween(double fromLat, double fromLng, double toLat, double toLng)
    
        //Haversine's Formula

        double dLat = fromLat - toLat;
        double dLng = fromLng - toLng;
        return 2 * asin(sqrt(pow(sin(dLat / 2), 2) + cos(fromLat) * cos(toLat * pow(sin(dLng / 2), 2))));
    




    package com.example.ambulance;

    import ...

public class MarkerAnimation 
    public static void animateMarkerToGB(final Marker marker, final LatLng finalPosition, final LatLngInterpolator latLngInterpolator) 
    final LatLng startPosition = marker.getPosition();
    final Handler handler = new Handler();
    final long start = SystemClock.uptimeMillis();
    final Interpolator interpolator = new AccelerateDecelerateInterpolator();
    final float durationInMs = 2000;

    handler.post(new Runnable() 
        long elapsed;
        float t;
        float v;

        @Override
        public void run() 
            //Calculator Progress Using Interpolator.
            elapsed = SystemClock.uptimeMillis() - start;
            t = elapsed / durationInMs;
            v = interpolator.getInterpolation(t);

            marker.setPosition(latLngInterpolator.interpolate(v, startPosition, finalPosition));

            //Repeat till progress is complete.

            if (t < 1) 
                //Post again 16ms later.
                handler.postDelayed(this, 16);
            

        
    );


这是我正在使用的代码。 另外,我已经在 AndroidManifest.xml 文件中授予了必要的权限。

【问题讨论】:

【参考方案1】:

您在startLocationUpdates 方法中添加了一个return,以防止应用程序访问此代码:

fusedLocationProviderClient.requestLocationUpdates(locationRequest, mLocationCallback, Looper.myLooper());

删除它可以解决问题,我已经对此进行了验证。

private void startLocationUpdates() 
    LocationRequest locationRequest = LocationRequest.create();
    locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    locationRequest.setInterval(300);
    locationRequest.setSmallestDisplacement(1);

    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) 
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED)
            ActivityCompat.requestPermissions(MapsActivity.this, new String[]Manifest.permission.ACCESS_FINE_LOCATION, REQUEST_ACCESS);
    
    fusedLocationProviderClient.requestLocationUpdates(locationRequest, mLocationCallback, Looper.myLooper());

希望这会有所帮助!

【讨论】:

以上是关于使用 FusedlocationProviderClient Api 在 Android 中进行实时位置跟踪的问题的主要内容,如果未能解决你的问题,请参考以下文章

在使用加载数据流步骤的猪中,使用(使用 PigStorage)和不使用它有啥区别?

今目标使用教程 今目标任务使用篇

Qt静态编译时使用OpenSSL有三种方式(不使用,动态使用,静态使用,默认是动态使用)

MySQL db 在按日期排序时使用“使用位置;使用临时;使用文件排序”

使用“使用严格”作为“使用强”的备份

Kettle java脚本组件的使用说明(简单使用升级使用)