Android appwidget有时会将首选项更改回默认值

时间:2012-01-09 23:23:24

标签: android android-appwidget

我在Android市场上发布了一些appwidgets,它们在大多数情况下运行良好。但是我注意到,使用共享首选项保存的首选项有时会重置为默认值。在这种情况下,默认值是硬编码变量。保存在xml中的共享首选项保持与用户保存的相同。

在一个可验证的情况下,在设备重启后发生了上述问题以及其他诸如停止响应的按钮之类的问题。我修复了这个问题,创建了一个BroadcastReceiver,它有一个onReceive()方法,该方法将由清单中的intent过滤器激活:

<intent-filter>
  <action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>

换句话说,BroadcastReceiver将在重启后运行,效果很好。

然而,该设备有时仍然会重置偏好,我注意到这种情况发生在一晚左右的待机状态之后。我怀疑这是因为设备(在一段时间后,可能由于进入待机状态)可能会重启appwidget,然后再次使用默认首选项。我尝试通过在清单中添加以下内容作为BroadcastReceiver的一部分来解决它:

<intent-filter>
  <action android:name="android.intent.action.PACKAGE_RESTARTED"/>
</intent-filter>

完整部分内容如下:

<receiver android:name=".BroadcastReceiverName">
  <intent-filter>
    <action android:name="android.intent.action.BOOT_COMPLETED"/>
  </intent-filter>
  <intent-filter>
    <action android:name="android.intent.action.PACKAGE_RESTARTED"/>
  </intent-filter>
</receiver>

但这似乎不起作用。

我想知道可能导致此问题的原因以及如何在应用中检测到它并采取相应措施,即启动BroadcastReceiver并重新加载首选项。

为了完整起见,这里是(工作)BroadcastReceiver代码的一部分,我从Service does not restart after "Clear Memory" + appWidget crashes获得了这个想法

public class BroadcastReceiverName extends BroadcastReceiver
{
  @Override
  public void onReceive(Context context, Intent intent)
  {
    /* stuff done here to reread shared preferences and refresh button's pending intents etc. */

    SharedPreferences config=context.getSharedPreferences(ExampleWidgetConfig.PREFS_NAME, 0);
    int poll=config.getInt(ExampleWidgetConfig.PREFS_UPDATE_RATE, ExampleWidgetProvider.poll);
    int alert=config.getInt(ExampleWidgetConfig.PREFS_ALERT, ExampleWidgetProvider.alert);
    int backg=config.getInt(ExampleWidgetConfig.PREFS_BACKG, ExampleWidgetProvider.backg);

    /* change hardcoded default preferences in case they differ from saved ones */
    ExampleWidgetProvider.poll=poll;
    ExampleWidgetProvider.alert=alert;
    ExampleWidgetProvider.backg=backg;

    /* ... */
  }
}

保存首选项的代码。请注意,此代码实际上有效,问题不在于首选项未保存或正确读取,而是应用程序中已更改为用户值的硬编码值将再次更改(请参阅上面的示例)。

/* change hardcoded values to user's settings */
ExampleWidgetProvider.poll=getpoll();
ExampleWidgetProvider.alert=getalert();
ExampleWidgetProvider.backg=getbackg();

/* store user settings we will continue to use these in the app */
SharedPreferences.Editor configEditor=config.edit();
configEditor.putInt(PREFS_UPDATE_RATE, ExampleWidgetProvider.poll);
configEditor.putInt(PREFS_ALERT, ExampleWidgetProvider.alert);
configEditor.putInt(PREFS_BACKG, ExampleWidgetProvider.backg);
configEditor.commit();

所以我需要知道如何找出这些硬编码值何时重置为默认值。我可以通过每小时左右读取首选项xml来解决它,但这听起来像是一个愚蠢的解决方案。

1 个答案:

答案 0 :(得分:1)

正如文件所述:

  

参数

     

key要检索的首选项的名称。   defValue如果此首选项不存在则返回的值。

     

返回首选项值(如果存在)或defValue。   如果存在此名称的首选项,则抛出ClassCastException   一个int。

如果要相信文档,那么首选项根本不存在,您可以通过使getInt值与xml中的值不同来测试,如果它返回{{1}你知道首选项不存在的值。

在上述情况下,您的首选项必须首先删除或者未正确设置,但这似乎不太可能。

您可以看到的另一件事是您在更新偏好设置时调用getInt,或者您的偏好设置是否正在更新。

您也可以在设置偏好时尝试使用这些模式,尝试commit,因为广播接收器是一个单独的过程,可能您正在其他地方设置首选项,并尝试'MODE_WORLD_WRITEABLE'。

来自评论的

更新

首先,代码有点令人困惑,我猜是因为我看不到所有内容,但是你不能在这里复制整个项目,所以我将不得不忍受。

这就是我理解问题的方法:您在偏好中设置这些值,您可以在某一点上调用MODE_MULTI_PROCESS这些首选项并且它是正确的,然后在某个事件之后(可能是通过站立触发) by)你再次调用getInt并且首选项返回到preference.xml中指定的默认值,而不是调用getInt时传递的默认值(因为这表明首选项不存在)

我注意到您正在将值复制到这些ExampleWidgetProvider。*变量,您确定这些值不是您作为首选项检索的正确值,并且首选项中存在的任何值都不会正确设置。我没有看到拥有这些变量的重点,因为当你更改任何一个变量时,你需要同步它们。如果他们是一个工作的一部分,那么他们应该被删除,所以他们不会卷积原来的问题。

我相信你知道;如果你重新启动应用程序,首选项应该与重启前相同,因为首选项值是持久的(假设你已正确配置它们),并且正如文档中所述:

  

android:defaultValue 首选项的默认值,即   如果持久性已关闭或持久性已打开,则设置为   在持久存储中找不到首选项。

这表明偏好不会重置为原始值,而是因为任何原因而不存在(如果这是特定的默认值,它会不断出现)。

存在方法getInt,但你说你不是那个。因此,偏好似乎不太可能被重置,而是首先被删除或从不存在。