package com.kuxhausen.huemore.widget; import android.app.PendingIntent; import android.appwidget.AppWidgetManager; import android.appwidget.AppWidgetProvider; import android.content.ComponentName; import android.content.ContentResolver; import android.content.Context; import android.content.Intent; import android.database.ContentObserver; import android.net.Uri; import android.os.Bundle; import android.os.Handler; import android.os.HandlerThread; import android.widget.RemoteViews; import com.kuxhausen.huemore.R; import com.kuxhausen.huemore.net.ConnectivityService; import com.kuxhausen.huemore.persistence.Definitions.GroupColumns; import com.kuxhausen.huemore.persistence.Definitions.InternalArguments; /** * Our data observer just notifies an update for all group widgets when it detects a change. */ class SmallGroupDataProviderObserver extends ContentObserver { private AppWidgetManager mAppWidgetManager; private ComponentName mComponentName; SmallGroupDataProviderObserver(AppWidgetManager mgr, ComponentName cn, Handler h) { super(h); mAppWidgetManager = mgr; mComponentName = cn; } @Override public void onChange(boolean selfChange) { // The data has changed, so notify the widget that the collection view needs to be updated. // In response, the factory's onDataSetChanged() will be called which will requery the // cursor for the new data. mAppWidgetManager.notifyAppWidgetViewDataChanged( mAppWidgetManager.getAppWidgetIds(mComponentName), R.id.group_list); } } public class SmallGroupWidgetProvider extends AppWidgetProvider { private static HandlerThread sWorkerThread; private static Handler sWorkerQueue; private static SmallGroupDataProviderObserver sDataObserver; public SmallGroupWidgetProvider() { // Start the worker thread sWorkerThread = new HandlerThread("SmallGroupWidgetProvider-worker"); sWorkerThread.start(); sWorkerQueue = new Handler(sWorkerThread.getLooper()); } @Override public void onEnabled(Context context) { // Register for external updates to the data to trigger an update of the widget. When using // content providers, the data is often updated via a background service, or in response to // user interaction in the main app. To ensure that the widget always reflects the current // state of the data, we must listen for changes and update ourselves accordingly. final ContentResolver r = context.getContentResolver(); if (sDataObserver == null) { final AppWidgetManager mgr = AppWidgetManager.getInstance(context); final ComponentName cn = new ComponentName(context, SmallGroupWidgetProvider.class); sDataObserver = new SmallGroupDataProviderObserver(mgr, cn, sWorkerQueue); r.registerContentObserver(GroupColumns.URI, true, sDataObserver); } } @Override public void onReceive(Context ctx, Intent intent) { final String action = intent.getAction(); if (action.equals(InternalArguments.CLICK_ACTION)) { String group = intent.getStringExtra(InternalArguments.GROUP_NAME); String mood = intent.getStringExtra(InternalArguments.MOOD_NAME); Intent trasmitter = new Intent(ctx, ConnectivityService.class); trasmitter.putExtra(InternalArguments.MOOD_NAME, mood); trasmitter.putExtra(InternalArguments.GROUP_NAME, group); ctx.startService(trasmitter); } super.onReceive(ctx, intent); } private RemoteViews buildLayout(Context context, int appWidgetId) { RemoteViews rv; // Specify the service to provide data for the collection widget. Note that we need to // embed the appWidgetId via the data otherwise it will be ignored. rv = new RemoteViews(context.getPackageName(), R.layout.widget_small_group_layout); final Intent intent = new Intent(context, SmallGroupWidgetService.class); intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME))); rv.setRemoteAdapter(appWidgetId, R.id.group_list, intent); // Set the empty view to be displayed if the collection is empty. It must be a sibling // view of the collection view. rv.setEmptyView(R.id.group_list, R.id.empty_view); final Intent onClickIntent = new Intent(context, SmallGroupWidgetProvider.class); onClickIntent.setAction(InternalArguments.CLICK_ACTION); onClickIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId); onClickIntent.setData(Uri.parse(onClickIntent.toUri(Intent.URI_INTENT_SCHEME))); final PendingIntent onClickPendingIntent = PendingIntent.getBroadcast(context, 1, onClickIntent, PendingIntent.FLAG_UPDATE_CURRENT); rv.setPendingIntentTemplate(R.id.group_list, onClickPendingIntent); return rv; } @Override public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) { // Update each of the widgets with the remote adapter for (int i = 0; i < appWidgetIds.length; ++i) { RemoteViews layout = buildLayout(context, appWidgetIds[i]); appWidgetManager.updateAppWidget(appWidgetIds[i], layout); } super.onUpdate(context, appWidgetManager, appWidgetIds); // wtf another google bug? this.onEnabled(context); } @Override public void onAppWidgetOptionsChanged(Context context, AppWidgetManager appWidgetManager, int appWidgetId, Bundle newOptions) { RemoteViews layout; layout = buildLayout(context, appWidgetId); appWidgetManager.updateAppWidget(appWidgetId, layout); } }