0

I have been searching for an answer for at least a week and I still can't get a straight answer that will fix the issue I have with my code. I'm fairly new to android development so I assume there is some deeper level understanding that I am missing.

I am developing an app that gets data from the internet so i tried to implement safeguards to prevent the app from crashing and ruining the user experience while there is no service.

I did this is using a onSharedPreferenceChanged. I created an activity that is called when there is no service (I test this using Airplane mode) and other reasons such as wifi connection and user selected preferences for using wifi only to download data.

Now, it worked a few times and stopped working and I can't figure out why. I looked at Stack OverFLow for a few days and I ran into a wall. I was led to this question: Different approaches to a Listener when I asked my own question. This question is different because that question was asking for a specific answer to why my code doesn't work. I also used the android studio documentation but it was outdated.

I don't want to keep asking questions about my code because I use the SharedPreferences.OnSharedPreferenceChangeListener in several activities so I just want to ask, How exactly does it work?

I know that it uses a WeakHashMap which gets garbage collected often, but I thought implementing it would solve the issue. But it didn't for some reason, the sharedPreferences values change but the listener doesn't get called.

Other than researching the question, I wrote a separate app to test just how onSharedPreferenceChanged works and it worked. This iteration of the code doesn't work though.

public class MainActivity extends AppCompatActivity implements SharedPreferences.OnSharedPreferenceChangeListener{
static final String TAG = "MainActivity";
public static final String SHARED_PREFS = "sharedPrefs";
public static final String WIFI_CONNECTION = "WiFi";
public static final String CELLULAR_CONNECTION = "Cellular";
public static final String CONNECTION = "Connection";

private NetworkCheck networkCheck;
SharedPreferences sharedPreferences;


boolean wifi;
boolean cellular;
boolean connected;

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

    wifiT = findViewById(R.id.wifi);
    cellularT = findViewById(R.id.mobile);
    connectedT = findViewById(R.id.connected);




    sharedPreferences = getSharedPreferences(SHARED_PREFS, MODE_PRIVATE);
    wifi = sharedPreferences.getBoolean(WIFI_CONNECTION, false);
    cellular = sharedPreferences.getBoolean(CELLULAR_CONNECTION, false);
    connected = sharedPreferences.getBoolean(CONNECTION, false);

 public void onSharedPreferenceChanged(SharedPreferences sharedPreferences, String key) {
    switch (key){
        case CONNECTION:
            connected = sharedPreferences.getBoolean(CONNECTION, false);
            Log.i(TAG, "sharedStuff In: connection: " + wifi + " cellular: "
                    + cellular + " connected: " + connected);
            setStuff();
            break;
        case WIFI_CONNECTION:
            wifi = sharedPreferences.getBoolean(WIFI_CONNECTION, false);
            Log.i(TAG, "sharedStuff In: wifi: " + wifi + " cellular: " +
                    cellular + " connected: " + connected);
            setStuff();

            break;
        case CELLULAR_CONNECTION:
            cellular = sharedPreferences.getBoolean(CELLULAR_CONNECTION, false);
            Log.i(TAG, "sharedStuff In: cellular: " + wifi + " cellular: " +
                    cellular + " connected: " + connected);
            setStuff();
            break;
        default:
            connected = sharedPreferences.getBoolean(CONNECTION, false);
            Log.i(TAG, "sharedStuff In: default: " + wifi + " cellular: " +
                    cellular + " connected: " + connected);
    }
    Log.i(TAG, "sharedStuff Out: listener: " + wifi + " cellular: " +
            cellular + " connected: " + connected);

}

 void setStuff() {
    if(wifi)
        wifiT.setText("WIfi Is Connected");
    else
        wifiT.setText("WIfi Is Not Connected");
    if(cellular)
        cellularT.setText("Cellular Is Connected");
    else
        cellularT.setText("Cellular Is Not Connected");
    if (connected)
        connectedT.setText("Network Is Connected");
    else
        connectedT.setText("Network Is Not Connected");
}
 @Override
protected void onStart() {
    super.onStart();
    IntentFilter filter = new IntentFilter();
    filter.addAction("android.net.conn.CONNECTIVITY_CHANGE");
    filter.addAction(WifiManager.WIFI_STATE_CHANGED_ACTION);
    this.registerReceiver(networkCheck, filter);
    PreferenceManager.getDefaultSharedPreferences(this)
            .registerOnSharedPreferenceChangeListener(this);

}



@Override
protected void onStop() {
    super.onStop();
    if (networkCheck != null) {
        this.unregisterReceiver(networkCheck);
        PreferenceManager.getDefaultSharedPreferences(this)
                .unregisterOnSharedPreferenceChangeListener(this);
    }
}

The preferences are loaded from another activity that uses `ConnectivityManager'. I've tested it extensively and it works every time so far.

I want my app to "see" that service has changed on the user's phone and act accordingly. For example, i have the app opening, and if there is no service, it will not ask for data from google and facebook until there is service and if there is no wifi service and the user specifically wants to only use wifi, the user will be notified about that their choice is being implemented.

This is why my question is more of a conceptual question than a "why isn't my code working" question. I thought I understood how it worked, but it doesn't work I must be wrong.

DJ. Aduvanchik
  • 332
  • 5
  • 17
  • 1
    I don't want this to come off as dismissive of your question, but a nice thing about Android is that it's open source. So a question of the nature of "How does X class in Android work?" can be answered by looking at the source code itself. – dominicoder Aug 25 '19 at 21:47
  • @dominicoder That's not dismissive. I'm new so I think myself into a corner sometimes. I need a new Avenue to run in. It is so weird when code works then just stops out of nowhere. On other reason I asked the question is because sometimes when I search on this site, I see amazing answers to simple questions, but not this question, so I figured I'd give someone an opportunity. By source code, do you mean opening the base class within Android Studio, or where else can I Look? – DJ. Aduvanchik Aug 25 '19 at 22:39
  • 1
    Yes, if you have the source for the current API level downloaded (from the SDK manager) you should be able to just click on registerOnSharedPreferenceChangeListener and jump to its implementation - then go down the rabbit hole from there. – dominicoder Aug 27 '19 at 06:06
  • @dominicoder, thank you. I was wondering if that was legal or not since they had a warning attached. But that's good to know. – DJ. Aduvanchik Aug 27 '19 at 13:32

1 Answers1

0

So I think I understand what I have been missing while using SharedPreferences. I wanted SharedPreferences.OnSharedPreferenceChangeListener to catch every single time a change occurred, but that's not how this works. The listener is more adept at listening for long term changes, such as a preference change, and not a constantly updating value.

What I ended up doing was adding a BroadcastReceiver into every Activity that would need to listen for a change and it made the app run much more smoothly. This realization came after I remembered reading the in Android, the best results come when Activities can run almost completely independently of each other as standalone program.

As far as how SharedPreferences works, it's pretty straight forward as the documentation says. The developer can add different types of data into the editor of SharedPreferences and call it in another app at will, and the listener looks for changes but it doesn't like constant changes and can ignore them.

DJ. Aduvanchik
  • 332
  • 5
  • 17