我正在实现一个具有ConfigurationActivity的Widget,并且必须与Eclair(2.1)保持兼容。
关于AppWidgetProviders onUpdate
方法的documentation明确指出:
....但是,如果您已声明配置Activity,则在用户添加App Widget时不会调用此方法,但会为后续更新调用此方法。配置Activity负责在配置完成时执行第一次更新。 (请参阅下面的“创建应用程序小组件配置活动”。)
不幸的是,这不是真的(至少对于我的带有JellyBean的Nexus S)。实际上onUpdate
在我的ConfigurationActivity触发器 onCreate
之前被称为。我想知道,如果其他手机上存在类似行为,并且是否可以阻止我的提供商内部onUpdate
来电?
我的解决方法是使用特定的AppWidgetId在我的WidgetConfigurationActivity中的SharedPreferences中存储一个标志。如果它不存在,我可以假设没有首先调用ConfigurationActivity。这有效,但在我的观点中真的很难看。如果我无法阻止onUpdate
触发,是否有更好的解决方案?
答案 0 :(得分:4)
是的,在主屏幕上添加小部件时会调用onUpdate()。 见这里:
http://developer.android.com/reference/android/appwidget/AppWidgetProvider.html
我不确定在创建窗口小部件时是否有办法不触发它。但是你可以通过将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);
}
}