I have a Flashlight widget that stops responding after the launcher is restarted, for example when date is changed in system, the launcher resets on my phone. According to this thread on SO: Link, I need to update the remoteView instead of creating new one every time. However I don't understand how to implement this in my code. I have a provider and a receiver for this.
Note: The widget starts working again after 30 mins as that is the time set for my widget to update in my appwidget-provider XML.
Provider:
public class WidgetProvider extends AppWidgetProvider {
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final int N = appWidgetIds.length;
for (int i = 0; i < N; i++) {
int appWidgetId = appWidgetIds[i];
Intent receiver = new Intent(context, FlashlightWidgetReceiver.class);
receiver.setAction("COM_FLASHLIGHT");
receiver.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, receiver, 0);
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.appwidget_layout);
views.setOnClickPendingIntent(R.id.imageButton, pendingIntent);
//appWidgetManager.updateAppWidget(appWidgetId, views);
appWidgetManager.partiallyUpdateAppWidget(appWidgetId, views);
}
}
}
Receiver:
public class FlashlightWidgetReceiver extends BroadcastReceiver {
private static boolean isLightOn = false;
private static Camera camera;
@Override
public void onReceive(Context context, Intent intent) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);
if (isLightOn) {
views.setImageViewResource(R.id.imageButton, R.drawable.btn_switch_off);
} else {
views.setImageViewResource(R.id.imageButton, R.drawable.btn_switch_on);
}
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(new ComponentName(context, WidgetProvider.class),
views);
if (isLightOn) {
if (camera != null) {
camera.stopPreview();
camera.release();
camera = null;
isLightOn = false;
}
} else {
// Open the default i.e. the first rear facing camera.
camera = Camera.open();
if (camera == null) {
Toast.makeText(context, "No Camera!", Toast.LENGTH_SHORT).show();
} else {
// Set the torch flash mode
Camera.Parameters param = camera.getParameters();
param.setFlashMode(Camera.Parameters.FLASH_MODE_TORCH);
try {
camera.setParameters(param);
camera.startPreview();
isLightOn = true;
} catch (Exception e) {
Toast.makeText(context, "No Camera!", Toast.LENGTH_SHORT).show();
}
}
}
}
}
Alright guys, I finally got time to fix this problem once and for all :)
I created more methods for the provider instead of doing everything in onUpdate, one important method needed:
public static PendingIntent buildButtonPendingIntent(Context context) {
Intent intent = new Intent();
intent.setAction("COM_FLASHLIGHT");
return PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
}
And this method is called through the receiver when the widget is clicked using the code below:
private void turnFlash(Context context) {
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.appwidget_layout);
views.setOnClickPendingIntent(R.id.imageButton, WidgetProvider.buildButtonPendingIntent(context));
}
That is all, no more hiccups!