Как отправить данные из приложения в AppWidgetProvider?

Я застрял в конкретном сценарии. Мне нужно обновить мой виджет, как только пользователь обновит время из приложения. Я попробовал Broadcast, отправив данные через Intent Extras, но не смог этого сделать. В настоящее время у меня есть данные в AppWidgetProvider, и мне нужно отправить эти данные в службу

public class CountdownWidget extends AppWidgetProvider {
    // SharedPreferences userDefaults;

    // update rate in milliseconds
    public static final int UPDATE_RATE = 1800000; // 30 minute

    public static String nameOne = "";

    @Override
    public void onDeleted(Context context, int[] appWidgetIds) {
        for (int appWidgetId : appWidgetIds) {
            setAlarm(context, appWidgetId, -1);
        }
        super.onDeleted(context, appWidgetIds);
    }

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

        Bundle extras = intent.getExtras();
        nameOne = extras.getString("NAME_ONE");

        Log.e("Name: ", nameOne);

        super.onReceive(context, intent);
    }

    @Override
    public void onUpdate(Context context, AppWidgetManager appWidgetManager,
                         int[] appWidgetIds) {

        for (int appWidgetId : appWidgetIds) {
            setAlarm(context, appWidgetId, UPDATE_RATE);
        }
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }

    public static void setAlarm(Context context, int appWidgetId, int updateRate) {

        // Log.e("", "Updating Widget Service");

        PendingIntent newPending = makeControlPendingIntent(context,
                CountdownService.UPDATE, appWidgetId);
        AlarmManager alarms = (AlarmManager) context
                .getSystemService(Context.ALARM_SERVICE);
        if (updateRate >= 0) {
            alarms.setRepeating(AlarmManager.ELAPSED_REALTIME,
                    SystemClock.elapsedRealtime(), updateRate, newPending);
        } else {
            // on a negative updateRate stop the refreshing
            alarms.cancel(newPending);
        }
    }

    public static PendingIntent makeControlPendingIntent(Context context,
                                                         String command, int appWidgetId) {
        Intent active = new Intent(context, CountdownService.class);
        active.setAction(command);
        active.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
        // this Uri data is to make the PendingIntent unique, so it wont be
        // updated by FLAG_UPDATE_CURRENT
        // so if there are multiple widget instances they wont override each
        // other
        Uri data = Uri.withAppendedPath(
                Uri.parse("countdownwidget://widget/id/#" + command
                        + appWidgetId), String.valueOf(appWidgetId));
        active.setData(data);
        return (PendingIntent.getService(context, 0, active,
                PendingIntent.FLAG_UPDATE_CURRENT));
    }
}

Как видите, nameOne — это статическая переменная. Я могу получать данные по методу onReceive с помощью getExtras, но я не могу передать эти данные в свою службу CountdownService.

Я пробовал CountdownWidget.nameOne, но все еще не могу получить данные в сервисе.

Любая помощь будет высоко оценена.


person muneikh    schedule 30.07.2012    source источник


Ответы (2)


Вам необходимо создать службу, которая обновляет виджет, см. это руководство ( 4-й раздел) можно попробовать передать данные через статические переменные.

person Ali Alnoaimi    schedule 30.07.2012
comment
Пожалуйста, посмотрите обновленный вопрос, я пытался использовать статическую переменную, но не смог получить данные. - person muneikh; 30.07.2012

Я делаю это, добавляя дополнения в намерение, которое я создаю для обновления виджета. Кроме того, когда у виджета есть информация, ее можно снова передать в RemoteViewsService, который заполняет представления для виджета.

В моем вспомогательном методе UpdateWidget я передаю userId (вызывается различными действиями в приложении, которым может потребоваться уведомить виджет о том, что ему необходимо обновить себя).

public static void updateWorkoutsWidget(Context context) {
    Intent intent = new Intent(context, WorkoutsWidget.class);
    intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
    intent.putExtra(WorkoutsWidgetService.USER_ID_EXTRA, userId);
    int[] ids = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, WorkoutsWidget.class));
    if(ids != null && ids.length > 0) {
        intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
        context.sendBroadcast(intent);
    }

Затем виджет имеет поле для хранения идентификатора пользователя и обновляет его в onReceive. Я передаю его в RemoteViewsService с намерением, которое используется для создания адаптера коллекции.

public class WorkoutsWidget extends AppWidgetProvider {
    private long userId;

    @Override
    public void onReceive(Context context, Intent intent) {
        if(intent.getLongExtra(WorkoutsWidgetService.USER_ID_EXTRA, -1) != -1) {
             userId = intent.getLongExtra(WorkoutsWidgetService.USER_ID_EXTRA, -1);
        }
        super.onReceive(context, intent);
    }

    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        // update each of the app widgets with the remote adapter
        for (Integer widgetId : appWidgetIds) {
            Intent intent = new Intent(context, WorkoutsWidgetService.class);
            intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, widgetId);
            intent.putExtra(WorkoutsWidgetService.USER_ID_EXTRA, userId);
            intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));

            RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.widget_workouts);
            rv.setRemoteAdapter(R.id.workouts_list, intent);

            rv.setEmptyView(R.id.workouts_list, R.id.empty_view);

            //(Pending intent stuff ommitted for brrevity)

            appWidgetManager.updateAppWidget(widgetId, rv);
        }
        super.onUpdate(context, appWidgetManager, appWidgetIds);
    }
}

И затем все это проходит прямо через RemoteViewsService в его RemoteViewsFactory:

public class WorkoutsWidgetService extends RemoteViewsService {
    public static final String TRACK_WORKOUT_ACTION = "com.bodybuilding.mobile.service.TRACK_WORKOUT_ACTION";
    public static final String USER_ID_EXTRA = "userId";

    @Override
    public RemoteViewsFactory onGetViewFactory(Intent intent) {
        return new WorkoutWidgetViewsFactory(this.getApplicationContext(), intent);
    }

    class WorkoutWidgetViewsFactory implements RemoteViewsFactory, ServiceConnection {

        WorkoutWidgetViewsFactory(Context context, Intent intent) {
            this.context = context;
            appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, -1);
            userId = intent.getLongExtra(USER_ID_EXTRA, -1);
        }

        //Lots of other stuff in here
    }
}
person alphonzo79    schedule 11.10.2014