Android widget interaction with service - android

Hello for all in 2013!
I have following android challenge:
Assume I have an app consisting of an activity and a widget. Both of these provide the same informations as actual as possible - so I have a service mining requested data and sending in message objects to the activity's or widget's handler, if possible. I'm OK with fact it causes large battery consumption and so on, it's not problem.
There are three possible layouts of the widgets. Current layout is determined on the fly (depends on data from the service) and setted via remoteviews.
Now my problem: I want to be able to toggle the service on/off by tapping on the widget. I have implemented PendingIntent as onClickPendingIntent (maybe the name is different, doesn't matter) and onReceive method to handle this one. It works pretty well but only for a while. After widget creation I'm able to trigger the intent by tapping the widget. But after a couple of minutes (nondeterministic) it makes nothing and the intent is not catch in onReceive anymore.
I have found in the log there is an intent ACTION_READY intent received in the widget before it stops responding my events. Is there any way to set the widget to listen for my touches anytime?
I have another problem with widget-zombie. I tried to google some doc about widgets, but not found any suitable document. If the system decide to kill my process, there will be still hanging dead widget UI on the screen. Its not responding any gestures and I guess it is not handling any messages too. Is there some chance to wake this widget programmaticaly (for example from the service)?
I will have second Christmas in two weeks if someone help me.
Lot of thanks!

Related

How to setup a background service on a geolocated app

I'm developing a geolocation based app for Android. I'm still beginning to understand how the framework works, so I'm not really sure if I'm doing things right.
The app has some custom View classes that are created within Activity classes and Layout components and mostly only render data. There is also a single Service that gets GPS updates using the Location API, read/write data, handle data and send it to the Views using Broadcasts. The Service is supposed to run as long as the app itself, but keep working on background indefinitely when the app is minimized.
The service is started on the base activity (which all activities extend) using:
startService(new Intent(BaseActivity.this, MyService.class));
It then proceeds to do its thing on an overrided onCreate method and periodically sends Broadcasts with data which the Activities and the Views listen to independently.
For me it seemed like a good setup, but I'm not sure since I started have some ANR problems after it's been started for some time (I let it sit overnight for testing and open it in the morning to an ANR screen).
I've read around about BoundServices and IntentServices, but it looked to me that my setup makes more sense (even though this whole thing is a bit confusing for me). So, am I in the right path? Or is this ANR error a warning to change it?

How to keep track of widgets when service is killed?

I am trying to fix somebody else's code and would like to have as few mods as possible. The project is a widget. The way the code is designed, there can be multiple instances of the widget added to the home screen. There is a service that receives broadcasts for actions in the widgets and deals with the broadcasts accordingly.
As there can be multiple instances of the widget, the service keeps track of the instances using a HashMap, mapping widget IDs to actual widgets. This works quite well until the service is killed (usually from the task manager). The next time a widget sends a broadcast, the service will be restarted (I haven't spent too much time understanding how it's restarted, but it does). However in killing/restarting the service, the map of widget IDs to actual widgets gets cleared, therefore the service doesn't know what widget is sending the broadcast and thus doesn't do anything.
What would be the best way to manage this situation? Somehow save/restore the map maybe?

Is there AppWidget callback for when an AppWidget is no longer visible?

I am updating my AppWidgets using a Service which listens to a pub/sub channel and essentially runs in the background forever, updating the AppWidgets whenever an update is received.
I am not concerned about battery life because the device is always plugged in, but I am concerned about CPU and memory usage by these background processes.
Is there a way I can get a notification that the AppWidget is no longer visible (e.g. when the home screen goes away or is swiped to another page)? I want to be able to toggle listening to the pub/sub channel if the AppWidget is not visible.
[Added]
Or, is there even a synchronous method I can call to check whether an AppWidget is currently visible?
There are ACTION_APPWIDGET_DELETED and ACTION_APPWIDGET_DISABLED broadcasts that tell when widget is deleted.
Alternatively you can also use AppWidgetProvider wrapper and implement onDelete() and onDisable() methods.

What does/does not belongs in WidgetProvider

Widget Provider is a specialized BroadcastReceiver.
Assuming there exists an Application, 1-n android service,1-k activities, and potentially additional 0-n broadcast receivers that are not widgets, I would like to verify what belongs and does not belong logically inside the broadcast receiver. Here are some items ..
And assuming that generally what gets launched is the widget first.
Please comment on any of the items as to whether they belong inside or outside the widget and why. Thanks.
1) If the application needs to always listen for certain events whether they show up in the widget or not where should this go? In the Widget? If not what would keep the broadcast receiver available to listen to the events for the application?
2) Should the widget issue notification? or request a service to issue them? ie should the notification logic reside in the widget itself or in the service.
3) Should the widget issue broadcasts or ask a service to do this?
4) Should the widget ever access any system services like like Notification Manager, PowerManager etc Why, Why not?
5) Should the widget keep any of its own state? If it should not keep state how can it change what it displays? Like a different text or icon?
6) Should the widget start off activities or let a service handle this?
7) is it ok to user the context passed to update and receiver or should one use ctx.getApplicationContext() to do things like context.startService? ( Perhaps the one passed in is the application context ? )
Quoting myself from your cross-post to the android-developers Google Group:
Your entire question is phrased around "the Widget". There is no "the
Widget". From the opening sentence of your question, I am interpreting
"the Widget" to mean "a subclass of AppWidgetProvider that handles the
processing for an app widget or family of app widget instances".
1) If the Application needs to always listen for certain events
whether they show up in the widget or not where should this go? In the
Widget?
There is no reason for an AppWidgetProvider to respond to other
broadcasts, since anything can update the app widget's RemoteViews.
And an AppWidgetProvider cannot register listeners (e.g.,
PhoneStateListener).
Hence, I would say the answer here is "no".
2) Should the widget issue notification? or request a service to issue
them? ie should the notification logic reside in the widget itself or
in the service.
Technically, AFAIK, raising a notification is cheap and therefore safe
for an AppWidgetProvider to do.
Logically, an AppWidgetProvider should never have any reason to raise
a notification, IMHO.
3) Should the widget issue broadcasts or ask a service to do this?
Technically, AFAIK, sending a broadcast is cheap and therefore safe
for an AppWidgetProvider to do.
Logically, an AppWidgetProvider should never have any reason to send
broadcasts, IMHO.
4) Should the widget ever access any system services like like
Notification Manager, PowerManager etc Why, Why not?
This cannot be answered in the abstract.
5) Should the widget keep any of its own state? If it should not keep
state how can it change what it displays? Like a different text or
icon?
It may need to. For example, suppose you have an app widget that shows
the weather for a certain city. The configuration activity for that
app widget allows the user to choose the city. Somewhere, you need to
store that city, and distinct from the cities that any other instance
of that app widget may need (e.g., user adds two copies of the app
widget to track weather in two cities).
6) Should the widget start off activities or let a service handle
this?
An AppWidgetProvider should never have a reason to directly "start off
activities", nor should a service triggered from an AppWidgetProvider
have any reason to directly "start off activities", IMHO.
However, either are perfectly welcome to create PendingIntents that
"start off activities" and attach them as click handlers for widgets
in an app widget's RemoteViews.
7) is it ok to user the context passed to update and receiver or
should one use ctx.getApplicationContext() to do things like
context.startService? ( Perhaps the one passed in is the application
context ? )
Most things you can just use the passed-in Context. One thing that
will not work for is using registerReceiver() with a null receiver to
get the last value of a sticky broadcast, such as
ACTION_BATTERY_CHANGED -- for that, you will need to use
getApplicationContext().

