Search code examples
androidservicebroadcastreceiveralarmmanager

Should I create 5 different receivers/services for my app?


I just started making an application aside from school and work and am not sure what route I should take. Essentially, I am building an app that calculates 5 different prayer times that change every day (the 5 prayers are named Fajr, Zuhr, Asr, Maghrib, and Isha). The calculation is done locally on the device and I found open source code for that and got it to calculate them properly. Once the getTimes() method is called, the prayer times should be calculated for that day and then recalculated once every single day after that. I'm thinking the setRepeating() method of the AlarmManager class would be good for that. How would I go about that? Once the prayer times are calculated, a service(s) should be started to create a notification at that exact time to notify the user that it is time to pray. The dilemma here is that I don't think that I should be using 5 different services/receivers to notify for each of the 5 different prayers. What would be the best way to go about this?

Currently, my app only notifies the user of Maghrib (one of the prayers) prayer time. It does not recalculate the times either.

Sorry if I am not very clear as I am new to this. I can expand more if needed.

My getTimes() method: (for the sake of simplicity I have removed the code that calculates the times)

public void getLocationTime(View v) {

        //Maghrib
        Calendar calMaghribTime = Calendar.getInstance();
        calMaghribTime.set(Calendar.HOUR_OF_DAY, getHourOfDay(strMaghribTime));
        calMaghribTime.set(Calendar.MINUTE, Integer.parseInt(strMaghribTime.substring(3,5)));
        calMaghribTime.set(Calendar.SECOND, 0);

        Intent myIntent = new Intent(MainActivity.this, NotificationCreatorReceiver.class);
        pendingIntent = PendingIntent.getBroadcast(MainActivity.this, 0, myIntent, 0);

        AlarmManager alarmManager = (AlarmManager)getSystemService(ALARM_SERVICE);
        alarmManager.set(AlarmManager.RTC, calMaghribTime.getTimeInMillis(), pendingIntent);

        Toast.makeText(this, "NotificationCreator onReceive()", Toast.LENGTH_SHORT).show();
    } //end of getLocationTime()

Here is my receiver:

public class NotificationCreatorReceiver extends BroadcastReceiver {

    @Override
    public void onReceive(Context context, Intent intent) {

        Intent service1 = new Intent(context, NotificationCreatorService.class);
        context.startService(service1);

    }
}

Here is my service:

public class NotificationCreatorService extends Service {


    @Override
    public IBinder onBind(Intent arg0)
    {
        // TODO Auto-generated method stub
        return null;
    }

    @Override
    public void onCreate()
    {
        super.onCreate();
        // TODO Auto-generated method stub
    }


    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {

        Toast.makeText(this, "NotificationCreator onStartCommand()", Toast.LENGTH_SHORT).show();

        // Use NotificationCompat.Builder to set up our notification.
        NotificationCompat.Builder builder = new NotificationCompat.Builder(this);

        //icon appears in device notification bar and right hand corner of notification
        builder.setSmallIcon(R.mipmap.ic_launcher);

        // This intent is fired when notification is clicked
        Intent intent1 = new Intent(this.getApplicationContext(),MainActivity.class);
        PendingIntent pendingNotificationIntent = PendingIntent.getActivity(this.getApplicationContext(),
                0, intent1, PendingIntent.FLAG_UPDATE_CURRENT);

        // Set the intent that will fire when the user taps the notification.
        builder.setContentIntent(pendingNotificationIntent);

        // Content title, which appears in large type at the top of the notification
        builder.setContentTitle("It's time for Maghrib");

        // Content text, which appears in smaller text below the title
        builder.setContentText("Maghrib prayer time has started in your area");

        NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

        // Will display the notification in the notification bar
        notificationManager.notify(0, builder.build());

        return START_STICKY;
    }

    @Override
    public void onDestroy()
    {
        // TODO Auto-generated method stub
        super.onDestroy();
    }

}

Solution

  • The short answer - probably 1 service, 5 receivers. A Receiver is designed to listen for events and take quick action. A Service should be used to do all of the "heavy lifting" if necessary.

    A Receiver should listen for an event and, if you only need to post a notification, then you can probably just do that and be done. But if you want to do much of anything else, it should pass an Intent to the Service with data to tell the Service how to respond.

    EDIT:

    Receivers have 10 seconds to do their job or else an ANR (Application Not Responding) error will occur. (See the docs: http://developer.android.com/reference/android/content/BroadcastReceiver.html) Creating and sending a notification should not take this long.

    However, "good design" means you should acquire a Wake Lock and then pass an intent to a Service to do much of anything. Also, you will probably find that you will want to do "other processing" at some point. However, if I were you and all that is required is to post a notification, I'd just use the Receiver and worry about it later. I've probably processed over a billion notifications this way without error. But a code reviewer may argue that it's "possible" for an ANR to occur... blah... blah... blah...