Android-Widget : Calling BroadcastReceiver onReceive from onUpdate of Appwidgetprovider - android

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".

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.

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

Related

Android onReceive not called

I'm trying to follow this example:
What is the correct way for sharing data among AppWidgetProvider and RemoteViewsService.RemoteViewsFactory
As such, I have a RemoteViewsFactory that has this:
#Override
public void onDataSetChanged() {
// Subsequent calls to get the data.
newsGetter.updateListFeed(null, new NewsGetter.OnUpdateListFeedFinishedListener() {
#Override
public void onUpdateListFeedFinished(VolleyError error) {
//async return here from volley
Intent widgetUpdateIntent = new Intent(NewsWidgetBase.FEED_UPDATED);
widgetUpdateIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
LocalBroadcastManager.getInstance(context).sendBroadcast(widgetUpdateIntent);
}
});
Log.e(TAG, "******************************** onDataSetChanged PROVIDER");
}
Then I have an AppWidgetProvider that has this:
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action)) {
Log.e("WidgetBase", "******************************** onReceive ACTION_APPWIDGET_UPDATE");
} else if (FEED_UPDATED.equals(action)) {
Log.e("WidgetBase", "******************************** onReceive FEED_UPDATED");
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
updateAppWidget(context, appWidgetManager, appWidgetId);
}
super.onReceive(context, intent);
}
And in the manifest:
<receiver android:name=".widgets.a">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="com.myapp.FEED_UPDATED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/abc" />
</receiver>
I get the debugger log for ACTION_APPWIDGET_UPDATE, but for my own Intent broadcast, it never fires onReceive (breakpoint is never even hit). Does anyone see what I'm doing wrong?
For your own Intent broadcast to work, you have to register your BroadcastReceiver programmatically. So register your receiver as
LocalBroadcastManager.getInstance(this).registerReceiver(YourWidgetReceiver, new IntentFilter("your_intent_action"));
And then send your broadcast as
Intent intent = new Intent("your_intent_action");
LocalBroadcastManager.getInstance(getApplicationContext()).sendBroadcast(intent)
;
Hope this helps.

Android - Appwidget with Remoteviews not updating after reboot

