Подтвердить что ты не робот

После того, как кнопки изменения ориентации на виджете не отвечают

У меня есть две кнопки на виджетах, которые меняют некоторые элементы в виджетах, если ориентация меняется на телефоне, кнопки ничего не делают. Я читал 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);
}
4b9b3361

Ответ 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, а также всех слушателей для ваших просмотров.

Остальные будут обрабатываться ОС автоматически.