How to start a service from App Widget in Android - android

I am making a home screen App Widget for my Android app. In that App Widget there is a ListView. That ListView has a custom layout which has a TextView & an ImageButton. I am setting a PendingIntent on that ImageButton to start the service as follows:
Intent intent = new Intent(mContext, MyService.class);
intent.putExtra(MyConstants.MY_EXTRA, c.getString(c.getColumnIndex(MyColumns.MY_COLUMN_TITLE)));
intent.setAction(MyConstants.MY_ACTION);
PendingIntent pendingIntent = PendingIntent.getService(mContext, 0, intent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.MyImageButton, pendingIntent);
in getViewAt method of RemoteViewsFactory. But on clicking the ImageButton the service does not start.
I have put an intentfilter with MY_ACTION for MyService. And also tried without it which did not make things work.
Anyone knows how to start service on click of a button inside a list view item in home screen App Widget in Android?
Everything works fine i.e. the ListView is populated perfectly from SQLite database.

From the android javadoc
public void setOnClickPendingIntent
Equivalent to calling
setOnClickListener(android.view.View.OnClickListener) to launch the
provided PendingIntent. When setting the on-click action of items
within collections (eg. ListView, StackView etc.), this method will
not work. Instead, use {#link
RemoteViews#setPendingIntentTemplate(int, PendingIntent) in
conjunction with RemoteViews#setOnClickFillInIntent(int, Intent).
In your update method of your AppWidgetProvider you have to add
final PendingIntent clickPendingIntentTemplate = PendingIntent.getService...
views.setPendingIntentTemplate(R.id.widget_list, clickPendingIntentTemplate);
and in the getViewAt method of your RemoteViewsFactory :
final Intent fillInIntent = new Intent();
fillInIntent.putExtra(...);
views.setOnClickFillInIntent(R.id.widget_list_item, fillInIntent);

Related

Update WidgetList View

I have a problem updating my Widget ListView, I don't need it to be updated automatically i need to update It according to a button Click in my App which calls an intent services that should update data.
the widget is updated correctly for the first time to click the button only,
and in other clicks Logs shows that data changes correctly but the view is not updated.
i had tried may solution from stackoverflow but all of them didn't work.
note
i don't want to use any database of sharedpreferences
and here is my code gitHub repo for my widget classes
https://github.com/abdelmun3m/BackingApp/tree/master/app/src/main/java/com/abdelmun3m/backingapp/widget
Have you added a PendingIntent on the button that is manually updating the widget, when you create the RemoteViews? This PendingIntent will trigger an onUpdate call on your WidgetPRovider. From there you can spawn the IntentService.
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.your_widget_layout);
...
// Initialize listview here
...
Intent refreshIntent = new Intent(context,YourWidgetProvider.class);
refreshIntent.setAction(AppWidgetManager.ACTION_APPWIDGET_UPDATE);
PendingIntent refreshPendingIntent = PendingIntent.getBroadcast(context, REFRESH_PENDING_INTENT_ID, refreshIntent, PendingIntent.FLAG_UPDATE_CURRENT);
rv.setOnClickPendingIntent(R.id.your_refresh_button_id, refreshPendingIntent);

Simple widget with a button to call an activity, or icons on home screen to call activities

Is there any work around to call an activity directly from a button on a widget? Like a beautiful button to launch the app.
From the doc and some answers here, views.setOnClickPendingIntent is the only way and that requires a service. But I don't need a service cause I'm not really updating the widget!
Actually, my original task is quite simple. I want an icon on home screen that calls an activity, but I don't want that icon appears in app-drawer. I know I can put a lot of activity icons in app-drawer.
You dont need a service for that.
You should just setOnClickPendingIntent in the onUpdate method in your AppWidgetProvider.
here are some links that show how it can be done, they are basically the same with some variations, you should try them out:
Start activity by clicking on widget
Launching activity from widget
How do I run an Activity from a button on a widget in Android?
How Do I Launch an Activity with Home Widget
Like i said there is no need for a service.
here is the sample code i used:
#Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager, int[] appWidgetIds){
RemoteViews remoteViews=new RemoteViews(context.getPackageName(), R.layout.testwidget);
//Intent set with the activity you want to start
Intent intent = new Intent(context, MainActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
remoteViews.setOnClickPendingIntent(R.id.textView1, pendingIntent);
appWidgetManager.updateAppWidget(appWidgetIds, remoteViews);
}

Messenger disappears from bundle onCreate

