5

I am working on Android Widget my widget is like following diagram, [prev] event name [next]

prev, next are the buttons on the widget.So i want to update the event name on click of next and prev button.On start of the service i loaded the data and stored it in array list. Now i want to iterate through the array list by clicking the next and prev buttons on the widget.

So how can i achieve this.Please help me with proper solution. Here is my xml layout

<LinearLayout
    android:id="@+id/lytWidget2"
    android:layout_width="fill_parent"
    android:layout_height="wrap_content"
    android:layout_marginTop="5dip"
    android:orientation="horizontal" >

    <Button
        android:id="@+id/btnPreviousView"
        android:layout_width="43dp"
        android:layout_height="fill_parent"
        android:layout_gravity="left|center"
        android:background="@drawable/ic_leftarrow"
        android:padding="5dip" />

    <TextView
        android:layout_width="wrap_content"
        android:layout_height="52dp"
        android:layout_weight="0.97"
        android:text="Event Name" />

    <Button
        android:id="@+id/btnNextView"
        android:layout_width="43dp"
        android:layout_height="fill_parent"
        android:layout_gravity="right|center_vertical"
        android:background="@drawable/ic_rightarrow"
        android:padding="5dip" />
</LinearLayout>
VK.Dev
  • 801
  • 4
  • 11
  • 24

4 Answers4

10

So, just handle the click events of your buttons in the AppWidgetProvider class like this. See this good tutorial on how to create simple widget. There are click handlers added too.

Sample code

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

      RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
      // find your TextView here by id here and update it.

      Toast.makeText(context, "Clicked!!", Toast.LENGTH_SHORT).show(); 
 } 
Tomislav Markovski
  • 12,331
  • 7
  • 50
  • 72
  • Thanks for the Answe.But how can i update the textview(between prev and next button) of the widget by clicking the button. – VK.Dev Dec 26 '11 at 12:29
  • 1
    Yes you can. Read the tutorial, it has great examples how to achieve this. There's a sample widget project that will help you greatly. – Tomislav Markovski Dec 26 '11 at 12:32
  • but sample directly opens activity.But i want to update the current view of the widget without opening anything.Look at the Facebook widget you can see the posts of the user by clicking next and previous button. – VK.Dev Dec 26 '11 at 12:56
  • Sample code has a line where it gets all views. Extract the TextView from those views and update it. `RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);` – Tomislav Markovski Dec 26 '11 at 12:58
  • 3
    This should really get the answer. – tempy Jun 13 '12 at 16:02
  • 2
    This firing only when the widget is dragged. How to fire it on click – Rahmathullah M Jul 06 '13 at 10:18
3

First, in your WidgetProviderClass you should define your actions so that you could differentiate them. In this case:

private static final String ACTION_UPDATE_CLICK_NEXT = "action.UPDATE_CLICK_NEXT";
private static final String ACTION_UPDATE_CLICK_PREVIOUS = "action.UPDATE_CLICK_PREVIOUS";

Next, in your overrided onUpdate() funcion you should put:

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

            RemoteViews views = new RemoteViews(context.getPackageName(),R.layout.your_widget_layout);

            views.setOnClickPendingIntent(R.id.nextButtonWidget, getPendingSelfIntent(context, ACTION_UPDATE_CLICK_NEXT));
            views.setOnClickPendingIntent(R.id.previousButtonWidget, getPendingSelfIntent(context, ACTION_UPDATE_CLICK_PREVIOUS));

}

Function for creating an intent that's directed to the current class (to itself):

private PendingIntent getPendingSelfIntent(Context context, String action) {

        Intent intent = new Intent(context, getClass()); // An intent directed at the current class (the "self").
        intent.setAction(action);
        return PendingIntent.getBroadcast(context, 0, intent, 0);
    }

When the event occurs onReceive() function will be called:

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


            if (ACTION_UPDATE_CLICK_NEXT.equals(intent.getAction())) {
                 // if the user clicked next
                }


            else if (ACTION_UPDATE_CLICK_PREVIOUS.equals(intent.getAction())) {
                // if the user clicked previous
        }

}

