androidandroid-intentandroid-widgetandroid-serviceandroid-broadcast

Android Widget Update service, multiple onclick listeners


I have the following widget service which updates a text view when I click on my one button.

UpdateWidgetService:

ipublic class UpdateWidgetService extends Service {

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

static LocationClient mLocationClient;

@Override
public void onStart(Intent intent, int startId) {

    Log.i(LOG, "Called and started");

    AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext());
    int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);

    ComponentName thisWidget = new ComponentName(getApplicationContext(), MyWidgetProvider.class);
    int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
    Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
    Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));

    for (int widgetId : allWidgetIds) {
        // create some random data
        int number = (new Random().nextInt(100));

        RemoteViews remoteViews = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.widget_layout);
        Log.w("WidgetExample", String.valueOf(number));
        // Set the text
        remoteViews.setTextViewText(R.id.widget_textview_gpscoords, "Random: " + String.valueOf(number));

        // Register an onClickListener
        Intent clickIntent = new Intent(this.getApplicationContext(), MyWidgetProvider.class);

        clickIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
        clickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);

        PendingIntent pendingIntent = PendingIntent.getBroadcast(getApplicationContext(), 0, clickIntent, PendingIntent.FLAG_UPDATE_CURRENT);
        remoteViews.setOnClickPendingIntent(R.id.widget_button_dissarm, pendingIntent);
        appWidgetManager.updateAppWidget(widgetId, remoteViews);
    }
    stopSelf();
    super.onStart(intent, startId);
}

@Override
public IBinder onBind(Intent intent) {
    return null;
}

}

MyWidget Provider:

public class MyWidgetProvider extends AppWidgetProvider {

private static final String LOG = "de.vogella.android.widget.example";

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

    Log.w(LOG, "onUpdate method called");
    // Get all ids
    ComponentName thisWidget = new ComponentName(context, MyWidgetProvider.class);
    int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);

    // Build the intent to call the service
    Intent intent = new Intent(context.getApplicationContext(), UpdateWidgetService.class);
    intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);

    // Update the widgets via the service
    context.startService(intent);
        }
}

android manifest:

<!-- Widget -->
    <receiver
        android:name="widget.MyWidgetProvider"
        android:icon="@drawable/icon"
        android:label="My 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>
    <meta-data
        android:name="com.google.android.gms.version"
        android:value="@integer/google_play_services_version" />
    <!-- Services -->
    <service android:name="widget.UpdateWidgetService" >
    </service>

Now my issue is that, how do I determine which button gets clicked? I have 4 buttons on my widget and I want to differentiate between which ones are clicked? In my example the intent for the buttons onclick is ACTION_APPWIDGET_UPDATE Im thinking I need to change that some how?

What is the correct way to go about doing this?

Ultimately my buttons are each going to make a webcall, this is why I am using the service, as the web call can take some time.


