防止触发WidgetProvider的onUpdate

时间:2012-08-02 16:01:14

标签: android android-widget appwidgetprovider

我正在实现一个具有ConfigurationActivity的Widget,并且必须与Eclair(2.1)保持兼容。

关于AppWidgetProviders onUpdate方法的documentation明确指出:

  

....但是,如果您已声明配置Activity,则在用户添加App Widget时不会调用此方法,但会为后续更新调用此方法。配置Activity负责在配置完成时执行第一次更新。 (请参阅下面的“创建应用程序小组件配置活动”。)

不幸的是,这不是真的(至少对于我的带有JellyBean的Nexus S)。实际上onUpdate在我的ConfigurationActivity触发器 onCreate之前被称为。我想知道,如果其他手机上存在类似行为,并且是否可以阻止我的提供商内部onUpdate来电?

我的解决方法是使用特定的AppWidgetId在我的WidgetConfigurationActivity中的SharedPreferences中存储一个标志。如果它不存在,我可以假设没有首先调用ConfigurationActivity。这有效,但在我的观点中真的很难看。如果我无法阻止onUpdate触发,是否有更好的解决方案?

3 个答案:

答案 0 :(得分:4)

是的,在主屏幕上添加小部件时会调用onUpdate()。 见这里:

http://developer.android.com/reference/android/appwidget/AppWidgetProvider.html

http://developer.android.com/reference/android/appwidget/AppWidgetManager.html#ACTION_APPWIDGET_UPDATE

我不确定在创建窗口小部件时是否有办法不触发它。但是你可以通过将Widget Info XML文件中的“updatePeriodMillis”字段设置为 0 或者将其保留为空白来阻止它再次触发。

另一种方法是将窗口小部件ID存储在某处。现在,无论何时添加新窗口小部件,都要在Receiver类中检查ID是否已存在。如果它不存在(意味着一个新的小部件),那么不要执行任何代码。此外,每当删除窗口小部件时,都会从记录中删除窗口小部件ID由于您可能删除了窗口小部件,因此稍后添加了一个与旧窗口小部件ID相同的新窗口小部件。

希望有所帮助!

编辑: 在Receiver类的onReceive()方法中,执行以下操作:

public void onReceive(Context context, Intent intent) {
    // TODO Auto-generated method stub

    int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, AppWidgetManager.INVALID_APPWIDGET_ID);
    if( appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID )
    {
        super.onReceive(context, intent);
    }

}

首次从窗口小部件列表中选择窗口小部件时,其appWidgetId将等于INVALID_APPWIDGET_ID,直到将其添加到主屏幕上。由于“super.onReceive()”在选择窗口小部件时调用onUpdate()方法,因此第一次不会调用onUpdate()。

答案 1 :(得分:0)

我也有这个错误。

即使我将updatePeriodMillis设置为0.在开始Widget活动配置之前,我的onUpdate正在运行。我认为这是android小部件中的一个错误。

答案 2 :(得分:0)

我通过在onUpdate中为intent添加一个动作然后检查onReceive以查看是否单击了widget来解决了这个问题:

我添加了intentClick.setAction(WIDGET_CLICKED);,只有在点击小工具时才会触发。

public class WidgetProvider extends AppWidgetProvider {

    private static final String TAG = WidgetProvider.class.getSimpleName();
    private static String WIDGET_CLICKED = "widget_clicked";

public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    Log.e(TAG, "onUpdate()");

    remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);
    watchWidget = new ComponentName(context, WidgetProvider.class);

    Intent intentClick = new Intent(context, WidgetProvider.class);
    intentClick.setAction(WIDGET_CLICKED);
    intentClick.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, "" + appWidgetIds[0]);

    PendingIntent pendingIntent = PendingIntent.getBroadcast(context, appWidgetIds[0], intentClick, 0);
    remoteViews.setOnClickPendingIntent(R.id.img_btn, pendingIntent);
    remoteViews.setInt(R.id.img_btn, "setBackgroundResource", R.drawable.play);

    appWidgetManager.updateAppWidget(watchWidget, remoteViews);
}

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

    Log.e(TAG, "onReceive()");
    Bundle extras = intent.getExtras();

    //If AND ONLY IF WIDGET_CLICKED
    if (extras != null && intent.getAction().equals(WIDGET_CLICKED)) {
        remoteViews = new RemoteViews(context.getPackageName(), R.layout.main);

        //If isPlaying
        if (isPlaying) {
            //setBackground as PLAY
            remoteViews.setInt(R.id.img_btn, "setBackgroundResource", R.drawable.play);
            isPlaying = false;

            Intent i = new Intent(context, MediaPlayerService.class);
            i.putExtra("command", "stopSong");
            context.startService(i);

            //If NOT playing
        } else {
            //setBackground as STOP
            remoteViews.setInt(R.id.img_btn, "setBackgroundResource", R.drawable.stop);
            isPlaying = true;

            Intent i = new Intent(context, MediaPlayerService.class);
            i.putExtra("command", "playRandomSong");
            context.startService(i);
        }

        watchWidget = new ComponentName(context, WidgetProvider.class);

        (AppWidgetManager.getInstance(context)).updateAppWidget(watchWidget, remoteViews);
    }
}