4

I would like to store a Location object and i'm trying to pick a good way to do it. Please give me advice that how to do this

I'm using this code but when i get the location from Preferences then Location return like this...

Location[mProvider=STORAGE,mTime=0,mLatitude=30.0,mLongitude=76.0,mHasAltitude=false,mAltitude=0.0,mHasSpeed=false,mSpeed=0.0,mHasBearing=false,mBearing=0.0,mHasAccuracy=false,mAccuracy=0.0,mExtras=null]

/** Store Location object in SharedPreferences */
public void storeLocation(Context context, Location location) {
    SharedPreferences settings;
    Editor editor;
    try {
        JSONObject locationJson = new JSONObject();
        locationJson.put(LATITUDE, location.getLatitude());
        locationJson.put(LONGITUDE, location.getLongitude());

        settings = context.getSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE);
        editor = settings.edit();

        editor.putString(KEY_LOCATION, locationJson.toString());
        editor.commit();
        Log.i("location_util_store", "Location" + location);
    } catch (Exception e) {
        e.printStackTrace();
    }
}

/** Retrieve Location object from SharedPreferences
 * @return */
public Location getPrevLocation(Context context) {

    SharedPreferences settings;
    try {
        settings = context.getSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE);
        String jsonLocation = settings.getString(KEY_LOCATION, null);
        if (jsonLocation != null) {

            JSONObject locationJson = new JSONObject(jsonLocation);
            Location location = new Location("STORAGE");
            location.setLatitude(locationJson.getInt(LATITUDE));
            location.setLongitude(locationJson.getInt(LONGITUDE));
            Log.i("location_util_get", "Location" + location);
            return location;
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
    return null;
}
Reyaj
  • 135
  • 1
  • 7

4 Answers4

8

Best Solution: Extract location lat & long parameters as string and save them in prefs. You can extract other information as well from location depending upon your usecase.

Saving a location:-

        if (location == null) {
            sharedPreferences.edit().removeKey("LOCATION_LAT").apply();
            sharedPreferences.edit().removeKey("LOCATION_LON").apply();
            sharedPreferences.edit().removeKey("LOCATION_PROVIDER").apply();
        } else {
            sharedPreferences.edit().putString("LOCATION_LAT", String.valueOf(location.getLatitude())).apply();
            sharedPreferences.edit().putString("LOCATION_LON", String.valueOf(location.getLongitude())).apply();
            sharedPreferences.edit().putString("LOCATION_PROVIDER", location.getProvider()).apply();
        }

Retreiving a location:-

        String lat = sharedPreferences.getString("LOCATION_LAT", null);
        String lon = sharedPreferences.getString("LOCATION_LON", null);
        Location location = null;
        if (lat != null && lon != null) {
            String provider = sharedPreferences.getString("LOCATION_PROVIDER", null);
            location = new Location(provider);
            location.setLatitude(Double.parseDouble(lat));
            location.setLongitude(Double.parseDouble(lon));
        }
        return location;

Bad Solution: Use Gson to persist your Location instead:

Saving a Location:

String json = location == null ? null : new Gson().toJson(location);
sharedPreferences.edit().putString("Location", json).apply();

Retrieving a Location:

String json = sharedPreferences.getString("location", null);
return json == null ? null : new Gson().fromJson(json, Location.class);

As mentioned in this answer.

This shouldn't crash but it crashes on some devices. As mentioned here.

maveroid
  • 1,840
  • 1
  • 20
  • 20
  • 1
    @ArthurMelo Gson method works but app crashes on some devices as mentioned in "App crashes (sometimes) with Fatal signal 11 (SIGSEGV), code 1" http://stackoverflow.com/questions/37101603/app-crashes-sometimes-with-fatal-signal-11-sigsegv-code-1/37279407#37279407 – maveroid Dec 07 '16 at 06:20
  • Don't use this approach, https://stackoverflow.com/questions/44090552/application-crash-libc-fatal-signal-11-sigsegv-code-1/47866646#47866646 – Kirill Vashilo Dec 18 '17 at 10:42
  • @KirillVashilo, It is already mentioned that Gson approach doesn't work on some devices. Hence, use plain serialization as mentioned already in second solution in this answer. – maveroid Dec 19 '17 at 06:24
1

Resolved with this
Store Location Object:

SharedPreferences settings;
    Editor editor;
    try {

        settings = context.getSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE);
        editor = settings.edit();

        Gson gson = new Gson();
        String json = gson.toJson(location);
        editor.putString(KEY_LOCATION, json);
        editor.commit();

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

Retrieve Location object

SharedPreferences settings;
    try {
        settings = context.getSharedPreferences(PREFS_NAME,Context.MODE_PRIVATE);

        Gson gson = new Gson();
        String json = settings.getString(KEY_LOCATION, "");
        Location obj = gson.fromJson(json, Location.class);

        if (obj != null) {

            return obj;
        }

    } catch (Exception e) {
        e.printStackTrace();
    }
Reyaj
  • 135
  • 1
  • 7
  • 6
    This will **appear** to work but you will get native android crashes (with no stacktrace) because Location does not have a default constructor and that causes problems when serialising with Gson. – Lisandro Jun 23 '16 at 15:37
  • Don't use this approach, https://stackoverflow.com/questions/44090552/application-crash-libc-fatal-signal-11-sigsegv-code-1/47866646#47866646 – Kirill Vashilo Dec 18 '17 at 10:42
0

If only Lat Long is important to you then you can use the below answer. The most popular answers are wrong as you can see in the comments

You can use this by calling SharedPreferencesHelper.getInstance(context).setCurrentLocation(location);

public class SharedPreferencesHelper {
    private static SharedPreferencesHelper sharedPreferencesHelper;
    private static SharedPreferences pref;
    private String CURRENT_LOCATION_LAT = "CURRENT_LOCATION_LAT";
    private String CURRENT_LOCATION_LONG = "CURRENT_LOCATION_LONG";

    public static SharedPreferencesHelper getInstance(Context context) {
        if (null == sharedPreferencesHelper) {
            pref = PreferenceManager.getDefaultSharedPreferences(context);
            sharedPreferencesHelper = new SharedPreferencesHelper();
        }
        return sharedPreferencesHelper;
    }

    public Location getCurrentLocation() {
        Location location = new Location("");//provider name is unnecessary
        location.setLatitude(getDouble(CURRENT_LOCATION_LAT));
        location.setLongitude(getDouble(CURRENT_LOCATION_LONG));
        return location;
    }

    public void setCurrentLocation(Location location) {
        setDouble(CURRENT_LOCATION_LAT, location.getLatitude());
        setDouble(CURRENT_LOCATION_LONG, location.getLongitude());
    }

    private double getDouble(String key) {
        return Double.longBitsToDouble(pref.getLong(key, Double.doubleToLongBits(0)));
    }

    private void setDouble(String key, double val) {
        SharedPreferences.Editor editor = pref.edit();
        editor.putLong(key, Double.doubleToRawLongBits(val));
        editor.commit();
    }

}
David Corrado
  • 363
  • 3
  • 19
0

I needed to save Location with most of it's members as well, not just latitude and longitude. I ended up writing my own Serializable class. See my answer here.

Viktor Brešan
  • 5,293
  • 5
  • 33
  • 36