【问题标题】:Where to save Android GPS (Latitude , Longitude) points?在哪里保存 Android GPS(纬度,经度)点?
【发布时间】:2010-08-30 22:58:10
【问题描述】:

在 onLocationChanged 事件中,我想保存我的 GPS 路线(纬度、经度)。稍后我想加载这些数据并绘制路线。

谁是最好的方法,通过使用某种数组类型(并使用数据库保存或加载)或 XML 文件或其他方式?

谢谢。

【问题讨论】:

    标签: android gps


    【解决方案1】:

    在 SharedPreferences 中存储双精度值而不损失精度的最佳方法是:

    • 转换为位表示以将其存储为长:

      prefsEditor.putLong("Latitude", Double.doubleToLongBits(location.getLatitude()));
      
    • 要检索,从位表示转换为双精度:

      double latitude = Double.longBitsToDouble(prefs.getLong("Latitude", 0);
      

    但是,我认为如果您想存储大量点,则使用 SQLite 数据库比将每个坐标保存在 SharedPreferences 中的键值对中或在 XML 中序列化数组并将其写入文件或写入文件要好共享首选项。该数据库为您提供了仅将您在地图中显示的区域内的点加载到内存中的优势,因此您可以节省内存。

    【讨论】:

    • 这是正确答案,接受的答案会丢失精度,因此没有存储正确的值。
    【解决方案2】:

    如果我错了,请纠正我,但最好将双精度值转换为字符串,然后在调用它们时将它们转换回双精度值。听起来很痛苦,但 oracle 的网站 (http://download.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html) 说:

    “如果您需要在大型浮点数数组中节省内存,请使用浮点数(而不是双精度数)。这种数据类型不应该用于精确值,例如货币”

    prefEditor.putString("Latitude", Double.valueOf(loc.getLatitude()).toString());
    

    然后,调用值

    String latitudeString = pref.getString("Latitude", "0");
    double latitude = Double.parseDouble(latitudeString);
    

    这似乎更令人讨厌,但似乎也更有可能返回您保存的确切值,而不是稍微偏离。我想这取决于你需要的值有多准确。

    不过,就使用数组而言,我一无所知,因为我从来不需要使用它们,也没有使用它们的经验。

    【讨论】:

    • 很明显,为什么从浮点数到加倍你会失去“精度”-> 准确性
    • 这确实很有意义,例如,如果你从某个坐标获取地址字符串,然后将坐标保存为浮点数,然后再次获取地址 - 你会得到完全不同的字符串。用户会想知道为什么。
    • 默认值必须是字符串,请更正pref.getString("Latitude", 0);到 pref.getString("纬度", "0"); (不能自己做,编辑必须至少 6 个字符)
    • @TilmanHausher 谢谢。当我没有 Eclipse 对我抱怨时,我会想念这些东西。
    【解决方案3】:

    使用 SharedPreferences 和编辑器。

    看看这个开源代码,它可能会对你有很大帮助: OsmandSettings.java

    我将解释代码的重要部分:

    import android.content.SharedPreferences;
    import android.content.SharedPreferences.Editor;
    
    // These settings are stored in SharedPreferences, replace com.osmand.settings 
    // with your own package name, or whatever String you want.
    public static final String SHARED_PREFERENCES_NAME = "com.osmand.settings";
    public static final String LATITUDE = "latitude";
    public static final String LONGITUDE = "longitude";
    

    要写入 SharedPreferences:

    public void onLocationChanged(Location location){
        SharedPreferences prefs = Context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
        Editor editor = prefs.edit();
        //Save it as a float since SharedPreferences can't deal with doubles
        edit.putFloat(LATITUDE, (float) Location.getLatitude());
        edit.putFloat(LONGITUDE, (float) Location.getLongitude());
        edit.commit();
    }
    

    从 SharedPreferences 中读取:

    public void onLocationChanged(Location location){
        SharedPreferences prefs = Context.getSharedPreferences(SHARED_PREFERENCES_NAME, Context.MODE_WORLD_READABLE);
        double lat = (double)prefs.getFloat(LATITUDE, 0);
        double lon = (double)prefs.getFloat(LONGITUDE, 0);
    }
    

    【讨论】:

    • 这只会存储最后一个位置。只需将它们存储在 ArrayList 或其他东西中
    • 每个 oracle This data type [float] should never be used for precise values, such as currency。因此,如果您想检索相同的值(我假设您这样做),则不应将其保存/获取为浮点数,而应保存为 String 或 Long。见my answer
    • 地理坐标不必精确,必须精确。存储为 float、double、int 或 long 都可以。
    【解决方案4】:

    我在 Map 上做应用程序时也遇到了同样的问题。 事实上,我想说的问题很好。

    你可以这样做。

    1> 在地图上单击事件时,您必须显示该点的纬度和经度。 我在这里附上代码,你如何找到经度和经度。

    public boolean onTouchEvent(MotionEvent event, MapView mapView) 
            {   
                //---when user lifts his finger---
                if (event.getAction() == 1) {                
                    GeoPoint p = mapView.getProjection().fromPixels(
                        (int) event.getX(),
                        (int) event.getY());
                        Toast.makeText(getBaseContext(), 
                            p.getLatitudeE6() / 1E6 + "," + 
                            p.getLongitudeE6() /1E6 , 
                            Toast.LENGTH_SHORT).show();
                }                            
                return false;
            }   
    

    2> 现在你可以将这个 lat 和 long 存储在 KEY,value 对中。 在这里,您必须将 value1 设为 lat,将 value 2 设为 long。并传递
    的对象 value(value1,value2) 到键、值对。

    3> 现在你有你通过的所有纬度和经度的列表。 然后绘制从第一个索引到最后一个索引的路线。

    这是我认为实现这个应用程序的最佳方式。

    【讨论】:

      【解决方案5】:

      考虑您表示数据所需的精度(而非准确度)。几英寸就够近了吗?大多数手持 GPS 接收器很幸运能达到几米。赤道经度 1 度秒会使您移动约 100 英尺。如果您使用带符号的 32 位整数来表示纬度和经度,LatE6 和 LonE6,您可以将最大经度存储为 +/-180,000,000,而最低有效数字为:

      (1 / 1E6) * (3600 秒/度) * (100 英尺/秒) = 0.36 英尺或 4 英寸。

      我必须想象我的 Garmin 使用的是这样的东西,而不是只有 24 位精度的浮点数,当然也不是 64 位双精度数。整数和双精度之间的转换不应该花费太多。您甚至可以将 lat/lon 对打包成 long。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2012-07-23
        • 1970-01-01
        相关资源
        最近更新 更多