GPSから速度と進行方向を取得する必要があります。ただし、location.getSpeed()
からの唯一の番号は0であるか、使用できない場合があります。私のコード:
String provider = initLocManager();
if (provider == null)
return false;
LocationListener locListener = new LocationListener() {
public void onLocationChanged(Location location) {
updateWithNewLocation(location, interval, startId);
Log.i(getString(R.string.logging_tag), "speed =" + location.getSpeed());
}
public void onProviderDisabled(String provider){
updateWithNewLocation(null, interval, startId);
}
public void onProviderEnabled(String provider) {}
public void onStatusChanged(String provider, int status, Bundle extras) {}
};
_locManager.requestLocationUpdates(provider, interval, DEFAULT_GPS_MIN_DISTANCE, locListener);
private String initLocManager() {
String context = Context.LOCATION_SERVICE;
_locManager = (LocationManager) getSystemService(context);
Criteria criteria = new Criteria();
criteria.setAccuracy(Criteria.ACCURACY_FINE);
criteria.setAltitudeRequired(false);
criteria.setBearingRequired(true);
criteria.setSpeedRequired(true);
criteria.setCostAllowed(true);
//criteria.setPowerRequirement(Criteria.POWER_LOW);
String provider = _locManager.getBestProvider(criteria, true);
if (provider == null || provider.equals("")) {
displayGPSNotEnabledWarning(this);
return null;
}
return provider;
}
基準を試してみましたが、成功しませんでした。誰かが問題が何であるかについての考えを持っていますか?
location.getSpeed()は、location.setSpeed()で設定されたもののみを返します。これは、ロケーションオブジェクトに設定できる値です。
GPSを使用して速度を計算するには、少し計算する必要があります。
Speed = distance / time
したがって、次のことを行う必要があります。
(currentGPSPoint - lastGPSPoint) / (time between GPS points)
すべてフィート/秒に変換されますが、速度を表示したい場合。これは、ランナーアプリを作成したときの方法です。
具体的には、絶対距離を計算する必要があります。
(sqrt((currentGPSPointX - lastGPSPointX)^2) + (currentGPSPointY - lastGPSPointY)^2)) / (time between GPS points)
GPSの位置と内部で取得された時間を保持する新しいTrackPointクラスなどを作成すると役立つ場合があります。
手動で速度を取得するために使用されるカスタムLocationListenerがあり、速度がある場合はロケーションオブジェクトによって使用されます。
new LocationListener() {
private Location mLastLocation;
@Override
public void onLocationChanged(Location pCurrentLocation) {
//calcul manually speed
double speed = 0;
if (this.mLastLocation != null)
speed = Math.sqrt(
Math.pow(pCurrentLocation.getLongitude() - mLastLocation.getLongitude(), 2)
+ Math.pow(pCurrentLocation.getLatitude() - mLastLocation.getLatitude(), 2)
) / (pCurrentLocation.getTime() - this.mLastLocation.getTime());
//if there is speed from location
if (pCurrentLocation.hasSpeed())
//get location speed
speed = pCurrentLocation.getSpeed();
this.mLastLocation = pCurrentLocation;
////////////
//DO WHAT YOU WANT WITH speed VARIABLE
////////////
}
@Override
public void onStatusChanged(String s, int i, Bundle bundle) {
}
@Override
public void onProviderEnabled(String s) {
}
@Override
public void onProviderDisabled(String s) {
}
};
Imbr 's answer 見た目はとても良いですが、ユニットを操作している場合はあまり役に立ちません。
速度をメートル/秒(m/s)で計算するために私がしたことは次のとおりです。
new LocationListener() {
private Location lastLocation = null;
private double calculatedSpeed = 0;
@Override
public synchronized void onLocationChanged(Location location) {
if (lastLocation != null) {
double elapsedTime = (location.getTime() - lastLocation.getTime()) / 1_000; // Convert milliseconds to seconds
calculatedSpeed = lastLocation.distanceTo(location) / elapsedTime;
}
this.lastLocation = location;
double speed = location.hasSpeed() ? location.getSpeed() : calculatedSpeed;
/* There you have it, a speed value in m/s */
. . .
}
. . .
}
球形の惑星では、距離は次の式で計算する必要があります。
private static Double distance(Location one, Location two) {
int R = 6371000;
Double dLat = toRad(two.getLatitude() - one.getLatitude());
Double dLon = toRad(two.getLongitude() - one.getLongitude());
Double lat1 = toRad(one.getLatitude());
Double lat2 = toRad(two.getLatitude());
Double a = Math.sin(dLat / 2) * Math.sin(dLat / 2)
+ Math.sin(dLon / 2) * Math.sin(dLon / 2) * Math.cos(lat1) * Math.cos(lat2);
Double c = 2 * Math.atan2(Math.sqrt(a), Math.sqrt(1 - a));
Double d = R * c;
return d;
}
private static double toRad(Double d) {
return d * Math.PI / 180;
}
getSpeed()メソッドは実際には問題なく機能しますが、1秒などの高いリクエスト間隔を使用する必要があり、高い精度が必要です。最初に3秒の間隔とPRIORITY_BALANCED_POWER_ACCURACYを実行し、言うように変更するまで0の値を取得し続けました。融合ロケーションプロバイダーAPIを使用しています。
public class Main3Activity extends AppCompatActivity {
private FusedLocationProviderClient mFusedLocationClient;
private int speed;
private double lat;
private double lng;
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main2);
mFusedLocationClient = LocationServices.getFusedLocationProviderClient(this);
}
@Override
protected void onResume() {
super.onResume();
if(!runtime_permissions()) {
requestLocations();
}
}
@Override
protected void onPause() {
super.onPause();
//stop location updates when Activity is no longer active
if (mFusedLocationClient != null) {
mFusedLocationClient.removeLocationUpdates(mLocationCallback);
}
}
@SuppressLint("MissingPermission")
private void requestLocations(){
LocationRequest mLocationRequest = new LocationRequest();
mLocationRequest.setInterval(1000);;
mLocationRequest.setPriority(LocationRequest.PRIORITY_HIGH_ACCURACY);
mFusedLocationClient.requestLocationUpdates(mLocationRequest, mLocationCallback, Looper.myLooper());
}
LocationCallback mLocationCallback = new LocationCallback() {
@Override
public void onLocationResult(LocationResult locationResult) {
List<Location> locationList = locationResult.getLocations();
if (locationList.size() > 0) {
//The last location in the list is the newest
Location location = locationList.get(locationList.size() - 1);
lat = location.getLatitude();
lng = location.getLongitude();
//speed in km/h
speed = (int) ((location.getSpeed() * 3600) / 1000);
}
}
};
private boolean runtime_permissions() {
if(Build.VERSION.SDK_INT >= 23 && ContextCompat.checkSelfPermission(this,
Manifest.permission.ACCESS_FINE_LOCATION) != PackageManager.PERMISSION_GRANTED){
requestPermissions(new String[]{Manifest.permission.ACCESS_FINE_LOCATION},100);
return true;
}
return false;
}
@Override
public void onRequestPermissionsResult(int requestCode, @NonNull String[] permissions, @NonNull int[] grantResults) {
super.onRequestPermissionsResult(requestCode, permissions, grantResults);
if(requestCode == 100){
if( grantResults[0] == PackageManager.PERMISSION_GRANTED){
onResume();
}else{
runtime_permissions();
}
}
}
}
getspeed()は正常に動作します。距離の式を使用して計算を行う必要はありません。 getspeedにはすでにありますが、緯度と経度がある限り、getspeedには速度があります。
(1)requestLocationUpdates()
メソッドを使用して、onLocationChangeメソッドがgetSpeed()
を表示するように設定されたLocationListenerクラスを作成できると思います。これは私が最近Location.getLatitudeとLocation.getLongitudeで行われたのを見た方法ですので、getSpeed()を同じように使用できると思いますよね?
(2)ただし、Eclipseの説明ウィンドウを読んだだけで、前の人が言ったことを正確に示していることがわかります。「hasSpeed()がfalseの場合、0.0fが返されます。」しかし、おそらくこれは役立つでしょう: http://www.ehow.com/how_5708473_convert-latitude-feet.html :)
ねえ私も同じように苦しんでいましたが、今は解決しました!値に18/5を掛けるだけで、ほぼ正確な値が得られます。
speed=location.getSpeed()*18/5
また、精度を高めるために、interval
を1000*2
として指定し、fastest interval
を1000*1
として指定します。
私も以前にこの問題に遭遇しました、これが役立つことを願っています。
デバイスがGPSをロックできないか、GPSに接続できないため、0が返されます。
古いレノボデバイスを使用して速度を取得しようとしましたが、gpsをロックできないため0を返します。
私はサムスンギャラクシーネクサスを使用してみました、そしてそれは私の速度を返しました(より良いGPSセンサーを持っています)。
スマートフォンのGPSセンサーが適切でないか、家の中や建物内など、GPS信号が弱い場所にいる可能性があります。
基本的に瞬間速度を計算し、setSpeed()メソッドを使用してその場所に追加します。タキメーターを確認できる車内で比較したので、かなり正確です。
private double calculateInstantaneousSpeed(Location location) {
double insSpeed = 0;
if (y1 == null && x1 <= -1) {
//mark the location y1 at time x1
y1 = location;
x1 = duration.getDurationAsSeconds();
} else {
//mark the location y2 at time x2
y2 = location;
x2 = duration.getDurationAsSeconds();
//calculate the slope of the curve (instantaneous speed)
dy = y1.distanceTo(y2);
dx = x2 - x1;
insSpeed = dy / dx;
y1 = y2;
x1 = x2;
}
Singleton.getInstance().instantaneousSpeedSamples.add(insSpeed);
//System.out.println("Instantaneous Speed m/s: "+insSpeed);
return insSpeed;
}