I saw similar questions here on SO, but nothing seems to work in my case...
I created an appwidget with an AdapterViewFlipper (Simple ViewAnimator that will animate between two or more views that have been added to it). The appwidget has a Next button that enables the user to navigate to the next view on the widget.
It all works fine when I first add the appwidget. But if the smartphone reboots, the Next button of the widget no longer works on my Samsung S4 (the method onReceive is called, but nothings happens, it doesn't navigate to the next view and is stuck at the first view). I have to delete the widget and add it again in order for it to work...
I suspect that it is a problem of Touchwiz since I tested it on another phone (Moto G) and it worked fine.
Here are some portions of my code :
AppWidgetProvider
public class AppWidgetProvider extends AppWidgetProvider {
public static final String NEXT_ACTION = VersionUtil.getPackageName() + ".action.NEXT";
private static final String TAG = DailyAppWidget.class.getSimpleName();
#Override
public void onEnabled(Context context) {
// Enter relevant functionality for when the first widget is created
}
#Override
public void onDisabled(Context context) {
// Enter relevant functionality for when the last widget is disabled
}
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
// There may be multiple widgets active, so update all of them
for (int appWidgetId : appWidgetIds) {
updateAppWidget(context, appWidgetManager, appWidgetId, colorValue);
}
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
void updateAppWidget(Context context, AppWidgetManager appWidgetManager,
int appWidgetId, int primaryColor) {
Intent intent = new Intent(context, ViewFlipperWidgetService.class);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
// When intents are compared, the extras are ignored, so we need to embed the extras
// into the data so that the extras will not be ignored.
intent.setData(Uri.parse(intent.toUri(Intent.URI_INTENT_SCHEME)));
// Instantiate the RemoteViews object for the app widget layout.
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.app_widget);
// open the activity from the widget
Intent intentApp = new Intent(context, MainActivity.class);
intentApp.setFlags(Intent.FLAG_ACTIVITY_CLEAR_TOP | Intent.FLAG_ACTIVITY_NEW_TASK);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intentApp, 0);
rv.setOnClickPendingIntent(R.id.widget_title, pendingIntent);
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.ICE_CREAM_SANDWICH) {
rv.setRemoteAdapter(R.id.adapter_flipper, intent);
} else {
rv.setRemoteAdapter(appWidgetId, R.id.adapter_flipper, intent);
}
// Bind the click intent for the next button on the widget
final Intent nextIntent = new Intent(context,
AppWidgetProvider.class);
nextIntent.setAction(AppWidgetProvider.NEXT_ACTION);
nextIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_ID, appWidgetId);
final PendingIntent nextPendingIntent = PendingIntent
.getBroadcast(context, 0, nextIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.widget_btn_next, nextPendingIntent);
appWidgetManager.updateAppWidget(appWidgetId, mRemoteViews);
}
#TargetApi(Build.VERSION_CODES.HONEYCOMB)
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (action.equals(NEXT_ACTION)) {
RemoteViews rv = new RemoteViews(context.getPackageName(),
R.layout.daily_app_widget);
rv.showNext(R.id.adapter_flipper);
int appWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
Log.e(TAG, "onReceive APPWIDGET ID " + appWidgetId);
AppWidgetManager.getInstance(context).partiallyUpdateAppWidget(
appWidgetId, rv);
}
super.onReceive(context, intent);
}
Service
public class FlipperRemoteViewsFactory implements RemoteViewsService.RemoteViewsFactory {
private Context mContext;
private int mAppWidgetId = AppWidgetManager.INVALID_APPWIDGET_ID;
private static final String TAG = "FILPPERWIDGET";
public FlipperRemoteViewsFactory(Context context, Intent intent) {
mContext = context;
mAppWidgetId = intent.getIntExtra(AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
//... get the data
}
#Override
public void onCreate() {
Log.e(TAG, "onCreate()");
}
#Override
public void onDataSetChanged() {
Log.i(TAG, "onDataSetChanged()");
}
#Override
public void onDestroy() {
}
#Override
public int getCount() {
//... return size of dataset
}
#Override
public RemoteViews getViewAt(int position) {
Log.i(TAG, "getViewAt()" + position);
RemoteViews page = new RemoteViews(mContext.getPackageName(), R.layout.app_widget_item);
//... set the data on the layout
return page;
}
#Override
public RemoteViews getLoadingView() {
Log.i(TAG, "getLoadingView()");
return new RemoteViews(mContext.getPackageName(), R.layout.appwidget_loading);
}
#Override
public int getViewTypeCount() {
Log.i(TAG, "getViewTypeCount()");
return 1;
}
#Override
public long getItemId(int position) {
Log.i(TAG, "getItemId()");
return position;
}
#Override
public boolean hasStableIds() {
Log.i(TAG, "hasStableIds()");
return true;
}
}
Manifest
<receiver android:name=".AppWidgetProvider"
android:label="#string/app_name"
android:enabled="#bool/is_at_least_12_api">
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/app_widget_info" />
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
</receiver>
<!-- Service serving the RemoteViews to the collection widget -->
<service android:name=".ViewFlipperWidgetService"
android:permission="android.permission.BIND_REMOTEVIEWS"
android:exported="false" />
app wigdet info
<?xml version="1.0" encoding="utf-8"?>
<appwidget-provider xmlns:android="http://schemas.android.com/apk/res/android"
android:initialKeyguardLayout="#layout/app_widget"
android:initialLayout="#layout/app_widget"
android:minHeight="110dp"
android:minWidth="250dp"
android:previewImage="#drawable/widget_preview"
android:resizeMode="horizontal|vertical"
android:updatePeriodMillis="14400000"
android:widgetCategory="home_screen" />
Any help would be appreciated !
Depends on the launcher, there is no guarantee that your AppWidget will be updated immediately after the device started. It may be refreshed immeidately, or wait till the updatePeriodMillis passed after system started.
To solve your problem, define a BroadcastReceiver that will trigger the update of AppWidget after the reboot.
In AndroidManifest.xml, define the BootReceiver to get the boot_complete message.
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<receiver android:name=".BootReceiver" android:enabled="true" android:exported="false" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
And define the BootReceiver.java to start your AppWidgetUpdateService
public class BootReceiver extends BroadcastReceiver{
#Override
public void onReceive(Context context, Intent intent){
//start appwidget update service
}
}

Workaround for AppWidgetProvider's onEnabled & onDisabled is not being called

Since I'm using AlarmManager to perform periodical widget update, I need to ensure onEnabled & onDisabled will work reliably.
However, I realize they will not be triggered sometimes. I'm not the only one who is facing this problem.
Android appWidgetProvider onEnabled never called on tablet
Is there any official bug ticket submitted to Google Android team?
Is there any workaround, especially onDisabled? As I do not want AlarmManager still being triggered repeatably, after the last widget had been removed.
AndroidManifest.xml
<receiver android:name="org.yccheok.MyAppWidgetProvider"
android:exported="true" >
<intent-filter >
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
<action android:name="android.appwidget.action.APPWIDGET_ENABLED" />
<action android:name="android.appwidget.action.APPWIDGET_DELETED" />
<action android:name="android.appwidget.action.APPWIDGET_DISABLED" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/widget_info" />
</receiver>
public class MyAppWidgetProvider extends AppWidgetProvider {
private static PendingIntent createAlarmUpdatePendingIntent(Context context) {
Intent intent = new Intent(context, JStockAppWidgetProvider.class);
intent.setAction(JStockAppWidgetProvider.ALARM_UPDATE_ACTION);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
return pendingIntent;
}
#Override
public void onEnabled(Context context)
{
super.onEnabled(context);
PendingIntent pendingIntent = createAlarmUpdatePendingIntent(context);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
int scanSpeed = JStockApplication.instance().getJStockOptions().getScanSpeed();
alarmManager.setRepeating(AlarmManager.RTC, System.currentTimeMillis() + scanSpeed, scanSpeed, pendingIntent);
}
#Override
public void onDisabled(Context context)
{
super.onDisabled(context);
PendingIntent pendingIntent = createAlarmUpdatePendingIntent(context);
AlarmManager alarmManager = (AlarmManager)context.getSystemService(Context.ALARM_SERVICE);
alarmManager.cancel(pendingIntent);
}
you can check in method a number of instances that are currently running.
private boolean hasInstances(Context context) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(
new ComponentName(context, this.getClass()));
return (appWidgetIds.length > 0);
}
I afraid you have misunderstood the methods of AppWidgetProvider.
onDeleted(Context context, int[] appWidgetIds)
Called in response to the ACTION_APPWIDGET_DELETED broadcast **when one or more** AppWidget instances have been deleted. Override this method to implement your own AppWidget functionality.
onDisabled(Context context)
Called in response to the ACTION_APPWIDGET_DISABLED broadcast, which is sent when the last AppWidget instance for this provider is deleted. Override this method to implement your own AppWidget functionality.
In short, If you have two or more AppWidget instances then if you remove any of them at that time only onDeleted() method for particular widget will be called.
If you have only single AppWidget instance then if you remove that time onDesabled() and onDeleted() both will be called.
So you will have to move your code from onDesabled() method to onDeleted() method and it will get called every time.!
Also take care that onEnabled() will be called only for the first instance and not for every next instance you create.
For what I understood you just need one alarm, and I suppose all widgets will be all the same. So, the idea for your alarm is run on service, not on widget.
You shouldn't run long time actions on BroadcastReceiver.
We will use the onUpdate and not onEnable (because the design of this demo). Then aways we get a new widget we can perform the service.
AppWidgetProvider:
public class MyAppWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds)
{
ComponentName thisWidget = new ComponentName(context, MyAppWidgetProvider.class);
int[] allWidgetIds = appWidgetManager.getAppWidgetIds(thisWidget);
Intent intent = new Intent(context.getApplicationContext(), JStockAppWidgetService.class);
intent.setAction(JStockAppWidgetService.ALARM_UPDATE_ACTION);
intent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, allWidgetIds);
context.startService(intent);
}
#Override
public void onDisabled(Context context)
{
super.onDisabled(context);
Intent intent = new Intent(context.getApplicationContext(), JStockAppWidgetService.class);
intent.setAction(JStockAppWidgetService.ALARM_STOP_ACTION);
// I kept this just in case you wanna keep running your alarm without widget. You can just stopService here too.
context.startService(intent);
}
}
And here the Service:
public class JStockAppWidgetService extends Service {
public static final String ALARM_UPDATE_ACTION = "ALARM_UPDATE_ACTION";
public static final String ALARM_STOP_ACTION = "ALARM_STOP_ACTION";
//delay to refresh your widget
private int delay = 10000; //10 secs
private Thread myThread;
#Override
public void onStart(Intent intent, int startId) {
final int[] allWidgetIds = intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS);
final Handler handler = new Handler();
Runnable runnable = new Runnable() {
#Override
public void run() {
try {
//running your timeout while is not interrupted
while(!Thread.currentThread().isInterrupted()) {
//we need to back to GUI thread
handler.post(new Runnable() {
#Override
public void run() {
runInMyGuiThread(allWidgetIds);
}
});
//everybody needs to sleep sometime =p
Thread.sleep(delay);
}
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
e.printStackTrace();
}
}
};
String action = intent.getAction();
if(action == ALARM_UPDATE_ACTION) {
if(myThread != null)
myThread.interrupt();
myThread = new Thread(runnable);
myThread.start();
} else if(action == ALARM_STOP_ACTION && myThread != null) {
myThread.interrupt();
}
}
//here you are in GUI thread with all your widgets id
public void runInMyGuiThread(int[] allWidgetIds) {
for(int widgetId : allWidgetIds){
//do what you want to update each widget
}
}
#Override
public IBinder onBind(Intent intent) {
return null;
}
}
This is just a little demo, you can stop the service or keep it running without widget, I will let with you.
I was confused by the following situation.
If you have added the widget to the lock screen and then you are testing by adding and removing the widget to the home screen, then you never see onEnabled/onDisabled called. The reason is that there is still a widget added - the lock screen widget.

