Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Android: using sharedPreferences in a broadcast receiver

Tags:

android

I'm trying to create an application that will trigger a toast message if the phone receives an SMS containing a string that is stored in the default preferences. My problem is that I'm having trouble getting the toast to appear when the SMS is received. I've tested my code for the receiver with a declared string and it works, but when I use the preference stored one, it doesn't come up. Here is my sample code:

public class Main extends Activity{
private static final int RESULT_SETTINGS = 1;


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

@Override
public boolean onCreateOptionsMenu(Menu menu) {
    getMenuInflater().inflate(R.menu.main, menu);
    return true;
}

@Override
public boolean onOptionsItemSelected(MenuItem item) {
    switch (item.getItemId()) {
        case R.id.action_settings:
            Intent i = new Intent(this, Settings.class);
            startActivityForResult(i, RESULT_SETTINGS);
            break;
    }
    return true;
}

@Override
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
    super.onActivityResult(requestCode, resultCode, data);
    switch (requestCode) {
        case RESULT_SETTINGS: display(); break;
    }
}

private void display(){
    TextView displayv = (TextView) findViewById(R.id.mysettings);
    SharedPreferences sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
    // codes that display
}

And here is the receiver

public class WakeSMS extends BroadcastReceiver{

@Override
public void onReceive(Context context, Intent intent){
    SharedPreferences sharedPrefs = context.getSharedPreferences("sharedPrefs", context.MODE_PRIVATE);
    String trigger=sharedPrefs.getString("smsstr","NULL");

    Bundle bundle = intent.getExtras();
    SmsMessage[] msgs = null;
    String str= "SMS from";
    if(bundle != null){
        Object[] pdus =(Object[])bundle.get("pdus");
        msgs=new SmsMessage[pdus.length];
        for (int i = 0; i<msgs.length; i++){
            msgs[i] = SmsMessage.createFromPdu((byte[])pdus[i]);
            if(i==0){
                str+= msgs[i].getOriginatingAddress();
                str+=": ";
            }
            str+=msgs[i].getMessageBody().toString();
        }
        if(str.contains(trigger)){
            Toast.makeText(context, str, Toast.LENGTH_LONG).show();
        }
    }
}}

In my main activity, I can get my code to display the prefs but in the receiver it fails to trigger the toast. Is there anything I'm doing wrong? (My receiver is called WakeSMS because It's supposed to trigger an alarm in the future, but right now I just want it to trigger a toast for testing)

Edit: I have a feeling that the way I've declared my preferences in my code is perhaps off, but I'm at a loss trying to figure out what I'm doing wrong since the preferences' values can be displayed in the main activity, but cannot be used in the receiver.

like image 313
Work in Progress Avatar asked Feb 16 '23 09:02

Work in Progress


1 Answers

getDefaultSharedPreferences() returns you a SharedPreferences file with the name based on the app package. It is like saying

context.getSharedPreferences("com.your.package_preferences", context.MODE_PRIVATE);

Then in your receiver you say

context.getSharedPreferences("sharedPrefs", context.MODE_PRIVATE);

which gets you shared preferences with a different name.

Therefore you are saving to one SharedPreference file but attempting to retrieve from another.

Try using

getSharedPreferences("MySmsSharedPrefs", context.MODE_PRIVATE);

in both save and restore. i.e in the Acvtivity and the Receiver


Here is the sauce to confirm: https://android.googlesource.com/platform/frameworks/base/+/refs/heads/master/core/java/android/preference/PreferenceManager.java

**
 * Gets a SharedPreferences instance that points to the default file that is
 * used by the preference framework in the given context.
 * 
 * @param context The context of the preferences whose values are wanted.
 * @return A SharedPreferences instance that can be used to retrieve and
 *         listen to values of the preferences.
 */
public static SharedPreferences getDefaultSharedPreferences(Context context) {
    return context.getSharedPreferences(getDefaultSharedPreferencesName(context),
            getDefaultSharedPreferencesMode());
}

private static String getDefaultSharedPreferencesName(Context context) {
    return context.getPackageName() + "_preferences";
}
like image 50
Blundell Avatar answered Feb 23 '23 02:02

Blundell