Solution

  • I would change your UpdateWidgetService.java as the code below.

    public class UpdateWidgetService extends Service {
    
    private static final String LOG = "widgetService";
    
    // my changes - part 1 - beginning
    private static final String BUTTON_ONE_CLICKED = "com.yourpackage.BUTTON_ONE_CLICKED";
    private static final String BUTTON_TWO_CLICKED = "com.yourpackage.BUTTON_TWO_CLICKED";
    private static final String BUTTON_THREE_CLICKED = "com.yourpackage.BUTTON_THREE_CLICKED";
    private static final String BUTTON_FOUR_CLICKED = "com.yourpackage.BUTTON_FOUR_CLICKED";
    // my changes - part 1 - end
    
    
    @Override
    public void onStart(Intent intent, int startId) {
    
        Log.i(LOG, "Called and started");
        
        // my changes - part 2 - beginning
        if(BUTTON_ONE_CLICKED.equals(intent.getAction())) {
            // do what should be done if button One has been clicked
        }
        if(BUTTON_TWO_CLICKED.equals(intent.getAction())) {
            // do what should be done if button Two has been clicked
        }
        if(BUTTON_THREE_CLICKED.equals(intent.getAction())) {
            // do what should be done if button Three has been clicked
        }
        if(BUTTON_FOUR_CLICKED.equals(intent.getAction())) {
            // do what should be done if button Four has been clicked
        }
        // my changes - part 2 - end
    
        AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this.getApplicationContext());
        int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
    
        ComponentName thisWidget = new ComponentName(getApplicationContext(), MyWidgetProvider.class);
        int[] allWidgetIds2 = appWidgetManager.getAppWidgetIds(thisWidget);
        Log.w(LOG, "From Intent" + String.valueOf(allWidgetIds.length));
        Log.w(LOG, "Direct" + String.valueOf(allWidgetIds2.length));
    
        for (int widgetId : allWidgetIds) {
            // create some random data
            int number = (new Random().nextInt(100));
    
            RemoteViews remoteViews = new RemoteViews(this.getApplicationContext().getPackageName(), R.layout.widget_layout);
            Log.w("WidgetExample", String.valueOf(number));
            // Set the text
            remoteViews.setTextViewText(R.id.widget_textview_gpscoords, "Random: " + String.valueOf(number));
            
            // my changes - part 3 - beginning
            Context context = getApplicationContext();
            
            Intent buttonOneIntent = new Intent(context, UpdateWidgetService.class);
            Intent buttonTwoIntent = new Intent(context, UpdateWidgetService.class);
            Intent buttonThreeIntent = new Intent(context, UpdateWidgetService.class);
            Intent buttonFourIntent = new Intent(context, UpdateWidgetService.class);
            
            // set action
            buttonOneIntent.setAction(BUTTON_ONE_CLICKED);
            buttonTwoIntent.setAction(BUTTON_TWO_CLICKED);
            buttonThreeIntent.setAction(BUTTON_THREE_CLICKED);
            buttonFourIntent.setAction(BUTTON_FOUR_CLICKED);
            
            // put widgetId
            buttonOneIntent.putExtra("widgetId", widgetId);
            buttonTwoIntent.putExtra("widgetId", widgetId);
            buttonThreeIntent.putExtra("widgetId", widgetId);
            buttonFourIntent.putExtra("widgetId", widgetId);
            
            // make these intents unique to avoid collisions
            buttonOneIntent.setData(Uri.withAppendedPath(Uri.parse("webcall_widget://buttonone/widgetid"), String.valueOf(widgetId)));
            buttonTwoIntent.setData(Uri.withAppendedPath(Uri.parse("webcall_widget://buttontwo/widgetid"), String.valueOf(widgetId)));
            buttonThreeIntent.setData(Uri.withAppendedPath(Uri.parse("webcall_widget://buttonthree/widgetid"), String.valueOf(widgetId)));
            buttonFourIntent.setData(Uri.withAppendedPath(Uri.parse("webcall_widget://buttonfour/widgetid"), String.valueOf(widgetId)));
            
            // pending intents
            PendingIntent buttonOnePendingIntent = PendingIntent.getService(context, 0, buttonOneIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            PendingIntent buttonTwoPendingIntent = PendingIntent.getService(context, 0, buttonTwoIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            PendingIntent buttonThreePendingIntent = PendingIntent.getService(context, 0, buttonThreeIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            PendingIntent buttonFourPendingIntent = PendingIntent.getService(context, 0, buttonFourIntent, PendingIntent.FLAG_UPDATE_CURRENT);
            
            // register onClickListeners to your buttons
            remoteViews.setOnClickPendingIntent(R.id.button_one, buttonOnePendingIntent);
            remoteViews.setOnClickPendingIntent(R.id.button_two, buttonTwoPendingIntent);
            remoteViews.setOnClickPendingIntent(R.id.button_three, buttonThreePendingIntent);
            remoteViews.setOnClickPendingIntent(R.id.button_four, buttonFourPendingIntent);
            // my changes - part 3 - end
    
            appWidgetManager.updateAppWidget(widgetId, remoteViews);
        }
        stopSelf();
        super.onStart(intent, startId);
    }
    
    @Override
    public IBinder onBind(Intent intent) {
        return null;
    }
    }
    

    If something is unclear do not hesitate and ask me please.