0

Long story short, I have a class that handles my app shared preferences. I call it from various other classes without issues, but when I try to call it from my service (from the same APK) I get a null exception. I am guessing that it's getting called from the wrong context or something like that. Here is the relevant code.

MainActivity.java

package com.deskwizard.audiomanager;

import android.app.FragmentManager;
import android.app.FragmentTransaction;
import android.content.Context;
import android.os.Bundle;
import android.support.v4.app.FragmentActivity;

import com.deskwizard.audiomanager.DataSaveRestore;

public class MainActivity extends FragmentActivity {

    public static Context contextOfApplication;

    final FragmentManager fm = getFragmentManager();

    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        contextOfApplication = getApplicationContext();

        FragmentTransaction ft = fm.beginTransaction();
        ft.replace(R.id.fragment_settings, new FadeBalanceFragment());
        ft.commit();

        // TODO: Load previously saved settings for all values
        DataSaveRestore.restore_all();
        // TODO: init I2C
    }

    public static Context getContextOfApplication() {
        return contextOfApplication;
    }
}

DataSaveRestore.java (defaultpreferences class)

package com.deskwizard.audiomanager;

import android.app.Application;
import android.content.Context;
import android.content.SharedPreferences;
import android.preference.PreferenceManager;
import android.util.Log;

public class DataSaveRestore extends Application {

    // Data variables
    public static int Bass_level, Bass_CFreq, Bass_Qfact, Sub_level,
            Sub_Lowpass, Treble_level, Treble_CFreq, Mid_level, Mid_CFreq,
            Mid_Qfact, Fade, Balance, Loudness_level, Loudness_freq,
            Loudness_boost;

    static boolean Bass_DCMode, Loudness_state;

    static Context applicationContext = MainActivity.getContextOfApplication();

    public static void restore_all() {

        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(applicationContext);

        if (prefs.getInt("data_saved", 0) == 0) {
            set_defaults();
            load_defaults();
        } else {
            load_defaults();
        }
        //TODO: send settings to TDA7418
        DS3903.set_lowpass(DataSaveRestore.Sub_Lowpass);
    };

Service code snippet:

public class AudioManagerService extends Service {

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // TODO do something useful
        Log.d("com.deskwizard.audiomanager", "starting service...");

        DataSaveRestore.restore_all(); // restore settings to TDA7418/DS3903
        start();
        return Service.START_STICKY;
    }

The Null Exception error refers to this line, only when called from the service, it works properly from the main application and other classes:

    SharedPreferences prefs = PreferenceManager
            .getDefaultSharedPreferences(applicationContext);

Let me know if any further code can help narrow it down. Thanks, DW

1 Answers1

0

Because, In your service when you call, DataSaveRestore.restore_all(); It make reference on, (As there is no MainActivity context available from Servce)

static Context applicationContext = MainActivity.getContextOfApplication();

on this line, applicationContext will be null as it can't find MainActivity initialization

Simply, Just change your restore_all() method from Application class.

First remove static and and use getApplicationContext() of Android application class method to get application context as in Service,

public void restore_all() {

    SharedPreferences prefs = PreferenceManager
            .getDefaultSharedPreferences(getApplicationContext());

    if (prefs.getInt("data_saved", 0) == 0) {
        set_defaults();
        load_defaults();
    } else {
        load_defaults();
    }
    //TODO: send settings to TDA7418
    DS3903.set_lowpass(DataSaveRestore.Sub_Lowpass);
};

Now call, restore_all(); by initializing object of Application class not a static way.

Like,

DataSaveRestore  dataSaveRestore  = (DataSaveRestore) getApplicationContext();

dataSaveRestore.restore_all();
user370305
  • 103,719
  • 23
  • 157
  • 149
  • I tried your way and I am getting this error now calling it from MainActivity.java, 03-02 14:47:15.720: E/AndroidRuntime(5161): Caused by: java.lang.ClassCastException: android.app.Application cannot be cast to com.deskwizard.audiomanager.DataSaveRestore – Deskwizard Mar 02 '15 at 19:53
  • As your `DataSaveRestore ` class xtend Application, put entry in AndroidManifestFile with name `DataSaveRestore ` for Application tag. – user370305 Mar 02 '15 at 20:31
  • @Deskwizard - Look at http://stackoverflow.com/questions/2929562/register-application-class-in-manifest for how to register your class as Application class, then it works very well. – user370305 Mar 02 '15 at 20:34
  • here is the line I used in my classes, it has to be AFTER the onCreate: 'final DataSaveRestore dataSaveRestore = (DataSaveRestore) getActivity().getApplicationContext();' .... Thank you, its working now! you made my day. Too bad I can't upvote your comments. – Deskwizard Mar 02 '15 at 21:42