How does the Facebook for Android app's home screen widget work?

Actually this question applies to any widget that requires data from a remote server.
The answer would be pure speculation, but how do you think the widget gets its data? For those that don't know, the widget shows a history of your friends' latest status updates.
Some answers that I can think of:
The widget polls the API directly
The widget grabs data from some
service that's running in the
background, which polls the server
Somehow Facebook implemented push on
Android which I don't think exists
The widget somehow detects that the
user is using the screen and grabs
the data on demand
I would say #1 or #2. Most likely #2 for the reasons jleedev gives in his answer.
Note that to implement an app widget you extend AppWidgetProvider, which is a BroadcastReceiver. This is simply a class that runs in the background and pushes updates to the widget on screen via RemoteViews. So what you are seeing on your home screen isn't an actual running Activity, it's just a fairly static view that is updated periodically via a special BroadcastReceiver. I say all this to show that there isn't much difference between your #1 and #2, as all homescreen app widget code you write runs in the background.
Also you can't really do #4. You can't detect when an app widget is on screen, unfortunately. The best you can do currently is schedule alarms to update your app widget, and use the flag that keeps those alarms from firing when the phone is asleep.
The Android SDK documentation refers to the sample Simple Wiktionary AppWidget. This runs a service that periodically pulls data from the Internet and pushes it back to the widget. Full source code is available.
The documentation says
If your App Widget setup process can
take several seconds (perhaps while
performing web requests) and you
require that your process continues,
consider starting a Service in the
onUpdated() method... If you don't
update more than once per hour, this
probably won't cause significant
problems for the battery life.
The widget that I wrote runs a service that periodically pulls data from the internet and pushes it to the widget. That seems to work well.
I would assume #2. The activity and the widget need to display the same content, so it makes sense to have a single service to download and cache the data. Widgets are defined to update on a certain interval, but that doesn’t necessarily have to be the same as how often the service downloads the data. Most apps I have that refresh periodically have a setting to control the refresh frequency, and I imagine that would be a setting on the service.

Categories

Resources