Search code examples
androidalarmmanagerandroid-calendar

Schedule several automatic tasks using AlarmManager and Calendar


I have this piece of code...

desc.setOnClickListener(new OnClickListener(){
    public void onClick(View arg0){
        alert.setTitle("Download");
        alert.setIcon(R.drawable.go_down_3_32x32);
        alert.setMessage("¿Donwload?");
        alert.setPositiveButton("Yes", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int id){
                asyncForm2 af2 = new asyncForm2();
                af2.execute(idU, mDbH);
            }
        });
        alert.setNegativeButton("No", new DialogInterface.OnClickListener(){
            public void onClick(DialogInterface dialog, int id){
                dialog.cancel();
            }
        });
        AlertDialog alert0 = alert.create();
        alert0.show();
    }
});

Where desc is variable of type ImageView, alert is a variable of type AlertDialog.Builder, idU is an integer and mDbH is an instance of DataBaseHelper (my class to handle the SQLite database). Then I have the background AsyncTask...

class asyncForm2 extends AsyncTask<Object,String,String>{
    int idU;
    DataBaseHelper db;
    downloadData dd;
    protected void onPreExecute(){
        pDialog2 = new ProgressDialog(screen2.this);
        pDialog2.setMessage("Loading...");
        pDialog2.setIndeterminate(false);
        pDialog2.setCancelable(true);
        pDialog2.show();
    }
    protected String doInBackground(Object... params) {
        idU = Integer.parseInt(params[0].toString());
        db = (DataBaseHelper) params[1];
        dd = new downloadData(idU,db);
        if(dd.download(idU) == true){
            return "ok";
        }else{
            return "err";
        }
    }
    protected void onPostExecute(String result){
        if(result == "ok"){
            pDialog2.dismiss();
            Toast.makeText(getApplicationContext(), "Success", Toast.LENGTH_SHORT).show();
            setAlarms();
            Toast.makeText(getApplicationContext(), "Alarms set!!", Toast.LENGTH_SHORT).show();
        }else{
            Vibrator vibrator = (Vibrator) getSystemService(Context.VIBRATOR_SERVICE);
            vibrator.vibrate(200);
            Toast.makeText(getApplicationContext(), "Error", Toast.LENGTH_SHORT).show();
        }
    }
}

With this, the connection to the server is set and all the data I need for my app to work is downloaded... Then in method onPostExcecute the method setAlarms is called and does the following:

private void setAlarms(){
    // TODO Auto-generated method stub
    AlarmManager am = (AlarmManager) getSystemService(ALARM_SERVICE);
    Intent intent = new Intent(getApplicationContext(), AlarmReceiver.class);
    intent.putExtra("ID_USER", idU);
    String name1,name2;
    String splits[];
    int nameColumnIndex1, nameColumnIndex2;
    mDbH.open();
    Cursor itemCursor = null;
    itemCursor = mDbH.getForms(idU);
    if(itemCursor.moveToFirst() == false){
        itemCursor.close();
        mDbH.close();
    }else{
        for(itemCursor.moveToFirst();!itemCursor.isAfterLast();itemCursor.moveToNext()){
            PendingIntent sender = PendingIntent.getBroadcast(screen.this, 0, intent, 0);
            Calendar cal = GregorianCalendar.getInstance();
            nameColumnIndex1 = itemCursor.getColumnIndexOrThrow(DataBaseHelper.FORM_SYNC_DURATION);
            nameColumnIndex2 = itemCursor.getColumnIndexOrThrow(DataBaseHelper.FORM_SYNC_HOUR);
            name1 = itemCursor.getString(nameColumnIndex1);
            name2 = itemCursor.getString(nameColumnIndex2);
            splits = name2.split(":");
            if(name1.equals("DAILY")){
                cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(splits[0]));
                cal.set(Calendar.MINUTE, Integer.parseInt(splits[1]));
                cal.set(Calendar.SECOND, Integer.parseInt(splits[2]));
            }
            if(name1.equals("WEEKLY")){
                cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(splits[0]));
                cal.set(Calendar.MINUTE, Integer.parseInt(splits[1]));
                cal.set(Calendar.SECOND, Integer.parseInt(splits[2]));
                if(cal.get(Calendar.DAY_OF_MONTH)+7 > cal.getActualMaximum(Calendar.DAY_OF_MONTH)){
                    cal.set(Calendar.DAY_OF_MONTH, (cal.get(Calendar.DAY_OF_MONTH)+7) - cal.getActualMaximum(Calendar.DAY_OF_MONTH));
                    if(cal.get(Calendar.MONTH) + 1 >= cal.getActualMaximum(Calendar.MONTH)+1){
                        cal.set(Calendar.MONTH, (cal.get(Calendar.MONTH) + 1) - (cal.getActualMaximum(Calendar.MONTH)+1));
                        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 1);
                    }else{
                        cal.set(Calendar.MONTH,cal.get(Calendar.MONTH)+1);
                    }
                }else{
                    cal.set(Calendar.DAY_OF_MONTH, cal.get(Calendar.DAY_OF_MONTH)+7);
                    cal.set(Calendar.MONTH,cal.get(Calendar.MONTH)+1);
                }
            }
            if(name1.equals("FORTNIGHTLY")){
                cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(splits[0]));
                cal.set(Calendar.MINUTE, Integer.parseInt(splits[1]));
                cal.set(Calendar.SECOND, Integer.parseInt(splits[2]));
                if(cal.get(Calendar.DAY_OF_MONTH)+15 > cal.getActualMaximum(Calendar.DAY_OF_MONTH)){
                    cal.set(Calendar.DAY_OF_MONTH, (cal.get(Calendar.DAY_OF_MONTH)+15) - cal.getActualMaximum(Calendar.DAY_OF_MONTH));
                    if(cal.get(Calendar.MONTH) + 1 > cal.getActualMaximum(Calendar.MONTH)+1){
                        cal.set(Calendar.MONTH, (cal.get(Calendar.MONTH) + 1) - (cal.getActualMaximum(Calendar.MONTH)+1));
                        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 1);
                    }else{
                        cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
                    }
                }else{
                    cal.set(Calendar.DAY_OF_MONTH, Calendar.DAY_OF_MONTH+15);
                    cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
                }
            }
            if(name1.equals("MONTHLY")){
                cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(splits[0]));
                cal.set(Calendar.MINUTE, Integer.parseInt(splits[1]));
                cal.set(Calendar.SECOND, Integer.parseInt(splits[2]));
                if(cal.get(Calendar.DAY_OF_MONTH) + cal.getActualMaximum(Calendar.DAY_OF_MONTH) > cal.getActualMaximum(Calendar.DAY_OF_MONTH)){
                    cal.set(Calendar.DAY_OF_MONTH, (cal.get(Calendar.DAY_OF_MONTH) + cal.getActualMaximum(Calendar.DAY_OF_MONTH)) - cal.getActualMaximum(Calendar.DAY_OF_MONTH));
                    if(cal.get(Calendar.MONTH) + 1 > cal.getActualMaximum(Calendar.MONTH)+1){
                        cal.set(Calendar.MONTH, (cal.get(Calendar.MONTH) + 1) - (cal.getActualMaximum(Calendar.MONTH)+1));
                        cal.set(Calendar.YEAR, cal.get(Calendar.YEAR) + 1);
                    }else{
                        cal.set(Calendar.MONTH, cal.get(Calendar.MONTH) + 1);
                    }
                }
            }
            am.set(AlarmManager.RTC_WAKEUP, cal.getTimeInMillis(), sender);
        }
        itemCursor.close();
        mDbH.cerrar();
    }
}

