Кликабельные виджеты в Android - PullRequest
61 голосов
/ 01 мая 2010

Документация разработчика, кажется, подвела меня здесь. Я могу создать статический виджет, не задумываясь, я даже могу создать виджет, такой как виджет аналоговых часов, который будет обновляться сам, однако я не могу на всю жизнь понять, как создать виджет, который реагирует на нажатия пользователем Это. Вот лучший пример кода, который документация разработчика дает для того, что должно содержать действие виджета (единственная другая подсказка - демонстрации API, которые только создают статический виджет):

public class ExampleAppWidgetProvider extends AppWidgetProvider {
    public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
        final int N = appWidgetIds.length;

        // Perform this loop procedure for each App Widget that belongs to this provider
        for (int i=0; i<N; i++) {
            int appWidgetId = appWidgetIds[i];

            // Create an Intent to launch ExampleActivity
            Intent intent = new Intent(context, ExampleActivity.class);
            PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);

            // Get the layout for the App Widget and attach an on-click listener to the button
            RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
            views.setOnClickPendingIntent(R.id.button, pendingIntent);

            // Tell the AppWidgetManager to perform an update on the current App Widget
            appWidgetManager.updateAppWidget(appWidgetId, views);
        }
    }
}

от: Страница виджета документации разработчика Android

Таким образом, похоже, что ожидающее намерение вызывается при нажатии виджета, которое основано на намерении (я не совсем уверен, в чем разница между намерением и ожидающим намерением), и намерение предназначено для класс ExampleActivity. Таким образом, я сделал свой пример класса активности простым действием, которое при создании создаст объект медиаплеера и запустит его (он никогда не освободит объект, поэтому в конечном итоге произойдет сбой, вот его код:

@Override
public void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    MediaPlayer mp = MediaPlayer.create(getApplicationContext(), R.raw.sound);
    mp.start();
}

Однако, когда я добавил виджет на главный экран и щелкнул по нему, ничего не воспроизводилось, фактически, ничего не воспроизводилось, когда я установил таймер обновления на несколько сотен миллисекунд (в XML-файле поставщика appwidget). Кроме того, я установил точки останова и обнаружил, что он не только никогда не достигнет активности, но и не установил ни одной точки останова, которую я установил. (Я до сих пор не понял, почему это так), однако, logcat, похоже, указывал на то, что файл класса активности запускался.

Итак, что я могу сделать, чтобы приложение видело ответную реакцию на клик? Поскольку метод onClickPendingIntent () наиболее близок к методу типа onClick, который я нашел.

Большое спасибо.

Ответы [ 2 ]

126 голосов
/ 01 мая 2010

Сначала добавьте статическую переменную с константой.

public static String YOUR_AWESOME_ACTION = "YourAwesomeAction";

Затем вам нужно добавить действие к намерению, прежде чем добавить намерение к ожидающему намерению:

Intent intent = new Intent(context, widget.class);
intent.setAction(YOUR_AWESOME_ACTION);

(где widget.class - это класс вашего AppWidgetProvider, ваш текущий класс)

Затем вам нужно создать PendingIntent с getBroadcast

PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, 0);

Установите onClickPendingIntent для интерактивного представления в вашем виджете

remoteView.setOnClickPendingIntent(R.id.widgetFrameLayout, pendingIntent);

Затем переопределите метод onReceive в том же классе:

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

А затем реагируйте на нажатия кнопок, запрашивая намерение, возвращаемое для вашего действия в методе onReceive:

if (intent.getAction().equals(YOUR_AWESOME_ACTION)) {
   //do some really cool stuff here
}

И это должно сделать это!

1 голос
/ 28 июля 2018

Оставьте метод onUpdate как есть и скопируйте и вставьте логику в updateAppWidget .

static void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
                            int appWidgetId) {

    // Create an Intent to launch ExampleActivity when clicked
    Intent intent = new Intent(context, ExampleActivity.class);
    PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
    // Construct the RemoteViews object
    RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_provider_layout);
    // Widgets allow click handlers to only launch pending intents
    views.setOnClickPendingIntent(R.id.button, pendingIntent);
    // Instruct the widget manager to update the widget
    appWidgetManager.updateAppWidget(appWidgetId, views);
}

@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
    // There may be multiple widgets active, so update all of them
    for (int appWidgetId : appWidgetIds) {
        updateAppWidget(context, appWidgetManager, appWidgetId);
    }
}

PS. PendingIntent - это просто "ящик" для Intent, который позволяет другим приложениям иметь доступ и запускать этот Intent в вашем приложении.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...