简体   繁体   English

Android 服务未更新位置

[英]Android Service not updating location

I need to update fused location every 1 min and on each 5 meter displacement (I know its bad practice but for the sake of testing and showing in Log ) and i start service by button Pressed as soon as button pressed i got location in logcat but only once.我需要每 1 分钟和每 5 米位移更新一次融合位置(我知道这是不好的做法,但为了测试和显示在 Log 中),我通过按钮开始服务按下按钮后立即按下我在 logcat 中找到位置但是只有一次。 As per Service class the onLocationChanged should called every 1 min but it never calls again even my GPS turn on almost every min and then turn off after while but still there is no Location Update in Logcat.I need service class to keep update location without effecting UI or main thread根据服务类onLocationChanged应每 1 分钟调用一次,但即使我的 GPS 几乎每分钟打开一次,然后在一段时间后关闭,它也不会再次调用,但 Logcat 中仍然没有位置更新。我需要服务类来保持更新位置而不影响UI 或主线程

Here is logcat which shows location update only once这是 logcat 只显示一次位置更新

09-16 03:13:37.125 10419-10419/com.example.com.pro_working1 D/===Location Service===: Service onConnected Calling
09-16 03:13:37.125 10419-10419/com.example.com.pro_working1 D/===Location Service===: Start Location Update is Calling
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Service OnLocationChanged Calling
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Here is Updated Locations: Latitude 28.5XXXXX Longitude 77.2XXXXX
09-16 03:13:38.315 10419-10419/com.example.com.pro_working1 D/===Location Service===: Sending Location Starting  Accuracy is: 37.5

Here is my Service Class这是我的服务类

