falcon
falcon

Reputation: 1434

Service is null in widget provider

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

Answers (1)

jtt
jtt

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

Flow

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

Related Questions