在安卓10中跳转GPS位置

huangapple go评论85阅读模式
英文:

Jumping gps location in android 10

问题

public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {

    private static final String TAG = LocationFinder.class.getSimpleName();
    private Location location;
    private GoogleApiClient googleApiClient;
    private LocationRequest locationRequest;
    private static final long UPDATE_INTERVAL = 1000, FASTEST_INTERVAL = 1000;
    private Context context;
    static final public String GDS_RESULT = "AE_Find_Location";
    static final public String GDS_SPEED = "Service_SPD";
    static final public String GDS_LAT = "Service_lat";
    static final public String GDS_LON = "Service_lon";
    static final public String GDS_BEARING = "Service_bearing";
    private LocalBroadcastManager broadcaster;
    private int SEND_LOCATION_TIMER = 30000;
    public static final int REQUEST_CHECK_SETTINGS = 100;

    @Override
    public void onCreate() {
        super.onCreate();
        context = getApplicationContext();
        googleApiClient = new GoogleApiClient.Builder(this)
                .addApi(LocationServices.API)
                .addConnectionCallbacks(this)
                .addOnConnectionFailedListener(this).build();
        broadcaster = LocalBroadcastManager.getInstance(this);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (googleApiClient != null)
            googleApiClient.connect();
        startSendData();
        return START_STICKY;
    }

    private ArrayList<Location> locations = new ArrayList<>();
    private ConcurrentLinkedQueue<Coordinate> queue = new ConcurrentLinkedQueue<>();
    private Timer timer;
    private TimerTask timerTask = new TimerTask() {
        @Override
        public void run() {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    if (location == null) return;
                    sendResult(location);
                }
            }).start();
        }
    };

    public void startSendData() {
        if (timer != null) {
            return;
        }
        timer = new Timer();
        timer.scheduleAtFixedRate(timerTask, 0, 1000);
    }

    public void stopSendData() {
        if (timer == null) return;
        timer.cancel();
        timer = null;
    }

    @Nullable
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }

    @Override
    public void onConnected(Bundle bundle) {
        if (ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
                && ActivityCompat.checkSelfPermission(this,
                Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
            return;
        }

        LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
                .addLocationRequest(locationRequest);
        builder.setAlwaysShow(true);

        PendingResult<LocationSettingsResult> result =
                LocationServices.SettingsApi.checkLocationSettings(
                        googleApiClient,
                        builder.build()
                );

        result.setResultCallback(new ResultCallback<LocationSettingsResult>() {
            @Override
            public void onResult(LocationSettingsResult locationSettingsResult) {
                final Status status = locationSettingsResult.getStatus();

                switch (status.getStatusCode()) {
                    case LocationSettingsStatusCodes.SUCCESS:
                        // NO need to show the dialog;
                        break;
                    case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
                        try {
                            status.startResolutionForResult(MyApplication.currentActivity, REQUEST_CHECK_SETTINGS);
                        } catch (IntentSender.SendIntentException e) {
                            //failed to show dialog
                        }
                        break;
                    case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
                        // Location settings are unavailable so not possible to show any dialog now
                        break;
                }
            }
        });

        location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
        startLocationUpdates();
    }

    private void startLocationUpdates() {
        locationRequest = new LocationRequest();
        locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
        locationRequest.setInterval(UPDATE_INTERVAL);
        locationRequest.setFastestInterval(FASTEST_INTERVAL);

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

        LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
    }

    @Override
    public void onConnectionSuspended(int i) {
    }

    @Override
    public void onConnectionFailed(ConnectionResult connectionResult) {
    }

    @Override
    public void onLocationChanged(Location location) {
        if (location != null) {
            this.location = location;
        }
    }

    @Override
    public void onDestroy() {
        super.onDestroy();
        if (googleApiClient != null && googleApiClient.isConnected()) {
            LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
            googleApiClient.disconnect();
        }
        stopSendData();
    }

    public void sendResult(Location location) {
        try {
            if (location == null) return;

            String lat = HelperNumber.convertNumber(new DecimalFormat("##.#####").format(location.getLatitude()));
            String lng = HelperNumber.convertNumber(new DecimalFormat("##.#####").format(location.getLongitude()));

            Intent intent = new Intent(GDS_RESULT);
            intent.putExtra(GDS_SPEED, location.getSpeed());
            intent.putExtra(GDS_LAT, Double.valueOf(lat));
            intent.putExtra(GDS_LON, Double.valueOf(lng));
            intent.putExtra(GDS_BEARING, location.getBearing());
            broadcaster.sendBroadcast(intent);

            if (MyApplication.prefManager.getApiRequestTime() + SEND_LOCATION_TIMER > Calendar.getInstance().getTimeInMillis())
                return;
            MyApplication.prefManager.setApiRequestTime(Calendar.getInstance().getTimeInMillis());

        } catch (NullPointerException e) {
            e.printStackTrace();
        }
    }
}
英文:

I use location service in my navigation app. The service get location per second. But jumping gps location is like this photo:

在安卓10中跳转GPS位置

In the service used the GoogleApiClient and LocationListener for get best last location. Also used broadcast for send result to app.
and my location service is:

public class LocationService extends Service implements GoogleApiClient.ConnectionCallbacks, GoogleApiClient.OnConnectionFailedListener, LocationListener {
private static final String TAG = LocationFinder.class.getSimpleName();
private Location location;
private GoogleApiClient googleApiClient;
private LocationRequest locationRequest;
private static final long UPDATE_INTERVAL = 1000, FASTEST_INTERVAL = 1000;
private Context context;
// Send Data to View with BroadCast
static final public String GDS_RESULT = &quot;AE_Find_Location&quot;;
static final public String GDS_SPEED = &quot;Service_SPD&quot;;
static final public String GDS_LAT = &quot;Service_lat&quot;;
static final public String GDS_LON = &quot;Service_lon&quot;;
static final public String GDS_BEARING = &quot;Service_bearing&quot;;
private LocalBroadcastManager broadcaster;
private int SEND_LOCATION_TIMER = 30000;
public static final int REQUEST_CHECK_SETTINGS = 100;
@Override
public void onCreate() {
super.onCreate();
context = getApplicationContext();
// we build google api client
googleApiClient = new GoogleApiClient.Builder(this)
.addApi(LocationServices.API)
.addConnectionCallbacks(this)
.addOnConnectionFailedListener(this).build();
broadcaster = LocalBroadcastManager.getInstance(this);
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
if (googleApiClient != null)
googleApiClient.connect();
startSendData();
return START_STICKY;
}
private ArrayList&lt;Location&gt; locations = new ArrayList&lt;&gt;();
private ConcurrentLinkedQueue&lt;Coordinate&gt; queue = new ConcurrentLinkedQueue&lt;&gt;();
private Timer timer;
private TimerTask timerTask = new TimerTask() {
@Override
public void run() {
new Thread(new Runnable() {
@Override
public void run() {
if (location == null) return;
sendResult(location);
}
}).start();
}
};
public void startSendData() {
if (timer != null) {
return;
}
timer = new Timer();
timer.scheduleAtFixedRate(timerTask, 0, 1000);
}
public void stopSendData() {
if (timer == null) return;
timer.cancel();
timer = null;
}
@Nullable
@Override
public IBinder onBind(Intent intent) {
return null;
}
@Override
public void onConnected(Bundle bundle) {
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&amp;&amp; ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
return;
}
Log.i(TAG, &quot;onResult: connected&quot;);
LocationSettingsRequest.Builder builder = new LocationSettingsRequest.Builder()
.addLocationRequest(locationRequest);
builder.setAlwaysShow(true);
PendingResult&lt;LocationSettingsResult&gt; result =
LocationServices.SettingsApi.checkLocationSettings(
googleApiClient,
builder.build()
);
result.setResultCallback(new ResultCallback&lt;LocationSettingsResult&gt;() {
@Override
public void onResult(LocationSettingsResult locationSettingsResult) {
final Status status = locationSettingsResult.getStatus();
switch (status.getStatusCode()) {
case LocationSettingsStatusCodes.SUCCESS:
// NO need to show the dialog;
break;
case LocationSettingsStatusCodes.RESOLUTION_REQUIRED:
try {
status.startResolutionForResult(MyApplication.currentActivity, REQUEST_CHECK_SETTINGS);
} catch (IntentSender.SendIntentException e) {
//failed to show dialog
}
break;
case LocationSettingsStatusCodes.SETTINGS_CHANGE_UNAVAILABLE:
// Location settings are unavailable so not possible to show any dialog now
break;
}
}
});
// Permissions ok, we get last location
location = LocationServices.FusedLocationApi.getLastLocation(googleApiClient);
startLocationUpdates();
}
private void startLocationUpdates() {
locationRequest = new LocationRequest();
locationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
locationRequest.setInterval(UPDATE_INTERVAL);
locationRequest.setFastestInterval(FASTEST_INTERVAL);
if (ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED
&amp;&amp; ActivityCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_COARSE_LOCATION) != PackageManager.PERMISSION_GRANTED) {
}
LocationServices.FusedLocationApi.requestLocationUpdates(googleApiClient, locationRequest, this);
}
@Override
public void onConnectionSuspended(int i) {
}
@Override
public void onConnectionFailed(ConnectionResult connectionResult) {
}
@Override
public void onLocationChanged(Location location) {
if (location != null) {
this.location = location;
}
}
@Override
public void onDestroy() {
super.onDestroy();
// stop location updates
if (googleApiClient != null &amp;&amp; googleApiClient.isConnected()) {
LocationServices.FusedLocationApi.removeLocationUpdates(googleApiClient, this);
googleApiClient.disconnect();
}
stopSendData();
}
public void sendResult(Location location) {
try {
if (location == null) return;
String lat = HelperNumber.convertNumber(new DecimalFormat(&quot;##.#####&quot;).format(location.getLatitude()));
String lng = HelperNumber.convertNumber(new DecimalFormat(&quot;##.#####&quot;).format(location.getLongitude()));
Intent intent = new Intent(GDS_RESULT);
intent.putExtra(GDS_SPEED, location.getSpeed());
intent.putExtra(GDS_LAT, Double.valueOf(lat));
intent.putExtra(GDS_LON, Double.valueOf(lng));
intent.putExtra(GDS_BEARING, location.getBearing());
broadcaster.sendBroadcast(intent);
if (MyApplication.prefManager.getApiRequestTime() + SEND_LOCATION_TIMER &gt; Calendar.getInstance().getTimeInMillis())
return;
MyApplication.prefManager.setApiRequestTime(Calendar.getInstance().getTimeInMillis());
} catch (NullPointerException e) {
e.printStackTrace();
}
}
}

Thanks about your help.

答案1

得分: 0

你可以设置一个条件语句(if)来检查是否为伪造。

将你的timerTask代码更改为类似以下内容:

    private TimerTask timerTask = new TimerTask() {
            @Override
            public void run() {
                new Thread(new Runnable() {
                    @Override
                    public void run() {
                        if (location == null) return;
    
                        if (lastLocation != null) {
                            if (Math.abs((lastLocation.distanceTo(location)) / (location.getTime() - lastLocation.getTime())) > 0.06 && counter < 5) {
                                sendResult(lastLocation);
                                counter++;
                                return;
                            }
                        }
                        counter = 0;
                        sendResult(location);
                        lastLocation = location;
                    }
                }).start();
            }
        };

值 0.6 是用于过滤跳跃 GPS 的阈值。

英文:

You can set a condition statement (if) to check if that is fake or not.

Change your code on timerTask to something like this:

    private TimerTask timerTask = new TimerTask() {
@Override
public void run() {
new Thread(new Runnable() {
@Override
public void run() {
if (location == null) return;
if (lastLocation != null) {
if (Math.abs((lastLocation.distanceTo(location)) / (location.getTime() - lastLocation.getTime())) &gt; 0.06 &amp;&amp; counter&lt;5) {
sendResult(lastLocation);
counter++;
return;
}
}
counter = 0;
sendResult(location);
lastLocation = location;
}
}).start();
}
};

Value 0.6 is a threshold for filter jump GPS.

答案2

得分: 0

最好规范智能手机中跳跃的GPS信号的方法是删除低准确度的位置。
而且低速度时位置准确度较低。
希望这种方法有助于解决这个问题。

英文:

The best way to normalize jumping gps in smartphone is remove locations that the low accuracy.
Also the location accuracy is low on low speeds.
I hope this way useful to resolve this problem.

huangapple
  • 本文由 发表于 2020年7月26日 13:25:17
  • 转载请务必保留本文链接:https://go.coder-hub.com/63096406.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定