Reputation: 1434
I am creating a homescreen widget in android. The widget provider starts a service which will update the widgets every 5 minutes. When i remove the widget from the homescreen, i cancel the service in 'onDisabled()' method of widget provider. But the service is null and the service keeps running in the background forever! I have no clue why this is null. Any ideas of how to do this? Also can i have a single service instance for all widget instances?
My widget provider
public class MyWidgetProvider extends AppWidgetProvider {
private PendingIntent service = null;
@Override
public void onUpdate(Context context, AppWidgetManager appWidgetManager,
int[] appWidgetIds) {
final AlarmManager m = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
final Calendar TIME = Calendar.getInstance();
TIME.set(Calendar.MINUTE, 0);
TIME.set(Calendar.SECOND, 0);
TIME.set(Calendar.MILLISECOND, 0);
final Intent i = new Intent(context, UpdatorService.class);
i.putExtra("WIDGET_IDS", appWidgetIds);
if (service == null) {
service = PendingIntent.getService(context, 0, i,
PendingIntent.FLAG_UPDATE_CURRENT);
}
m.setRepeating(AlarmManager.RTC, TIME.getTime().getTime(), 60 * 1000,
service);
super.onUpdate(context, appWidgetManager, appWidgetIds);
}
@Override
public void onDisabled(Context context) {
final AlarmManager m = (AlarmManager) context
.getSystemService(Context.ALARM_SERVICE);
Log.d("onDisabled() >>> ", service + "");
if (service != null) {
Log.d("WIDGET>>>", "Cancelling the service");
m.cancel(service);
service.cancel();
}
}
}
UpdatorService
public class UpdatorService extends Service {
@Override
public void onCreate() {
super.onCreate();
}
@Override
public int onStartCommand(Intent intent, int flags, int startId) {
int[] widgetIds = (int[]) intent.getExtras().get("WIDGET_IDS");
for (int i = 0; i < widgetIds.length; i++) {
SharedPreferences prefs = getSharedPreferences("PREFS_"
+ widgetIds[i], Context.MODE_PRIVATE);
if (prefs != null) {
//something logic here
//This is a async task to get http data
new RequestTask(this, parameterMap, widgetIds[i]).execute();
}
}
return START_NOT_STICKY;
}
private void buildUpdate(int widgetId, String result) {
ChartRenderer ch = new ChartRenderer();
GraphicalView gview=ch.generateChart(result, this);
RemoteViews views = new RemoteViews(getPackageName(),
R.layout.bw_widget_layout);
views.setBitmap(R.id.chart, "setImageBitmap", ch.getBitmapFromView(gview));
AppWidgetManager appWidgetManager = AppWidgetManager.getInstance(this);
appWidgetManager.updateAppWidget(widgetId, views);
}
@Override
public IBinder onBind(Intent intent) {
return null;
}
public void processResult(String result, int widgetId) {
buildUpdate(widgetId, result);
}
}
RequestTask
class RequestTask extends AsyncTask<String, String, String> {
private UpdatorService service;
private Map<String, String> paramMap;
int widgetId;
RequestTask(UpdatorService service, Map<String, String> paramMap, int wid) {
this.service = service;
this.paramMap = paramMap;
widgetId = wid;
}
@Override
protected String doInBackground(String... uri) {
.......
return responseString;
}
@Override
protected void onPostExecute(String result) {
super.onPostExecute(result);
service.processResult(result, widgetId);
}
}
Upvotes: 0
Views: 294
Reputation: 13541
First of all, you shouldn't pass the service to your RequestTask, that is bad design.
You should be using an Intent to send an update to your provider, if you look at the sample widgets they follow this same behavior. Also your service is poorly written, you should stop yourself IMMEDIATELY after you have finished your work instead of stopping it from the application, its more efficient and its cleaner for the service state maintenance.
The entire idea of a service is this (in your case):
Do work and then stop
Intent request starts service to do processing, passing in information via the Intent Extras and then let the widget do its magic and then stop itself, responsibly calling <service>.stopSelf()
.
Upvotes: 1