BONUS: If you want to call the onUpdate() function here is a function that will do that for you. It requires only the context parameter!

/**
 * A general technique for calling the onUpdate method,
 * requiring only the context parameter.
 *
 * @author John Bentley, based on Android-er code.
 * @see <a href="http://android-er.blogspot.com
 * .au/2010/10/update-widget-in-onreceive-method.html">
 * Android-er > 2010-10-19 > Update Widget in onReceive() method</a>
 */

private void onUpdate(Context context) {

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    ComponentName thisAppWidgetComponentName = new ComponentName(context.getPackageName(), getClass().getName());
    int[] appWidgetIds = appWidgetManager.getAppWidgetIds(thisAppWidgetComponentName);
    onUpdate(context, appWidgetManager, appWidgetIds);
}
Marija
  • 422
  • 4
  • 12
0

NewAppWidget.java

package com.example.android.appwidgetsample;

import android.app.PendingIntent;
import android.appwidget.AppWidgetManager;
import android.appwidget.AppWidgetProvider;
import android.content.Context;
import android.content.Intent;
import android.content.SharedPreferences;
import android.widget.RemoteViews;

import java.text.DateFormat;
import java.util.Date;

/**
 * App widget provider class, to handle update broadcast intents and updates
 * for the app widget.
 */
public class NewAppWidget extends AppWidgetProvider {

    // Name of shared preferences file & key
    private static final String SHARED_PREF_FILE =
            "com.example.android.appwidgetsample";
    private static final String COUNT_KEY = "count";

    /**
     * Update a single app widget.  This is a helper method for the standard
     * onUpdate() callback that handles one widget update at a time.
     *
     * @param context          The application context.
     * @param appWidgetManager The app widget manager.
     * @param appWidgetId      The current app widget id.
     */
    private void updateAppWidget(Context context,
                                AppWidgetManager appWidgetManager,
                                int appWidgetId) {

        // Get the count from prefs.
        SharedPreferences prefs =
                context.getSharedPreferences(SHARED_PREF_FILE, 0);
        int count = prefs.getInt(COUNT_KEY + appWidgetId, 0);
        count++;

        // Get the current time.
        String dateString =
                DateFormat.getTimeInstance(DateFormat.SHORT).format(new Date());

        // Construct the RemoteViews object.
        RemoteViews views = new RemoteViews(context.getPackageName(),
                R.layout.new_app_widget);
        views.setTextViewText(R.id.appwidget_id,
                String.valueOf(appWidgetId));
        views.setTextViewText(R.id.appwidget_update,
                context.getResources().getString(
                    R.string.date_count_format, count, dateString));

        // Save count back to prefs.
        SharedPreferences.Editor prefEditor = prefs.edit();
        prefEditor.putInt(COUNT_KEY + appWidgetId, count);
        prefEditor.apply();

        // Setup update button to send an update request as a pending intent.
        Intent intentUpdate = new Intent(context, NewAppWidget.class);

        // The intent action must be an app widget update.
        intentUpdate.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);

        // Include the widget ID to be updated as an intent extra.
        int[] idArray = new int[]{appWidgetId};
        intentUpdate.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, idArray);

        // Wrap it all in a pending intent to send a broadcast.
        // Use the app widget ID as the request code (third argument) so that
        // each intent is unique.
        PendingIntent pendingUpdate = PendingIntent.getBroadcast(context,
                appWidgetId, intentUpdate, PendingIntent.FLAG_UPDATE_CURRENT);

        // Assign the pending intent to the button onClick handler
        views.setOnClickPendingIntent(R.id.button_update, pendingUpdate);

        // Instruct the widget manager to update the widget.
        appWidgetManager.updateAppWidget(appWidgetId, views);
    }

    /**
     * Override for onUpdate() method, to handle all widget update requests.
     *
     * @param context          The application context.
     * @param appWidgetManager The app widget manager.
     * @param appWidgetIds     An array of the app widget IDs.
     */
    @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);
        }
    }
}

NewAppWidget.xml

