Reputation: 3852
I am making a flashlight widget which will toggle the flashlight on/off and also I am trying to toggle the icon of the widget-button on clicking the widget button, for this I have the Appwidgetprovider whose onUpdate will use RemoteViews and call the BroadcastReceiver.
In the BroadcastReceiver, the onReceive function will perform the flashlight toggle and the icon toggle for the widget. The issue I am facing is that the onReceive function is not being called and no action happening with the widget.
below is the code:
AppWidgetProvider class:
public class WidgetActivity extends AppWidgetProvider {
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Intent receiver = new Intent(context, WidgetActivity.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.widget_flash_layout);
views.setOnClickPendingIntent(R.id.imageButton1, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
}
BroadcastReceiver Class:
public class WidgetService extends BroadcastReceiver {
private static boolean isLightOn = false;
private static Camera camera;
@Override
public void onReceive(Context context, Intent intent) {
// TODO Auto-generated method stub
RemoteViews views = new RemoteViews(context.getPackageName(),
R.layout.widget_flash_layout);
if (isLightOn) {
views.setImageViewResource(R.id.imageButton1,
R.drawable.light_off_widget);
} else {
views.setImageViewResource(R.id.imageButton1,
R.drawable.light_on_widget);
}
AppWidgetManager appWidgetManager = AppWidgetManager
.getInstance(context);
appWidgetManager.updateAppWidget(new ComponentName(context,
WidgetActivity.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
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 flash", Toast.LENGTH_SHORT)
.show();
}
}
}
}
}
Manifest:
<receiver android:name="com.widget.WidgetActivity">
<intent-filter>
<action
android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="@xml/flash_widget" />
</receiver>
<receiver android:name="com.widget.WidgetService">
<action android:name="COM_FLASHLIGHT"></action>
</receiver>
In the manifest I have not wrapped the <action>
tag of the widget service with
<intent-filter>
as it was showing a warning saying "Exported receiver does not require permission".
Upvotes: 1
Views: 8696
Reputation: 290
if you read the documentation, onDataSetChanged in RemoteViewsService, is called when notifyDataSetChanged() is triggered.
so, if you wanna update your WidgetService from onReceive() method, you can call notifyAppWidgetViewDataChanged() method from AppWidgetManager
@Override
public void onReceive(Context context, Intent intent) {
super.onReceive(context, intent);
int[] ids = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
AppWidgetManager.getInstance(context)
.notifyAppWidgetViewDataChanged(ids, R.id.stack_view_movies);
}
Upvotes: 0
Reputation: 17085
onReceive function is not being called and no action happening with the widget
Your intent component class
should be the Broadcast Receiver class
, not the WidgetProvider
Change this
Intent receiver = new Intent(context, WidgetActivity.class);
to
Intent receiver = new Intent(context, WidgetService.class);
When you use PendingIntent.getBroadcast
it expect the Intent to be broadcast
. So when you click on the button in the widget
, the Broadcast Receiver
onResume
will get called.
You don't really need to set any Action
here for the receiver
.
But if you want to use a custom Intent
, then you can set the Intent action
like this
Intent receiver = new Intent("COM_FLASHLIGHT");
and your receiver in manifest
should register with intent-filter
to handle the custom action.
<receiver android:name=".services.WidgetService">
<intent-filter>
<action android:name="COM_FLASHLIGHT"></action>
</intent-filter>
</receiver>
So, when the BroadCast Receiver
onReceive
get called, you can check for the specific action like this
public class WidgetService extends BroadcastReceiver {
@Override
public void onReceive(Context context, Intent intent) {
if(intent.getAction().equalsIgnoreCase("COM_FLASHLIGHT")){
// do your stuff for this action.
}
}
Custom Actions
are normally defined when you have multiple actions in a RemoteView
.
Upvotes: 6