I'm trying to use Messenger as an IPC mechanism between my appwidget and an activity.
I do the following:
I create an intent that starts a specific activity when a button is clicked on my appwidget.
intent = new Intent(mContext, TorchLightActivity.class);
intent.putExtra(RPC, new Messenger(mHandler));
intent.putExtra(TYPE, mType);
...
final PendingIntent actionPendingIntent = PendingIntent.getActivity(mContext, 0, intent, 0);
remoteView.setOnClickPendingIntent(layout, actionPendingIntent);
When I click on my widget button an activity is started
onCreate(...)
final Bundle bun = getIntent().getExtras();
// Get null here
mMessanger = (Messenger) bun.get(FlashlightModule.RPC);
// Working great
mType = bun.getInt(FlashlightModule.Type);
When looking at the bundle I can see that the only extra data I have is FlashlightModule.Type e.g. the int value.
The intent is created with extras from the start (see Get the intent from onCreate in Android ) and setData is used from the start (see Application widget with bundle?)
Is it possible at all to pass Messenger between AppWidget to my own activity?
Thank you.
I'm trying to use Messenger as an IPC mechanism between my appwidget and an activity.
This makes no sense.
Your AppWidgetProvider instance will live for a couple of milliseconds -- any longer, and you're doing it wrong. It will never have an opportunity to use "IPC" with your activity, via Messenger or any other means.
Moreover, you should never create something from a BroadcastReceiver (such as an AppWidgetProvider) that you are expecting to live past the end of onReceive() (on onUpdate() for the AppWidgetProvider), such as your Handler, let alone the Messenger.
When your activity wishes to update the app widget's UI, it can create the RemoteViews and update the app widget.

Launching an activity from an AppWidget

How do i launch an activity from an AppWidget? I want to give the user the ability to edit its settings.
All the AppWidget methods have a Context: you can use that to create an Intent to launch your Activity.
EDIT: strictly speaking, you don't even need the Context (just create an Intent and then call startActivity).
you can find a lot of examples around the internet this example is excellent courtesy of Mark Murphy
https://github.com/commonsguy/cw-advandroid/tree/master/AppWidget
You have to do something like this:
Intent intent = new Intent(context, MainWidgetActivity.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, intent, 0);
// Get the layout for the App Widget and attach an on-click listener
// to the button
RemoteViews rv = new RemoteViews(context.getPackageName(), R.layout.appwidget);
rv.setOnClickPendingIntent(R.id.button, pendingIntent);
while MainWidgetActivity.class is the Activity you want to launch

logging to a database when user clicks on a widget

I have a widget that displays an analog clock. What I would like is for the the widget to write to a database the time when a user clicks on the widget. I've already got the databaseHelper class and have an Activity that displays a screen showing the current date and time and writes the time to a database.
I followed the tutorial here: Analog Clock Tutorial and ended up with this:
public void onReceive(Context context, Intent intent)
{
String action = intent.getAction();
if (AppWidgetManager.ACTION_APPWIDGET_UPDATE.equals(action))
{
RemoteViews views = new RemoteViews(context.getPackageName(), R.layout.widget);
this.mIntent = new Intent(context, AskTheTime.class);
PendingIntent pendingIntent = PendingIntent.getActivity(context, 0, mIntent, 0);
views.setOnClickPendingIntent(R.id.Widget, pendingIntent);
AppWidgetManager.getInstance(context).updateAppWidget(intent.getIntArrayExtra(AppWidgetManager.EXTRA_APPWIDGET_IDS), views);
}
}
The AskTheTime class extends activity and logs to the database in onCreate(). But this means that it displays only the time when the widget was started - not when it was clicked. (I guess this is because I'm starting a pendingIntent) I'm not sure If I should put the database write in another method or if I should be using Intents to do this sort of thing from widgets. Any pointers would be great! I've look at several tutorials for intents but none of them seem very clear to me.
When your widget is pressed, the OS activates the pending intent you set on the widget.
It looks like you are opening an activity AskTheTime when the widget is pressed.
So the problem is that AskTheTime might have already been created when the widget is pressed, so the onCreate() isn't called again.
What you could do is try doing your logging in onStart() or onResume() instead of, or in addition to, onCreate() inside your activity.
From the documentation regarding onStart:
Called when the activity is becoming
visible to the user.
And onResume:
Called when the activity will start
interacting with the user. At this
point your activity is at the top of
the activity stack, with user input
going to it.

Categories

Resources