Question

I have some shared preferences (latitude, longitude) that I want to access from a service, that is not subclassed from Activity.

In particular, when I try to access getPreferences, this function doesn't exist's on a service. My code is posted below

My goal here is to allow WRITE these shared preferences with my service. Any suggestions/examples that can help me along?

public class MyService extends Service implements Runnable {

    LocationManager mLocationManager;
    Location mLocation;
    MyLocationListener mLocationListener;
    Location currentLocation = null;
    static SharedPreferences settings;
    static SharedPreferences.Editor configEditor;

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

    public void onCreate() {
        settings = this.getPreferences(MODE_WORLD_WRITEABLE);
        configEditor = settings.edit();
        writeSignalGPS();
    }

    private void setCurrentLocation(Location loc) {
        currentLocation = loc;
    }

    private void writeSignalGPS() {
        Thread thread = new Thread(this);
        thread.start();
    }

    @Override
    public void run() {
        mLocationManager = (LocationManager)getSystemService(Context.LOCATION_SERVICE);
        if (mLocationManager.isProviderEnabled(LocationManager.GPS_PROVIDER)) {
            Looper.prepare();
            mLocationListener = new MyLocationListener();
            mLocationManager.requestLocationUpdates(
            LocationManager.GPS_PROVIDER, 1000, 0, mLocationListener);
            Looper.loop();
            //Looper.myLooper().quit();
        } else {
            Toast.makeText(getBaseContext(),
              getResources().getString(R.string.gps_signal_not_found),
              Toast.LENGTH_LONG).show();
        }
    }

    private Handler handler = new Handler() {
        @Override
        public void handleMessage(Message msg) {
            if (currentLocation!=null) {
                configEditor.putString("mylatitude", ""+currentLocation.getLatitude());
                configEditor.putString("mylongitude", ""+currentLocation.getLongitude());
                configEditor.commit();
            }
        }
    };

    private class MyLocationListener implements LocationListener {
        @Override
        public void onLocationChanged(Location loc) {
            if (loc != null) {
                Toast.makeText(getBaseContext(),
                getResources().getString(R.string.gps_signal_found),
                  Toast.LENGTH_LONG).show();
                setCurrentLocation(loc);
                handler.sendEmptyMessage(0);
            }
        }

    @Override
    public void onProviderDisabled(String provider) {}

    @Override
    public void onProviderEnabled(String provider) {}

    @Override
    public void onStatusChanged(String provider, int status, Bundle extras) {}
}

I get the error on the line settings = this.getPreferences(MODE_WORLD_WRITEABLE);

Was it helpful?

Solution

If you are only using one SharedPreferences for your application, have all your code get it via PreferenceManager.getDefaultSharedPreferences().

OTHER TIPS

Actually, most of you might be running into the problem, that on devices with API >=11, the shared preferences are not set for multi process use by default anymore.

Solution:

if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB) {
    prefs = getSharedPreferences(PREFS, 0 | Context.MODE_MULTI_PROCESS);
} else {
    prefs = getSharedPreferences(PREFS, 0);
}

Little late to help you out on this, but I hope this helps someone in the future. Here is your problem:

    public void onCreate() {
       settings = this.getPreferences(MODE_WORLD_WRITEABLE);
       configEditor = settings.edit();
       writeSignalGPS();
    }

Since you only retrieve the Shared Preference file when the service is created, the file is never properly updated by the service and thus the data is never shared with the application. Before writing to Shared Preferences or retrieving any data that may have changed, make sure to retrieve the Shared Preference file (reload) again such as:

    private Handler handler = new Handler() {
    @Override
    public void handleMessage(Message msg) {
        if (currentLocation!=null) {
            settings = this.getPreferences(MODE_WORLD_WRITEABLE);
            configEditor = settings.edit();
            configEditor.putString("mylatitude", ""+currentLocation.getLatitude());
            configEditor.putString("mylongitude", ""+currentLocation.getLongitude());
            configEditor.commit();
        }
    }

then in your application:

     settings = this.getPreferences(MODE_WORLD_WRITEABLE);
     String myLat = setttings.getString("mylatitude","");

Also, anything on Android 3.0 that has a scenario where a service and an activity share Shared Prefs, you should use:

     settings = this.getPreferences(MODE_MULTI_PROCESS);

If you have declared SharedPreferences as:

private static final String PREFS_NAME = "UserData"; 
private static final String PREFS_VALUE1 = "value1"; 

then use the below code to fetch values:

SharedPreferences preferences = context.getSharedPreferences(PREFS_NAME, Context.MODE_PRIVATE);
value1 = preferences.getString(PREFS_VALUE1, "0");

In same way you can even save values to SharedPreferences.

For people who bump into this ... I had a similar problem ... The true cause of the problem is we are trying to get/use a context that is not fully initialized .. I was able to use sharedPreferences normally outside of my constructor for my IntentService.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top