LocationManager和跳跃坐标 [英] LocationManager and jumping coordinates

查看:95
本文介绍了LocationManager和跳跃坐标的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

看看这张图片。你会看到一些LocationManager如何给出奇怪的坐标。看起来他们跳起来了。但同时本地谷歌地图应用程序显示移动设备的正确位置。



我使用Android 7.0.0和7.1.1下的3种不同智能手机测试了应用程序,或多或少的相同结果。



请帮我检查一下我的代码,看看它丢失了哪些设置。



谢谢! p>

  import android.app.Service; 
导入android.content.Context;
导入android.content.Intent;
导入android.location.Location;
导入android.location.LocationManager;
导入android.net.ConnectivityManager;
导入android.net.NetworkInfo;
导入android.os.Bundle;
导入android.os.Handler;
导入android.os.HandlerThread;
导入android.os.IBinder;
导入android.text.format.DateFormat;
导入android.util.Log;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
导入java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Date;

public class gps_service2 extends Service {
private static final String TAG =GPS SERVICE;
私人LocationManager mLocationManager = null;
private static final int LOCATION_INTERVAL = 15000;
private static final float LOCATION_DISTANCE = 10f;
上下文上下文;

private class LocationListener实现android.location.LocationListener
{
Location mLastLocation;

public LocationListener(String provider)
{
Log.e(TAG,LocationListener+ provider);
mLastLocation =新位置(供应商);
}

@Override
public void onLocationChanged(Location location)
{
Log.e(TAG,onLocationChanged:+ location);

尝试
{
ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(context,App_Settings,0);
AppSettings appSettings = complexPreferences.getObject(App_Settings,AppSettings.class);

boolean isMobileDataEnabled = Utils.isMobileDataEnabled(context); (appSettings!= null&&(isMobileDataEnabled)){

LocationItem locationItem = new LocationItem();
locationItem.DeviceID = appSettings.getDeviceID();
locationItem.Latitude = Double.toString(location.getLatitude());
locationItem.Longitude = Double.toString(location.getLongitude());
日期d =新日期();
CharSequence timeOfRequest = DateFormat.format(yyyy-MM-dd HH:mm:ss,d.getTime());
locationItem.TimeOfRequest = timeOfRequest.toString();
locationItem.SerialNumber = appSettings.getSerialNumber();

mLastLocation.set(location);

Gson gson = new Gson();
String requestObject = gson.toJson(locationItem);
Log.d(TAG,ФормированиеURL APIсервера);
String url = appSettings.getIpAddress()+/ api / staff / savedata;
makeRequest(url,requestObject,dLocation);


catch(Exception ex)
{
Log.d(TAG,Ошибка:+ ex.getMessage());



@Override
public void onProviderDisabled(String provider)
{
Log.e(TAG,onProviderDisabled: +提供者);
}

@Override
public void onProviderEnabled(String provider)
{
Log.e(TAG,onProviderEnabled:+ provider);

$ b @Override
public void onStatusChanged(String provider,int status,Bundle extras)
{
Log.e(TAG,onStatusChanged: +提供者);



LocationListener [] mLocationListeners = new LocationListener [] {
new LocationListener(LocationManager.GPS_PROVIDER),
new LocationListener(LocationManager.NETWORK_PROVIDER )
};

@Override
public IBinder onBind(Intent arg0)
{
return null;

$ b @Override
public int onStartCommand(Intent intent,int flags,int startId)
{
Log.e(TAG,onStartCommand );
super.onStartCommand(intent,flags,startId);
返回START_STICKY;
}

@Override
public void onCreate()
{
context = this;
Log.e(TAG,onCreate);
initializeLocationManager();
尝试{
mLocationManager.requestLocationUpdates(
LocationManager.NETWORK_PROVIDER,LOCATION_INTERVAL,LOCATION_DISTANCE,
mLocationListeners [1]);
} catch(java.lang.SecurityException ex){
Log.i(TAG,无法请求位置更新,忽略,前);
} catch(IllegalArgumentException ex){
Log.d(TAG,网络提供者不存在,+ ex.getMessage());
}
尝试{
mLocationManager.requestLocationUpdates(
LocationManager.GPS_PROVIDER,LOCATION_INTERVAL,LOCATION_DISTANCE,
mLocationListeners [0]);
} catch(java.lang.SecurityException ex){
Log.i(TAG,无法请求位置更新,忽略,前);
} catch(IllegalArgumentException ex){
Log.d(TAG,gps provider does not exist+ ex.getMessage());


$ b @Override
public void onDestroy()
{
Log.e(TAG,onDestroy);
super.onDestroy();如果(mLocationManager!= null){
(int i = 0; i< mLocationListeners.length; i ++){
try {
mLocationManager.removeUpdates(mLocationListeners [i ]);
} catch(Exception ex){
Log.i(TAG,无法移除位置列表,忽略,ex);




$ b private void initializeLocationManager(){
Log.e(TAG,initializeLocationManager);
if(mLocationManager == null){
mLocationManager =(LocationManager)getApplicationContext()。getSystemService(Context.LOCATION_SERVICE);



public static double round(double value,int places){
if(places <0)throw new IllegalArgumentException();
BigDecimal bd = new BigDecimal(value);
bd = bd.setScale(places,RoundingMode.HALF_UP);
return bd.doubleValue();

$ b $ public void makeRequest(String uri,String json,DLocation dLocation){
HandlerThread handlerThread = new HandlerThread(URLConnection);
handlerThread.start();
Handler mainHandler = new Handler(handlerThread.getLooper());
Runnable myRunnable = createRunnable(uri,json,dLocation);
mainHandler.post(myRunnable);

$ b $ private private Runnable createRunnable(final String uri,final String data,final DLocation dLocation){

Runnable aRunnable = new Runnable(){
public void run(){
try {
// Connect
HttpURLConnection urlConnection;
urlConnection =(HttpURLConnection)((new URL(uri).openConnection()));
urlConnection.setDoOutput(true);
urlConnection.setRequestProperty(Content-Type,application / json);
urlConnection.setRequestProperty(Accept,application / json);
urlConnection.setRequestMethod(POST);

urlConnection.setConnectTimeout(12000);
urlConnection.setReadTimeout(10000);

urlConnection.connect();

//写入
OutputStream outputStream = urlConnection.getOutputStream();
BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream,UTF-8));
尝试{
writer.write(data);
} catch(IOException e){
e.printStackTrace();
Log.d(TAG,用于HTTP协议的HTTP协议);
}
writer.close();
outputStream.close();

//读取
BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(),UTF-8));

String line = null;
StringBuilder sb = new StringBuilder(); ((line = bufferedReader.readLine())!= null){
sb.append(line);

while
}

bufferedReader.close();
String result = sb.toString();

Log.d(TAG,result);

$ b catch(SocketTimeoutException e){
e.printStackTrace();

Log.d(TAG,ОшибкаHTTP+ e.getMessage());
}
catch(Exception e){
e.printStackTrace();
}
}
};

返回aRunnable;



$ b


解决方案

这是智能手机/消费级GPS的典型行为。为了减少波动,您需要对结果进行归一化。一种方法是从坐标队列计算地理中心,例如: https://github.com/Esri/cordova-plugin-advanced-geolocation/blob/master/src/com/esri/cordova/geolocation /utils/GeodataHelper.java#L56

  public class Coordinate {
public double latitude;
公共双倍经度;
公众持股量准确性;
}

public static Coordinate getGeographicCenter(final ConcurrentLinkedQueue< Coordinate> queue){
double x = 0;
double y = 0;
double z = 0;
浮点数精度= 0;
int radiusKM = 6367;

(最终坐标坐标:队列){
精度+ =坐标准确度;

//将经度和经度转换为弧度
final double latRad = Math.PI * coordinate.latitude / 180;
final double lonRad = Math.PI * coordinate.longitude / 180;

//转换成笛卡尔坐标
x + = radiusKM * Math.cos(latRad)* Math.cos(lonRad);
y + = radiusKM * Math.cos(latRad)* Math.sin(lonRad);
z + = radiusKM * Math.sin(latRad);
}

//获取我们的平均值
final double xAvg = x / queue.size();
final double yAvg = y / queue.size();
final double zAvg = z / queue.size();
final float accuracyAvg = accuracy / queue.size();

//将笛卡尔转换回弧度
final double sphericalLatRads = Math.asin(zAvg / radiusKM);
final double sphericalLonRads = Math.atan2(yAvg,xAvg);

//将弧度转换回经度和纬度
坐标centerPoint = new Coordinate();
centerPoint.latitude = sphericalLatRads *(180 / Math.PI);
centerPoint.longitude = sphericalLonRads *(180 / Math.PI);
centerPoint.accuracy = accuracyAvg;

return centerPoint;
}


Take a look at this image. You see that some how LocationManager gives weird coordinates. It looks like they jump. But at the same time native google map app display correct location of the moving device.

I tested app with 3 different smartphones under Android 7.0.0 and 7.1.1 and get the same result more or less.

Please help me check my code to see which settings it is missing still.

Thank you!

import android.app.Service;
import android.content.Context;
import android.content.Intent;
import android.location.Location;
import android.location.LocationManager;
import android.net.ConnectivityManager;
import android.net.NetworkInfo;
import android.os.Bundle;
import android.os.Handler;
import android.os.HandlerThread;
import android.os.IBinder;
import android.text.format.DateFormat;
import android.util.Log;
import com.google.gson.Gson;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.HttpURLConnection;
import java.net.SocketTimeoutException;
import java.net.URL;
import java.util.Date;

public class gps_service2 extends Service {
    private static final String TAG = "GPS SERVICE";
    private LocationManager mLocationManager = null;
    private static final int LOCATION_INTERVAL = 15000;
    private static final float LOCATION_DISTANCE = 10f;
    Context context;

    private class LocationListener implements android.location.LocationListener
    {
        Location mLastLocation;

        public LocationListener(String provider)
        {
            Log.e(TAG, "LocationListener " + provider);
            mLastLocation = new Location(provider);
        }

        @Override
        public void onLocationChanged(Location location)
        {
            Log.e(TAG, "onLocationChanged: " + location);

            try
            {
                ComplexPreferences complexPreferences = ComplexPreferences.getComplexPreferences(context, "App_Settings", 0);
                AppSettings appSettings = complexPreferences.getObject("App_Settings", AppSettings.class);

                boolean isMobileDataEnabled = Utils.isMobileDataEnabled(context);

                if (appSettings != null && (isMobileDataEnabled)) {

                    LocationItem locationItem = new LocationItem();
                    locationItem.DeviceID = appSettings.getDeviceID();
                    locationItem.Latitude =  Double.toString(location.getLatitude());
                    locationItem.Longitude = Double.toString(location.getLongitude());
                    Date d = new Date();
                    CharSequence timeOfRequest = DateFormat.format("yyyy-MM-dd HH:mm:ss", d.getTime());  
                    locationItem.TimeOfRequest = timeOfRequest.toString();
                    locationItem.SerialNumber = appSettings.getSerialNumber();

                    mLastLocation.set(location);

                    Gson gson = new Gson();
                    String requestObject = gson.toJson(locationItem);
                    Log.d(TAG, "Формирование URL API сервера");
                    String url = appSettings.getIpAddress() + "/api/staff/savedata";
                    makeRequest(url, requestObject, dLocation);
                }
            }
            catch (Exception ex)
            {
                Log.d(TAG, "Ошибка: " + ex.getMessage());
            }
        }

        @Override
        public void onProviderDisabled(String provider)
        {
            Log.e(TAG, "onProviderDisabled: " + provider);
        }

        @Override
        public void onProviderEnabled(String provider)
        {
            Log.e(TAG, "onProviderEnabled: " + provider);
        }

        @Override
        public void onStatusChanged(String provider, int status, Bundle extras)
        {
            Log.e(TAG, "onStatusChanged: " + provider);
        }
    }

    LocationListener[] mLocationListeners = new LocationListener[] {
            new LocationListener(LocationManager.GPS_PROVIDER),
            new LocationListener(LocationManager.NETWORK_PROVIDER)
    };

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

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.e(TAG, "onStartCommand");
        super.onStartCommand(intent, flags, startId);
        return START_STICKY;
    }

    @Override
    public void onCreate()
    {
        context = this;
        Log.e(TAG, "onCreate");
        initializeLocationManager();
        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.NETWORK_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                    mLocationListeners[1]);
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "network provider does not exist, " + ex.getMessage());
        }
        try {
            mLocationManager.requestLocationUpdates(
                    LocationManager.GPS_PROVIDER, LOCATION_INTERVAL, LOCATION_DISTANCE,
                    mLocationListeners[0]);
        } catch (java.lang.SecurityException ex) {
            Log.i(TAG, "fail to request location update, ignore", ex);
        } catch (IllegalArgumentException ex) {
            Log.d(TAG, "gps provider does not exist " + ex.getMessage());
        }
    }

    @Override
    public void onDestroy()
    {
        Log.e(TAG, "onDestroy");
        super.onDestroy();
        if (mLocationManager != null) {
            for (int i = 0; i < mLocationListeners.length; i++) {
                try {
                    mLocationManager.removeUpdates(mLocationListeners[i]);
                } catch (Exception ex) {
                    Log.i(TAG, "fail to remove location listners, ignore", ex);
                }
            }
        }
    }

    private void initializeLocationManager() {
        Log.e(TAG, "initializeLocationManager");
        if (mLocationManager == null) {
            mLocationManager = (LocationManager) getApplicationContext().getSystemService(Context.LOCATION_SERVICE);
        }
    }

    public static double round(double value, int places) {
        if (places < 0) throw new IllegalArgumentException();
        BigDecimal bd = new BigDecimal(value);
        bd = bd.setScale(places, RoundingMode.HALF_UP);
        return bd.doubleValue();
    }

    public void makeRequest(String uri, String json, DLocation dLocation) {
        HandlerThread handlerThread = new HandlerThread("URLConnection");
        handlerThread.start();
        Handler mainHandler = new Handler(handlerThread.getLooper());
        Runnable myRunnable = createRunnable(uri, json, dLocation);
        mainHandler.post(myRunnable);
    }

    private Runnable createRunnable(final String uri, final String data,final DLocation dLocation){

        Runnable aRunnable = new Runnable(){
            public void run(){
                try {   
                    //Connect
                    HttpURLConnection urlConnection;
                    urlConnection = (HttpURLConnection) ((new URL(uri).openConnection()));
                    urlConnection.setDoOutput(true);
                    urlConnection.setRequestProperty("Content-Type", "application/json");
                    urlConnection.setRequestProperty("Accept", "application/json");
                    urlConnection.setRequestMethod("POST");

                    urlConnection.setConnectTimeout(12000);
                    urlConnection.setReadTimeout(10000); 

                    urlConnection.connect();

                    //Write
                    OutputStream outputStream = urlConnection.getOutputStream();
                    BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(outputStream, "UTF-8"));
                    try {
                        writer.write(data);
                    } catch (IOException e) {
                        e.printStackTrace();
                        Log.d(TAG,"Ошибка записи в буфер для пережачи по HTTP");
                    }
                    writer.close();
                    outputStream.close();

                    //Read
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(urlConnection.getInputStream(), "UTF-8"));

                    String line = null;
                    StringBuilder sb = new StringBuilder();

                    while ((line = bufferedReader.readLine()) != null) {
                        sb.append(line);
                    }

                    bufferedReader.close();
                    String result = sb.toString();

                    Log.d(TAG, result);                    

                }
                catch (SocketTimeoutException e){
                    e.printStackTrace();

                    Log.d(TAG, "Ошибка HTTP " + e.getMessage());
                }
                catch( Exception e){
                    e.printStackTrace();
                }
            }
        };

        return aRunnable;

    }

}

解决方案

That's pretty typical behavior from a smartphone/consumer-grade GPS. To reduce the fluctuations you'll need to normalize the results. One approach is to compute the geographic center from a queue of coordinates, for example: https://github.com/Esri/cordova-plugin-advanced-geolocation/blob/master/src/com/esri/cordova/geolocation/utils/GeodataHelper.java#L56

public class Coordinate {
    public double latitude;
    public double longitude;
    public float accuracy;
}

public static Coordinate getGeographicCenter(final ConcurrentLinkedQueue<Coordinate> queue){
    double x = 0;
    double y = 0;
    double z = 0;
    float accuracy = 0;
    int radiusKM = 6367;

    for(final Coordinate coordinate : queue){
        accuracy += coordinate.accuracy;

        // Convert latitude and longitude to radians
        final double latRad = Math.PI * coordinate.latitude / 180;
        final double lonRad = Math.PI * coordinate.longitude / 180;

        // Convert to cartesian coords
        x += radiusKM * Math.cos(latRad) * Math.cos(lonRad);
        y += radiusKM * Math.cos(latRad) * Math.sin(lonRad);
        z += radiusKM * Math.sin(latRad);
    }

    // Get our averages
    final double xAvg = x / queue.size();
    final double yAvg = y / queue.size();
    final double zAvg = z / queue.size();
    final float accuracyAvg = accuracy / queue.size();

    // Convert cartesian back to radians
    final double sphericalLatRads = Math.asin(zAvg / radiusKM);
    final double sphericalLonRads = Math.atan2(yAvg, xAvg);

    // Convert radians back to latitude and longitude
    Coordinate centerPoint = new Coordinate();
    centerPoint.latitude = sphericalLatRads * (180 / Math.PI);
    centerPoint.longitude = sphericalLonRads * (180 / Math.PI);
    centerPoint.accuracy = accuracyAvg;

    return centerPoint;
}

这篇关于LocationManager和跳跃坐标的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