从广播接收器启动的Activity中无法访问Sharedpreferences

3

(与我刚才发布的其他问题略有不同,如果违反规则,请谅解)

在我的第一个活动中,我正在设置一些共享首选项,然后通过意图启动另一个活动2,并从sharedpreferences设置一些文本视图...这一切都很顺利。

这是我的问题。 在我的第一个活动中,我有一个带有挂起意向的alarmmanger,这个挂起意向是一个广播接收器,用于锁定手机,然后启动activity2。这个活动是上面提到的同一个第二个活动。然而,当从broadcastreceiver启动此活动时,没有任何文本视图从sharedpreferences中加载。这只发生在从broadcastreceiver启动activity2时。

SharedPreference在第一个活动中设置为

SharedPreferences lockPreferences = getSharedPreferences("lockprefs", Context.MODE_PRIVATE);

它们在activity2中的访问方式相同。
SharedPreferences lockPreferences = getSharedPreferences("lockprefs", Context.MODE_PRIVATE);

当从广播接收器启动activity2时,没有加载任何sharedprefs。

broadcastreceiver位于不同的包名中,我将其移动到与活动相同的包中进行测试,但没有任何区别。

这让我发疯了,请帮帮我!谢谢。

编辑:

我有一个GCMIntentService,这是我设置共享偏好的地方(基于从GCM接收到的值)(我只包含相关代码)。

我可以使用getString等方法。

public class GcmIntentService extends IntentService {

public static final String PREFERENCE_NAME = "lockPreference";

  @Override
    protected void onHandleIntent(Intent intent) {

        SharedPreferences lockPreference = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);
        SharedPreferences.Editor lockPrefsEditor;
        lockPrefsEditor = lockPreference.edit();

lockPrefsEditor.putString("newpassword", newpassword);
lockPrefsEditor.commit();

现在如果我启动activity2,共享首选项将被正确读取。 但是,当首先尝试从broadcastreceiver访问时,它不起作用。
这是一个测试接收器:
package com.myapp;

import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.util.Log;
import android.widget.Toast;

public class test extends BroadcastReceiver {


    public static final String TAG = "myapp";
    public static String newpassword = ""; 


 @Override
 public void onReceive(Context context, Intent intent) {


      Log.i(TAG,"test receiver");

      SharedPreferences lockPreference = context.getSharedPreferences(GcmIntentService.PREFERENCE_NAME, Context.MODE_PRIVATE);
      newpassword = lockPreference.getString("newpassword", "");
      Log.i(TAG, "Password from shared prefs: " + newpassword);

      Toast.makeText(context, "Sharedprefs password:" + newpassword, Toast.LENGTH_SHORT).show();


        }
}

这是一个Toast提示:“Sharedprefs密码:”

这是activity2,可以轻松读取偏好设置。

public class Activity2 extends Activity  {


    String newpassword;



    @Override
    public void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.set);


        //retrieve shared prefs
        SharedPreferences lockPreference = getSharedPreferences(GcmIntentService.PREFERENCE_NAME, Context.MODE_PRIVATE);
newpassword = lockPreference.getString("newpassword", "");

我可以制作烤面包片或其他东西。

我不明白为什么广播接收器会失败,它的上下文不是一样的吗?


粘贴并删除了代码?问题解决了吗? - Pararth
请展示你尝试访问SharedPreferences的所有代码位置 - BroadcastReceiver代码显然是调试代码,但你没有展示Activity2代码的上下文。 - Richard Le Mesurier
2个回答

3
除了Adb El-Rahman所说的,SharedPreferences是基于您使用的context从XML文件中加载的。
您可以看到,您正在使用传递给BroadcastReceiver的上下文,这可能不是您应用程序的上下文 - 因此将引用不同的首选项文件。它将是一个ReceiverRestrictedContext实例。
然而,根据 @CommonsWare对另一个问题的回答,您应该能够通过在BroadcastReceiver内调用context.getApplicationContext()来使其工作。
顺便说一句,您应该小心不要在BroadcastReceiver内运行过多的代码 - 系统似乎不喜欢这样做。

我怎样才能知道上下文是否正确?我只是指定了context.getSharedPreferences... 这在Activity2中可以工作,但在BroadcastReceiver中不行。 - Gary
BroadcastReceiver 的 javadoc 中,它将上下文定义为“接收器正在运行的上下文”。我认为这意味着它可以是发出广播的应用程序,而不是您的应用程序。但是,Activity 是一个 Context,它与您的应用程序相关联。因此,基本上不要将此代码放入 BroadcastReceiver 中,而是放入 Activity 或 Service 中。保持您的 BroadcastReceiver 代码非常简短和简单,以避免问题。 - Richard Le Mesurier
@Gary,我发现一个相关问题,建议你应该能够从接收器中访问你的“SharedPreferences”。我仍然认为在生产环境中这是一个不好的想法,但我可以看到你正在尝试一些基本的调试。如果你能使用“getApplicationContext()”使其工作,我很感兴趣知道结果。 - Richard Le Mesurier
是的,现在它正在工作,谢谢...我在接收器中没有做太多事情,但我需要从sharedprefs设置1或2个值...现在一切都正常 :-) - Gary

2
首先,你需要知道通过使用getSharedPreference方法创建的SharedPreference文件在你的应用目录下被表示为一个真实的XML文件,所以如果你已经添加了值并提交了修改,则所有的编辑都应该存在。
其次,在你的项目中拥有一个BroadcastReceiver类应该采用与你的项目相同的PackageName,即使它是在你的应用关闭时启动的。
现在你需要确保以下内容:
1)两个Activities使用相同的SharedPReference文件,通过在你的应用程序中创建一个包含文件名的公共常量来实现。
public final static String PREFERENCE_NAME = "com.example.mypackage.preference"

2) 两个 Activities 使用相同的 SharedPreference 文件,如下:

SharedPreferences lockPreferences = getSharedPreferences(PREFERENCE_NAME, Context.MODE_PRIVATE);

3) 确保在其他文件尝试读取之前提交你的编辑内容。

lockPreferences.putBoolean(CONSTANT_KEY, true);
commit();

谢谢你的帮助,我添加了一个公共常量,但它仍然无法工作。 - Gary
不要说它不工作。总是报告你遇到的异常或者有问题的那一行代码。如果你按照我正确提到的使用了偏好设置,你就不会有任何问题。 - Sami Eltamawy
没有异常,所以很难进行故障排除......我已经编辑了上面的内容来展示我的测试。 - Gary
不要问我怎么做的,但是在添加了公共常量后,我清理了项目,现在它可以工作了...感谢大家。 - Gary
如果你在使用Eclipse,我相信你:)。@Gary,请如果你发现我的答案有用,请不要忘记给它投票:)谢谢。 - Sami Eltamawy

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