Flashlight widget does not turn off

I have created everything necessary for my widget to exist and function. Even so at the first click, t does what it is supposed to but then image gets changed and says problem, and does not function. I want it to open flash and then close it.
Help will be much appreciated.
FlashlightWidgetProvider
public class FlashlightWidgetProvider extends AppWidgetProvider {
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
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.flash_widget);
views.setOnClickPendingIntent(R.id.button, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
}
FlashlightWidgetReceiver
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.flash_widget);
if(isLightOn) {
views.setImageViewResource(R.id.button, R.drawable.off);
} else {
views.setImageViewResource(R.id.button, R.drawable.on);
}
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
appWidgetManager.updateAppWidget(new ComponentName(context, FlashlightWidgetProvider.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, R.string.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, R.string.no_flash, Toast.LENGTH_SHORT).show();
}
}
}
}
}
Make sure the button resource refers to an ImageView and not a regular Button. I just tried this out at first with a Button in my layout file and I was getting the same problem where the widget would basically crash and remove itself from the home screen. When I changed button to be an ImageView in the layout file, the code now works.
I did modify the code a bit from yours, so in case that doesn't work by itself, here is the updated FlashlightWidgetProvider:
public class FlashlightWidgetProvider extends AppWidgetProvider {
#Override
public void onReceive(Context context, Intent intent) {
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(intent.getAction())) {
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(context);
int[] appWidgetIds = appWidgetManager.getAppWidgetIds(new ComponentName(context, getClass()));
Intent broadcastIntent = new Intent(context, FlashlightWidgetReceiver.class);
broadcastIntent.setAction("COM_FLASHLIGHT");
broadcastIntent.putExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS, appWidgetIds);
PendingIntent pendingIntent = PendingIntent.getBroadcast(context,
0,
broadcastIntent,
PendingIntent.FLAG_UPDATE_CURRENT);
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.flashlight);
views.setOnClickPendingIntent(R.id.flashButton, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, views);
}
super.onReceive(context, intent);
}
}
Also, make sure to register the widget provider and receiver correctly in the manifest (replacing the relevant pieces with your own, of course):
<receiver
android:name="com.example.stackoverflowtester.widget.FlashlightWidgetProvider"
android:label="Flashlight" >
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data
android:name="android.appwidget.provider"
android:resource="#xml/flashlight_widget_provider" />
</receiver>
<receiver android:name="com.example.stackoverflowtester.widget.FlashlightWidgetReceiver" >
<intent-filter>
<action android:name="COM_FLASHLIGHT" />
</intent-filter>
</receiver>

