androidandroid-intentandroid-widget

Android widget onclick listener for several buttons


I am trying to create a widget for my application. From my reading an android developer site your onclick listeners all need to have an Intent. But what if I just want my button to update data in the widget itself and I don't want to start a new activity?

Here is some Android demo code:

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);

I want a button that when I click makes a http web call and then displays the results in the widget. How do I go about doing this if I have to use intents? Also I need to be able to differentiate between which buttons where clicked.

Why do widgets use intents and not the normal onclick listener where it calls a function like activities?

EDIT

My widget provider:

public class MyWidgetProvider extends AppWidgetProvider {

private static final String MyOnClick1 = "myOnClickTag1";
private static final String MyOnClick2 = "myOnClickTag2";
private static final String MyOnClick3 = "myOnClickTag3";

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

    // Get all ids
    ComponentName thisWidget = new ComponentName(context, MyWidgetProvider.class);
    int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

    for (int widgetId : allWidgetIds) {

        RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);

        remoteViews.setOnClickPendingIntent(R.id.widget_button_stayarm, getPendingSelfIntent(context, MyOnClick1));
        remoteViews.setOnClickPendingIntent(R.id.widget_button_awayarm, getPendingSelfIntent(context, MyOnClick2));
        remoteViews.setOnClickPendingIntent(R.id.widget_button_dissarm, getPendingSelfIntent(context, MyOnClick3));

        remoteViews.setTextViewText(R.id.widget_textview_gpscoords, "gps cords");

        appWidgetManager.updateAppWidget(widgetId, remoteViews);
    }
}

protected PendingIntent getPendingSelfIntent(Context context, String action) {
    Intent intent = new Intent(context, getClass());
    intent.setAction(action);
    return PendingIntent.getBroadcast(context, 0, intent, 0);
}

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

    if (MyOnClick1.equals(intent.getAction())) {
        // your onClick action is here
        Toast.makeText(context, "Button1", Toast.LENGTH_SHORT).show();
        Log.w("Widget", "Clicked button1");
    } else if (MyOnClick2.equals(intent.getAction())) {
        Toast.makeText(context, "Button2", Toast.LENGTH_SHORT).show();
        Log.w("Widget", "Clicked button2");
    } else if (MyOnClick3.equals(intent.getAction())) {
        Toast.makeText(context, "Button3", Toast.LENGTH_SHORT).show();
        Log.w("Widget", "Clicked button3");
    }
};
}

My Android manifest:

<receiver
    android:name="widget.MyWidgetProvider"
    android:icon="@drawable/fsk"
    android:label="FSK Widget" >
    <intent-filter>
        <action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
    </intent-filter>

    <meta-data
        android:name="android.appwidget.provider"
        android:resource="@xml/example_appwidget_info" />
</receiver>

Solution

  • It is possible to make an onClick event for Views in Widgets. You can create as many onClick events as you want.

    On top of your Widget class, create a static variable, which will be your onClick name tag:

    private static final String MyOnClick = "myOnClickTag";
    

    Define a helper method to automate the creation of each PendingIntent:

    protected PendingIntent getPendingSelfIntent(Context context, String action) {
        Intent intent = new Intent(context, getClass());
        intent.setAction(action);
        return PendingIntent.getBroadcast(context, 0, intent, 0);
    }
    

    Set this onClick tag to your view as below:

        remoteViews.setOnClickPendingIntent(R.id.button, 
                          getPendingSelfIntent(context, MyOnClick));
    

    create an onReceive method in your Widget class and set this onClick event inside it:

    public void onReceive(Context context, Intent intent) {
    
        if (MyOnClick.equals(intent.getAction())){
            //your onClick action is here
        }
    };
    

    Whenever the view that you set the tag is pressed, onReceive will capture that and will do the action just the same as our everyday, standard onClick event.

    Edit: According to your answer, can you replace your onUpdate content with following lines and try again:

        RemoteViews remoteViews = new RemoteViews(context.getPackageName(),R.layout.widget_det);
        thisWidget = new ComponentName(context, MyWidgetProvider.class);    
        remoteViews.setOnClickPendingIntent(R.id.widget_button_stayarm, getPendingSelfIntent(context, MyOnClick1));
        remoteViews.setOnClickPendingIntent(R.id.widget_button_awayarm, getPendingSelfIntent(context, MyOnClick2));
        remoteViews.setOnClickPendingIntent(R.id.widget_button_dissarm, getPendingSelfIntent(context, MyOnClick3));
        remoteViews.setTextViewText(R.id.widget_textview_gpscoords, "gps cords");
        appWidgetManager.updateAppWidget(thisWidget, remoteViews);