As you can see, I set several alarms depending on a value from a table of my database, and regarding of that, the alarms are different form each other (daily, weekly, etc.). And my AlarmReceiver class is as follows:

public class AlarmReceiver extends BroadcastReceiver {
    private ProgressDialog pDialog1;
    private static DataBaseHelper mDbH;
    Context context0;

    @Override
    public void onReceive(Context context, Intent intent) {
        try {
            context0 = context;
            Bundle bundle = intent.getExtras();
            int idU = bundle.getInt("ID_USER");
            asyncForm af2 = new asyncForm();
            af2.execute(idU, mDbH);
        } catch (Exception e) {
            Toast.makeText(context, "Error", Toast.LENGTH_SHORT).show();
            e.printStackTrace();
        }
    }

    class asyncForm extends AsyncTask<Object,String,String>{
        int idU;
        DataBaseHelper db;
        sendData sd;
        protected void onPreExecute(){
            pDialog1 = new ProgressDialog(contexto);
            pDialog1.setMessage("Sending...");
            pDialog1.setIndeterminate(false);
            pDialog1.setCancelable(true);
            pDialog1.show();
        }
        @Override
        protected String doInBackground(Object... params) {
            idU = Integer.parseInt(params[0].toString());
            db = (DataBaseHelper) params[1];
            sd = new sendData(idU,mDbH);
            if(sd.send(idU) == true){
                return "ok";
            }else{
                return "err";
            }
        }
        protected void onPostExecute(String result){
            if(result == "ok"){
                pDialog1.dismiss();
                Toast.makeText(contexto, "Success", Toast.LENGTH_SHORT).show();
            }else{
                Toast.makeText(contexto, "Error", Toast.LENGTH_SHORT).show();
            }
        }
    }
}

As you can see, with the whole thing, i try to send data automatically to my server (the responses of the forms stored in the database). But for some reason when the time comes (lets say 12:00 noon) nothing happens. There is no error in logcat, thats why i don't know what i'm doing wrong!! Please help, I don't know if the problem is when working with Calendar or if this isn't, in fact, the way of setting alarms...

Greetings!


Solution

  • I didin't read the whole code, but to set more than one alarms you must provide different PendingIntent, otherwise every alarm overwrites the previous one. You can do this by setting different requestCode:

    PendingIntent sender = PendingIntent.getBroadcast(context, SOMEVALUE, intent, 0);
    

    For example, you could write a

    ArrayList<PendingIntent> array;
    
    private void setAlarms(){
    
         //your stuff
    
         array = new ArrayList<PendingIntent>();
    
         for(int i=0;i<something;i++){
            PendingIntent sender = PendingIntent.getBroadcast(context, i, intent, 0);
            array.add(sender)
    
            //here you can set alarm
        }
    
    
    }
    

    Remember that if you want to later cancel those alarms, you have to store all the PendingIntents! (in a List for example)

    To cancel

    void cancelAllAlarms(){
    
        if(!array.isEmpty()){
    
            for(int i=0; i<array.size(); i++){
                alarmManager.cancel(array.get(i));
            }
    
            array.clear();
    
         }
    }