Android:在广播接收器中使用SharedPreferences

4

我正在尝试创建一个应用程序,如果手机接收到包含在默认偏好设置中存储的字符串的短信,将触发toast消息。我的问题是,当接收到短信时,我无法让toast出现。我已经使用声明的字符串测试了接收器的代码,并且它可以运行,但是当我使用存储在偏好设置中的字符串时,它就不能正常工作。以下是我的示例代码:

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
}

这里是接收器

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();
        }
    }
}}

在我的主活动中,我可以让我的代码显示首选项,但在接收器中无法触发toast。我做错了什么吗?(我的接收器被称为WakeSMS,因为它应该在未来触发闹钟,但现在我只想要它触发一个测试用的toast)
编辑:我有一种感觉,我在代码中声明首选项的方式可能有误,但我正在努力找出我做错了什么,因为首选项的值可以在主活动中显示,但无法在接收器中使用。

是的,这就是它应该做的。用户可以设置应用程序首选项之一是触发器(可以是单词或短语),应该触发toast。在上面的接收器代码中,我已经设置为使用用户在应用程序首选项中定义的任何内容,但它不起作用。如果我注释sharedPrefs和trigger的声明,然后将最后一个if中的trigger替换为任何字符串,例如“money”,那么如果我收到带有“money”单词的短信,我就可以让toast显示出来。 - Work in Progress
我使用一个辅助类从共享首选项中获取字符串,之后我只需实例化此帮助类并调用其getter方法即可从共享首选项获取字符串。这对我总是有效的,事实上我必须检查在我的应用程序中收到的消息中的几个单词。 - Rachit Mishra
我之前没有想过使用辅助类,但我认为辅助类是一个很好的替代方案。然而,每次我的应用程序扩展(这只是应用程序的一个功能)时必须设置getter和setter可能会成为一个问题。我希望有人可以帮助我找出代码中的问题或更好的完成任务的方法,这将非常有帮助。顺便说一句,感谢您的意见! - Work in Progress
这是我的辅助类,http://hastebin.com/duliluyoji.avrasm,请查看它是否有效,并进行一些更改。 - Rachit Mishra
我尝试使用辅助类,但每当收到短信并调用接收器时,我的应用程序就会强制关闭。 - Work in Progress
显示剩余2条评论
1个回答

9

getDefaultSharedPreferences() 方法返回一个基于应用程序包名称的 SharedPreferences 文件。可以将其理解为:

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

然后在您的接收器中,您需要这样说:

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

这段代码可以让你使用不同的名称获取共享首选项。

因此,您正在保存到一个SharedPreference文件中,但尝试从另一个文件中检索。

尝试使用以下方法:

getSharedPreferences("MySmsSharedPrefs", context.MODE_PRIVATE);

在保存和恢复时都要进行,即在Activity和接收器中。以下是确认的方法: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";
}

我认为这是最好的答案! - Rachit Mishra
我已经让它工作了。非常感谢!我想我遇到的问题在接收器中,我调用了错误的首选项。我不知道在getSharedPreferences的第一个字段中可以使用包名称和_preferences。 - Work in Progress
我曾经遇到过类似的问题。当我尝试从onReceive中获取值时,它会给我不同的值,所以我尝试将其保存在片段中。但这个解决方案对我仍然没有用。后来我找到了一个不同的答案,它提出了使用MODE_MULTI_PROCESS而不是MODE_PRIVATE的想法。那个方法非常有效。以下是那个答案。 https://stackoverflow.com/a/10551235/7099939 - M Shaban Ali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接