Search code examples
javaandroidandroid-buttonandroid-preferences

Android Button in preferences changing the MainActivity


I have a Preference Activity where I would like to add a button. If this button is clicked, it should load some data and update the MainActivity.

How can I change stuff in the MainActivity from the PreferenceActivity?

I couldn't figure it out from all the other SO questions, so thank you for pointing me to the solution! :)

My Code

res/xml/preferences.xml

<?xml version="1.0" encoding="utf-8"?>
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android">

    <Preference
        android:key="loadDataButton"
        android:title="Click to update data"
        android:summary="This needs internet connection."
        android:widgetLayout="@layout/load_data_button"
        ></Preference>
</PreferenceScreen>

Edit: res/layout/load_data_button.xml

Probably one might also be able to use the onClick here.

<?xml version="1.0" encoding="utf-8"?>
<Button
    xmlns:android="http://schemas.android.com/apk/res/android"
    android:id="@+id/loadDataButton"
    android:text="Button"
    android:layout_width="wrap_content"
    android:layout_height="wrap_content"
    android:onClick="loadDataButtonClicked">
</Button>

PreferencesActivity.java

I think getting the Toast in here to work would show me how to solve the problem.

import android.os.Bundle;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceFragment;
import android.widget.Toast;

public class PreferencesActivity extends PreferenceActivity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        getFragmentManager().beginTransaction().replace(android.R.id.content, new MyPreferenceFragment()).commit();

    }

    public static class MyPreferenceFragment extends PreferenceFragment
    {
        @Override
        public void onCreate(final Bundle savedInstanceState)
        {
            super.onCreate(savedInstanceState);
            addPreferencesFromResource(R.xml.preferences);

            Preference button = findPreference("loadDataButton");
            button.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
                @Override
                public boolean onPreferenceClick(Preference preference) {

                    // simple code works, but I can't access MainActivity
                    Toast.makeText(getApplicationContext(), "Test which doesn't work.", Toast.LENGTH_SHORT).show();

                    return true;
                }
            });


        }

    }

}

Function I actually want to call on button click

Presumably this function is in MainActivity.java inside the class public class MainActivity extends AppCompatActivity {...}

    public void loadDataButtonClicked(View v) {

        // If permission not given
        if (ContextCompat.checkSelfPermission(getApplicationContext(),
                Manifest.permission.INTERNET) == PackageManager.PERMISSION_DENIED) {
            ActivityCompat.requestPermissions((Activity) getApplicationContext(),
                    new String[] {Manifest.permission.INTERNET},
                    0x2);

        }

        SharedPreferences SP = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
        final String event_key = SP.getString("event_key", "None");

        RequestQueue queue = Volley.newRequestQueue(getApplicationContext());
        String url ="https://www.google.com";

        StringRequest stringRequest = new StringRequest(Request.Method.POST, url,
                new Response.Listener<String>() {/* not important*/};

        queue.add(stringRequest);

    }


Solution

  • It's not possible to show 2 activities at the same time on the screen from the same app. This means the Main Activity can't do work until it's at the top of the stack.

    So, how is the preference activity being called? What triggers the main activity after changing the preference?

    So assuming the user is in the main activity and an intent opens the preference activity you have several ways of doing it.

    You can start the preferenceActivity expecting a result and where the code of the toast is you can load the data (best if it's asynchronous) and after that finish the activity with result.

    Another option is what is in the comments. Make the MainActivity listen to a broadcast in onResume and onPause stop listening. Then the Preference Activity would trigger an asynchronous process and finish itself. The main activity would now be visible, and when the asynchronous process ends then send the broadcast which the main activity would receive. If the asynchronous process can be to fast, then maybe store the information in shared preferences and get the data when MainActivity starts. Or you can also start MainActivity with a flag to go back in the stack and pass an extra parameter that you can get on the method onNewIntent() in the mainActivity and do the work you want.

    But basically, what you need is to search how to pass information from one activity to another activity in the stack.