public class Location_Service_background extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
    public static final String TAG = "===Location Service===";
    GoogleApiClient apiClient;
    Location mCurrentLocation;
    LocationRequest locationRequest;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        GoogleApiSetup();
        RequestLocationUpdates();
        Log.d(TAG,"OnStartCommand Is Calling ");
        return START_STICKY;
    }

    @Override
    public IBinder onBind(Intent intent) {
        // TODO: Return the communication channel to the service.
        throw new UnsupportedOperationException("Not yet implemented");
    }



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

    }


    @Override
    public void onDestroy() {
        super.onDestroy();
        if (apiClient.isConnected()){
            Log.d(TAG,"Service On Destroy Calling and apiClient is Connected");
            StopLocationUpdates();
            apiClient.disconnect();
        }
    }

    @Override
    public void onLowMemory() {
        super.onLowMemory();
    }

    @Override
    public void onConnected(@Nullable Bundle bundle) {
        Log.d(TAG,"Service onConnected Calling");
        if (mCurrentLocation != null) {
            if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
                return;
            }
             mCurrentLocation = LocationServices.FusedLocationApi.getLastLocation(apiClient);

        }
        else {
            Log.d(TAG,"Start Location Update is Calling");
            StartLocationUpdate();
        }
    }

    @Override
    public void onConnectionSuspended(int i) {
        Log.d(TAG,"Service OnConnectionSuspended Calling");
        apiClient.connect();
    }

    @Override
    public void onLocationChanged(Location location) {
        Log.d(TAG,"Service OnLocationChanged Calling");
        mCurrentLocation=location;
        Log.d(TAG,"Here is Updated Locations: Latitude "+mCurrentLocation.getLatitude()+"Longitude "+mCurrentLocation.getLongitude());
        String Latitude= String.valueOf(mCurrentLocation.getLatitude());
        String Longitude=String.valueOf(mCurrentLocation.getLongitude());
        String Accuracy=String.valueOf(mCurrentLocation.getAccuracy());
        Log.d(TAG,"Sending Location Starting"+" "+" Accuracy is: "+mCurrentLocation.getAccuracy());


    }

    @Override
    public void onConnectionFailed(@NonNull ConnectionResult connectionResult) {
        Log.d(TAG,"Connection Failed Called "+connectionResult);
    }



    private synchronized  void GoogleApiSetup() {
        apiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this)
                .build();
        apiClient.connect();
    }

    private void RequestLocationUpdates() {
        locationRequest = new LocationRequest();
        //1 Min = 60 seconds AND 1000 milliseconds in 1 second
        locationRequest.setInterval(60 * 1000);//5 Min 300 x 1000=300000
        locationRequest.setFastestInterval(60 * 1000);//2 Min
        locationRequest.setSmallestDisplacement(5);
        locationRequest.setMaxWaitTime(60*1000);
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
    }

    private void StopLocationUpdates() {
        LocationServices.FusedLocationApi.removeLocationUpdates(apiClient, this);
    }

    private void StartLocationUpdate() {
        if (ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED && ActivityCompat.checkSelfPermission(this, Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {

            return;
        }
        if (apiClient.isConnected()) {
            LocationServices.FusedLocationApi.requestLocationUpdates(apiClient, locationRequest, this);
        }
        else {
            Log.d(TAG,"GoogleApiClient is not connected yet.Please Try Again");
            apiClient.connect();
        }
    }


}

Hopefully this helps save someone the frustration i went through on this issue.希望这有助于避免我在这个问题上遇到的挫折。 I am using the FusedLocationAPI to request location updates and GoogleApiClient.我正在使用 FusedLocationAPI 来请求位置更新和 GoogleApiClient。 I also do this from a Service.我也从服务中做到这一点。

You are not getting any location updates at your timed interval because setSmallestDisplacement() takes absolute priority over the other parameters.由于 setSmallestDisplacement() 绝对优先于其他参数,因此您不会在定时间隔内获得任何位置更新。 So even if you have所以即使你有

locationRequestTimeInterval = LocationRequest.create()
    .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
    .setInterval(1)    
    .setFastestInterval(1)    
    .setMaxWaitTime(1)    
    .setSmallestDisplacement(5);

this will NEVER be triggered until the smallestDisplacement parameter is met.在满足smallestDisplacement 参数之前,这永远不会被触发。

The solution to this, is to create two separate LocationRequests... one that is only concerned with distance, and one that is only concerned with time, and use your single GoogleApiClient to create 2 requestLocationUpdates commands, one using the Time LocationRequest, and the other using the Distance LocationRequest.对此的解决方案是创建两个单独的 LocationRequests...一个只关心距离,一个只关心时间,并使用您的单个 GoogleApiClient 创建 2 个 requestLocationUpdates 命令,一个使用 Time LocationRequest,以及其他使用距离位置请求。

So your 2 LocationRequests look like this:所以你的 2 LocationRequests 看起来像这样:

locationRequestDistanceInterval = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setFastestInterval(0) // This MUST be set, otherwise no updates
            .setSmallestDisplacement(LOCATION_REQUEST_MIN_DISTNACE);

locationRequestTimeInterval = LocationRequest.create()
            .setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY)
            .setInterval(PROVIDER_GPS_UPDATE_TIME_INTERVAL)
            .setFastestInterval(PROVIDER_GPS_UPDATE_TIME_INTERVAL);
  • note that the setFastestInterval() value MUST be set on the Distance Request, otherwise the distance request will not be triggered.请注意,必须在距离请求上设置 setFastestInterval() 值,否则将不会触发距离请求。 It does not have to be 0, but this field must be set.它不必为 0,但必须设置此字段。

Then in your GoogleApiClients onConnected(), you can add the two requestLocationUpdates() calls.然后在您的 GoogleApiClients onConnected() 中,您可以添加两个 requestLocationUpdates() 调用。

LocationServices.FusedLocationApi.requestLocationUpdates(
    mLocationClient, 
    locationRequestDistanceInterval, 
    new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            // Handle your Distance based updates
        }
    }
);

LocationServices.FusedLocationApi.requestLocationUpdates(
    mLocationClient, 
    locationRequestTimeInterval, 
    new LocationListener() {
        @Override
        public void onLocationChanged(Location location) {
            // Handle your Time based updates
        }
    }
);  

You can use the same or separate LocationListeners to handle the responses for each request.您可以使用相同或不同的 LocationListeners 来处理每个请求的响应。 Hope this helps.希望这可以帮助。

