После того, как кнопки изменения ориентации на виджете не отвечают
У меня есть две кнопки на виджетах, которые меняют некоторые элементы в виджетах, если ориентация меняется на телефоне, кнопки ничего не делают. Я читал http://developer.android.com/guide/topics/resources/runtime-changes.html, но все это касается активности, а не виджета.
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget);
Intent active = new Intent(context, TvWidget.class);
active.setAction(ACTION_WIDGET_RECEIVER);
mDbHelper = new DbAdapter(context);
fillChannelList(context, appWidgetIds[appWidgetIds.length-1]);
Set<Integer> keys = channelsImages.keySet();
Iterator<Integer> iter = keys.iterator();
while(iter.hasNext())
{
if(channelId == 0)
{
channelId = iter.next();
break;
}
}
SharedPreferences settings = context.getSharedPreferences(PREFS_NAME, 0);
Editor edit = settings.edit();
edit.putInt("channelId", channelId);
edit.putInt("appWidgetIds", appWidgetIds[appWidgetIds.length-1]);
edit.commit();
active.putExtra("net.aerosoftware.tvvodic.appWidgetIds", appWidgetIds);
PendingIntent actionPendingIntent = PendingIntent.getBroadcast(context, 0, active, 0);
remoteViews.setOnClickPendingIntent(R.id.button_next, actionPendingIntent);
Intent refresh = new Intent(context, TvWidget.class);
refresh.setAction(ACTION_WIDGET_REFRESH);
refresh.putExtra("net.aerosoftware.tvvodic.appWidgetIds", appWidgetIds);
PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, 0, refresh, 0);
remoteViews.setOnClickPendingIntent(R.id.button_refresh, refreshPendingIntent);
updateView(context);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
Ответы
Ответ 1
Я бы предложил создать службу (возможно, подклассифицируя ее внутри вашего AppWidgetProvider) и переопределяя метод onConfigurationChanged(). Использование службы позволит вам делегировать вашу бизнес-логику для обработки, сборки и обновления вашего виджета. Он также позволит вам управлять поворотами. И если вы выполняете какие-либо операции блокировки, то сервис будет хорошим местом для создания потока и возврата результата в основной поток пользовательского интерфейса, чтобы избежать ANR.
Я бы предложил следующее:
public class MyWidget extends AppWidgetProvider
{
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds)
{
context.startService(new Intent(context, MyUpdateService.class));
}
public static class MyUpdateService extends Service
{
@Override
public void onStart(Intent intent, int startId)
{
super.onStart(intent, startId);
// Update the widget
RemoteView remoteView = buildRemoteView(this);
// Push update to homescreen
pushUpdate(remoteView);
// No more updates so stop the service and free resources
stopSelf();
}
public RemoteViews buildRemoteView(Context context)
{
RemoteView updateView = null;
updateView = new RemoteViews(context.getPackageName(), R.layout.my_widget_layout);
// Your code to build and update the remote view
return updateView;
}
@Override
public void onConfigurationChanged(Configuration newConfig)
{
int oldOrientation = this.getResources().getConfiguration().orientation;
if(newConfig.orientation != oldOrientation)
{
// Update the widget
RemoteView remoteView = buildRemoteView(this);
// Push update to homescreen
pushUpdate(remoteView);
}
}
private void pushUpdate(RemoteView remoteView)
{
ComponentName myWidget = new ComponentName(this, MyWidget.class);
AppWidgetManager manager = AppWidgetManager.getInstance(this);
manager.updateAppWidget(myWidget, updateViews);
}
}
}
Также посмотрите на эту ссылку: http://android-developers.blogspot.com/2009/04/introducing-home-screen-widgets-and.html
Кроме того, обязательно указывайте, что вы заинтересованы в получении уведомлений об изменении ротации в вашем манифесте. Что-то вроде этого будет работать:
андроид: configChanges = "keyboardHidden | ориентация"
объявлен в декларации сервиса внутри манифеста.
Надеюсь, что это поможет!
Ответ 2
Всякий раз, когда вы обновляете внешний вид вашего виджета (используя либо Activity, либо ваш широковещательный приемник [поставщик виджета приложений]), вы также должны переназначить все PendingIntents для обработчиков кликов, а затем вызвать updateAppWidget()
как обычно.
Пример с setTextViewText()
:
// This will update the Widget, but cause it to
// stop working after an orientation change.
updateWidget()
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
remoteViews.setTextViewText(R.id.widget_text_view, "Updated widget");
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
// This is the correct way to update the Widget,
// so that it works after orientation change.
updateWidget()
{
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
remoteViews.setTextViewText(R.id.widget_text_view, "Updated widget");
Intent intent = new Intent(context, MyWidgetActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, ...);
remoteViews.setOnClickPendingIntent(R.id.widget_click_button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, remoteViews);
}
Ответ 3
Проблема может быть связана с наличием двух кнопок на виджете, что почему-то вызывает проблемы. См. Здесь:
http://permalink.gmane.org/gmane.comp.handhelds.android.devel/98008
или
http://groups.google.com/group/android-developers/browse_thread/thread/578a4429c369c27c/273a53a96ddd10c5?lnk=gst&q=Widget+does+not+respond+when+phone+orientation+changes#273a53a96ddd10c5
Но пока неясно, каково истинное решение (решение, для которого не требуется создание фоновой службы).
Ответ 4
Если вы используете
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
чтобы изменить какое-либо состояние определенного вида внутри объекта удаленных представлений, вам также нужно изменить другие представления, поскольку событие изменения ориентации будет помнить только последний объект RemoteViews, который использовался для обновления вашего виджета. Он воссоздает виджет с последним используемым объектом RemoteViews. Вот почему вам всегда нужно обновлять все представления внутри объекта RemoteViews, а также всех слушателей для ваших просмотров.
Остальные будут обрабатываться ОС автоматически.