0

I have the following code derived from Service which I want to run as a service, in the background. In this class, I use a SharedPreferences.OnSharedPreferenceChangeListener class to check if a shared preference has change, in order to reinitialize a BroadcastReceiver to be run at some defined time intervals (like every 6 hours). But when I change the explicit shared preference in my main activity to 3 hours, for example, I need the code to be run in 3 hours (instead of 6 hours). Here is the code for the Service:

public class AlarmService extends Service
{
    public Alarm alarm = new Alarm();
    public SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);

    public void onCreate()
    {
        super.onCreate();
        SharedPreferences.OnSharedPreferenceChangeListener spChanged = new
            SharedPreferences.OnSharedPreferenceChangeListener() {
                @Override
                public void onSharedPreferenceChanged(SharedPreferences sharedPreferences,
                                                      String key) {                       
                    // reinitialize the alarm
                    alarm.SetAlarm(this); // ERROR HERE
                }
        };
        //SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
        sharedPref.registerOnSharedPreferenceChangeListener(spChanged);
    }

    @Override
    public int onStartCommand(Intent intent, int flags, int startId)
    {
        Log.d("!~!", "Service started.");
        alarm.SetAlarm(this);
        return START_STICKY;
    }


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

The method SetAlarm is defined in a class derived from BroadcastReceiver and is implemented as follows:

 public void SetAlarm(Context context)
    {
        // get the update cylce from the prefences
        SharedPreferences sharedPref = PreferenceManager.getDefaultSharedPreferences(context);
        int updateInterval = Integer.parseInt(sharedPref.getString("updateInterval", "24"));
        Log.d(LOGHEAD, String.format("Alarm set to update every %d hours.", updateInterval));


        AlarmManager am = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
        Intent intent = new Intent(context, Alarm.class);
        PendingIntent pi = PendingIntent.getBroadcast(context, 0, intent, 0);
        am.setRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), 1000 * 60 * updateInterval, pi); // Millisec * Second * Minute
    }

But when I compile the code, I get the following error:

Error:(33, 26) error: method SetAlarm in class Alarm cannot be applied to given types;
required: Context
found: <anonymous OnSharedPreferenceChangeListener>
reason: actual argument <anonymous OnSharedPreferenceChangeListener> cannot be converted to Context by method invocation conversion

The place at the error's occurrence is marked above. Once more I get an error related to the 'context', a concept, I am still failing to understand...

I am especially puzzled by the fact, that futher below on the code the call

alarm.SetAlarm(this);

is working fine. Maybe the issue is because of the use of an inner class?

Any ideas how to fix this? Or fix the whole code? I have put together the code from examples and I am not sure if this is good android code...

Alex
  • 41,580
  • 88
  • 260
  • 469

2 Answers2

0

In that particular context this does refer to the OnSharedPreferenceChangeListener as shown in the error message.

Replace this with AlarmService.this to reference the outer service instance and things should work.

Based on you comment you also need to initialize the preferences inside of onCreate().

First only declare the preferences

private SharedPreferences sharedPref;

and then inside onCreate() do

sharedPref = PreferenceManager.getDefaultSharedPreferences(this);
George Mulligan
  • 11,813
  • 6
  • 37
  • 50
  • Updated the answer to address your other issue too. – George Mulligan Mar 30 '16 at 18:37
  • I see. Also something to be aware of that you might run into is the behavior described [here](http://stackoverflow.com/a/3104265/1435985) about registering a `OnSharedPreferenceChangeListener` without keeping a strong reference to it. – George Mulligan Mar 30 '16 at 18:45
0

Inside a listener this refers to the OnSharedPreferenceChangeListener object which does not extend the Context class. You need to pass a valid Context object to your setAlarm method.
However when you call setAlarm in the onStartCommand, this represents your AlarmService object.

For further reference - read the Oracle documentation

Dmitri Timofti
  • 2,428
  • 1
  • 22
  • 25