<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
                xmlns:tools="http://schemas.android.com/tools"
                android:layout_width="match_parent"
                android:layout_height="match_parent"
                android:background="#09C"
                android:padding="@dimen/widget_margin" >

    <!-- Panel for Widget ID -->
    <LinearLayout
        android:id="@+id/section_id"
        style="@style/AppWidgetSection"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_alignParentTop="true"
        android:orientation="horizontal">

        <TextView
            android:id="@+id/appwidget_id_label"
            style="@style/AppWidgetLabel"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="2"
            android:text="@string/widget_id_label"/>

        <TextView
            android:id="@+id/appwidget_id"
            style="@style/AppWidgetText"
            android:layout_width="0dp"
            android:layout_height="wrap_content"
            android:layout_weight="1"
            android:gravity="end"
            android:text="XX"/>
    </LinearLayout>

    <!-- Panel for widget update date and number of updates -->
    <LinearLayout
        android:id="@+id/section_update"
        style="@style/AppWidgetSection"
        android:layout_width="match_parent"
        android:layout_height="wrap_content"
        android:layout_alignParentLeft="true"
        android:layout_alignParentStart="true"
        android:layout_below="@+id/section_id"
        android:orientation="vertical">

        <TextView
            android:id="@+id/appwidget_update_label"
            style="@style/AppWidgetLabel"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:layout_marginBottom="2dp"
            android:text="@string/widget_update_label"/>

        <TextView
            android:id="@+id/appwidget_update"
            style="@style/AppWidgetText"
            android:layout_width="match_parent"
            android:layout_height="wrap_content"
            android:text="@string/date_count_format"/>
    </LinearLayout>

    <!-- Update widget button -->
    <Button
        android:id="@+id/button_update"
        style="@style/AppWidgetButton"
        android:layout_width="wrap_content"
        android:layout_height="wrap_content"
        android:layout_below="@+id/section_update"
        android:layout_centerHorizontal="true"
        android:text="@string/widget_button_update" />
</RelativeLayout>
0
private static final String ACTION_UPDATE_CLICK_NEXT = "action.UPDATE_CLICK_NEXT";
private static final String ACTION_UPDATE_CLICK_PREVIOUS = "action.UPDATE_CLICK_PREVIOUS";

AppWidgetManager#getAppWidgetIds() returns empty int array when the widget service is null. Thus, you will not get appWidgetIds on your button action. You have to get it from intent.

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

    if (ACTION_UPDATE_CLICK_NEXT.equals(intent.getAction()) || ACTION_UPDATE_CLICK_PREVIOUS.equals(intent.getAction()) ) {
        int[] appWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
        drawWidgets(context, appWidgetIds);

    } else {
        AppWidgetManager widgetManager = AppWidgetManager.getInstance(context);
        ComponentName widgetComponent = new ComponentName(context, getClass());
        int[] appWidgetIds = widgetManager.getAppWidgetIds(widgetComponent);
        drawWidgets(context, appWidgetIds);

    }

}

Of course, you should pass the app-widget-ids to the intent as extra

private void drawWidget(Context context, int appWidgetId) {
    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
    RemoteViews remoteView = new RemoteViews(context.getPackageName(), R.layout.widget_light);
    
    ...

    Intent intent = new Intent(context, getClass());
    intent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
    int[] ids = AppWidgetManager.getInstance(context).getAppWidgetIds(new ComponentName(context, getClass()));
    //put the IDs in the intent. We may not get it from AppWidgetManager
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, ids);
    int flags = (Build.VERSION.SDK_INT >= Build.VERSION_CODES.M) ? PendingIntent.FLAG_UPDATE_CURRENT | PendingIntent.FLAG_IMMUTABLE : PendingIntent.FLAG_UPDATE_CURRENT;
    PendingIntent pendingIntent= PendingIntent.getBroadcast(context, 0, intent, flags);
    remoteView.setOnClickPendingIntent(R.id.nextButtonWidget, pendingIntent);

    appWidgetManager.updateAppWidget(appWidgetId, remoteView);


}
makata
  • 2,188
  • 2
  • 28
  • 23