Presuming that you are in fact moving the device more than 5 meters between expected updates , I think there might be a problem with the LocationRequest class where the setSmallestDisplacement() method just doesn't work properly... or at least it doesn't work as expected.假设您实际上在预期更新之间移动设备超过 5 米,我认为 LocationRequest 类可能存在问题,其中 setSmallestDisplacement() 方法无法正常工作......或者至少它没有按预期工作。 (I've seen these issues on other posts ). (我在其他帖子上看到过这些问题)。

You could always check the distance yourself by removing the setSmallestDisplacement(), and instead doing:您始终可以通过删除 setSmallestDisplacement() 来自己检查距离,而是执行以下操作:

onLocationChanged() {
    double distance = // [ calculate distance between current lat/long and previous lat/long ]
    if (distance > 5 meters) {
        // do your normal onLocationChanged() code here
    }
}

There is also the possiblity that for some reason, the FusedLocationProvider is not able to access your GPS and is instead using wifi or cell tower... in which case, 5m is too small of a distance to specify.也有可能由于某种原因,FusedLocationProvider 无法访问您的 GPS,而是使用 wifi 或手机信号塔……在这种情况下,5m 的距离太小而无法指定。 Your logs say the accuracy is 37.5 meters, so that doesn't seem accurate enough to be able to measure 5 meters.您的日志显示精度为 37.5 米,因此这似乎不够准确,无法测量 5 米。 So... maybe you don't have FINE access permission set in your manifest?那么...也许您的清单中没有设置 FINE 访问权限?

Also could it be a problem with runtime permissions not being done properly?也可能是运行时权限没有正确完成的问题吗? You could temporarily set your target SDK to 22 in order to check this.您可以暂时将目标 SDK 设置为 22 以进行检查。

little help who knows it can be used小帮助谁知道可以用

    int jarak = 10;
    int interval = 5;


    LocationRequest request = new LocationRequest();
    request.setInterval(interval*1000); //update lokasi 10 detik
    request.setFastestInterval(interval*1000); //dapat update dari aplikasi lain yg lebih cepat 10 detik
    //request.setSmallestDisplacement(1); //diupdate jika berpindah 1 meter
    request.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);


    FusedLocationProviderClient client = LocationServices.getFusedLocationProviderClient(this);
    int permission = ContextCompat.checkSelfPermission(this, Manifest.permission.ACCESS_FINE_LOCATION);
    if(permission == PackageManager.PERMISSION_GRANTED) {



        client.requestLocationUpdates(request, new LocationCallback() {

            @Override
            public void onLocationResult(LocationResult locationResult) {
                List<Location> locationList = locationResult.getLocations();
                if (locationList.size() > 0) {
                    Location locationCurrent = locationList.get(locationList.size() - 1);


                    double latitude = locationCurrent.getLatitude();
                    double longitude = locationCurrent.getLongitude();

                    double lastlatitude = Double.parseDouble(prefs.getString("lastlatitude","0"));
                    double lastlongitude = Double.parseDouble(prefs.getString("lastlongitude","0"));

                    Location startPoint=new Location("LokasiA");
                    startPoint.setLatitude(latitude);
                    startPoint.setLongitude(longitude);

                    Location endPoint = new Location("LokasiB");
                    endPoint.setLatitude(lastlatitude);
                    endPoint.setLongitude(lastlongitude);

                    double distance = startPoint.distanceTo(endPoint);

                    Log.d(tag, "location update last " + endPoint);
                    if(distance > jarak) {
                        Log.d(tag, "location update new" + startPoint);
                        Log.d(tag, "location dest " + distance);

                        SharedPreferences.Editor editor = prefs.edit();
                        editor.putString("lastlatitude", String.valueOf(latitude));
                        editor.putString("lastlongitude", String.valueOf(longitude));
                        editor.apply();



                        Log.i("getLatitude:",String.valueOf(locationCurrent.getLatitude()) );
                        Log.i("getLongitude:",String.valueOf(locationCurrent.getLongitude()) );


                    }

                }


            }
        },null);
    }

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

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