Android widget, start intent

I'm trying to make an Android widget, to show some info from my app.
I have succeed to show some info, but know i what to have a feature to "switch page" in my app. It means pressing a button, and new info is showing. But how do i do it? I have tried different thing, and I'm ending up with the following code:
public class HelloWidget extends AppWidgetProvider {
RemoteViews remoteViews;
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds) {
Toast.makeText(context, "onUpdate", Toast.LENGTH_SHORT).show();
RemoteViews remoteViews = new RemoteViews(context.getPackageName(), R.layout.widget_layout);
Intent intent = new Intent();
intent.setAction(TestReceiver.TEST_INTENT);
intent.setClassName(TestReceiver.class.getPackage().getName(), TestReceiver.class.getName());
PendingIntent pendingIntent = PendingIntent.getBroadcast(context.getApplicationContext(), 0, intent, PendingIntent.FLAG_CANCEL_CURRENT);
remoteViews.setOnClickPendingIntent(R.id.bbutton1, pendingIntent);
remoteViews.setTextViewText(R.id.widgetTxt, "The textview");
appWidgetManager.updateAppWidget(appWidgetIds[0], remoteViews);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
public class TestReceiver extends BroadcastReceiver {
public static final String TEST_INTENT = "MyTestIntent";
#Override
public void onReceive(Context context, Intent intent) {
Toast.makeText(context, "You reached the TestReceiver", Toast.LENGTH_SHORT).show();
if (intent.getAction() == TEST_INTENT) {
remoteViews.setTextViewText(R.id.widgetTxt, "Is changed");
}
}
}
#Override
public void onReceive(Context context, Intent intent) {
final String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_DELETED.equals(action)) {
final int appWidgetId = intent.getExtras().getInt(
AppWidgetManager.EXTRA_APPWIDGET_ID,
AppWidgetManager.INVALID_APPWIDGET_ID);
if (appWidgetId != AppWidgetManager.INVALID_APPWIDGET_ID) {
this.onDeleted(context, new int[] { appWidgetId });
}
} else {
super.onReceive(context, intent);
}
}
#Override
public void onDeleted(Context context, int[] appWidgetIds) {
Toast.makeText(context, "onDelete", Toast.LENGTH_SHORT).show();
super.onDeleted(context, appWidgetIds);
}
}
Toast are showing "onUpdate" and then i remove it at "onDeleted". The textview also change in the onUpdate, but nothing happens when i press the button.
My Manifest look like this:
<receiver android:name=".HelloWidget" android:label="#string/app_name">
<intent-filter>
<action android:name="android.appwidget.action.APPWIDGET_UPDATE" />
</intent-filter>
<meta-data android:name="android.appwidget.provider"
android:resource="#xml/hello_widget_provider" />
</receiver>
<receiver android:name=".TestReceiver" android:label="#string/app_name">
<intent-filter>
<action android:name="MyTestIntent">
</action>
</intent-filter>
</receiver>
What am i doing wrong?
Thanks
Is your TestReceiver an inner class of HelloWidget?
Then you didn't specify the correct name in the manifest.

Categories

Resources