0

I'm developing an android app, and part of it involves a notification that reminds the user to do something. This notification at a specified time and repeats every 12 hours. I'm using AlarmManager to schedule the alarm and I've also included the code to start my Alarm Service when the device boots. Here are my java classes:

MainActivity.java

public class MainActivity extends Activity {

@Override
protected void onCreate(Bundle savedInstanceState) {
    // TODO Auto-generated method stub
    super.onCreate(savedInstanceState);
    setContentView(R.layout.activity_main);

    SharedPreferences preferences = PreferenceManager
            .getDefaultSharedPreferences(this);
    SharedPreferences.Editor editor = preferences.edit();
    int i = preferences.getInt("numberoflaunches", 1);

    if (i < 2) {
        alarmMethod();
        i++;
        editor.putInt("numberoflaunches", i);
        editor.commit();
    }
}

private void alarmMethod() {

    Intent intent = new Intent(this, AlarmService.class);
    this.startService(intent);

    Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_SHORT).show();

}

}  

AlarmService.java

public class AlarmService extends Service {

//used for register alarm manager
PendingIntent pendingIntent;
//used to store running alarm manager instance
AlarmManager alarmMgr;
//Callback function for alarm manager event
BroadcastReceiver mReceiver;

private static final String TAG = "MyService";

@Override
public IBinder onBind(Intent intent) {
    return null;
}

@Override
public void onCreate() {
    super.onCreate();

    //Register AlarmManager Broadcast receive.
    RegisterAlarmBroadcast();
}

@Override
public void onStart(Intent intent, int startid) {

    Calendar calendar = Calendar.getInstance();
    calendar.set(Calendar.SECOND, 0);
    calendar.set(Calendar.MINUTE, 30);
    calendar.set(Calendar.HOUR_OF_DAY, 6);

    alarmMgr.cancel(pendingIntent);
    alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP,
            calendar.getTimeInMillis(), 1000 * 60 * 60 * 12, pendingIntent);

}

private void showNotification() {

    Uri soundUri = RingtoneManager.getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
    Notification notification = new NotificationCompat.Builder(this)
            .setContentTitle("app_name")
            .setContentText("something")
            .setContentIntent(PendingIntent.getActivity(this, 0, new Intent(this, MainActivity.class), PendingIntent.FLAG_UPDATE_CURRENT))
            .setSound(soundUri)
            .setSmallIcon(R.drawable.notification_icon)
            .setAutoCancel(true)
            .setOnlyAlertOnce(true)
            .build();

    NotificationManagerCompat.from(this).notify(0, notification);

}

private void RegisterAlarmBroadcast() {
    Log.i("RegisterAlarmBroadcast", "Register Intent.RegisterAlarmBroadcast");

    //This is the call back function(BroadcastReceiver) which will be called when your alarm time is reached.
    mReceiver = new BroadcastReceiver() {
        private static final String TAG = "Alarm Example Receiver";

        @Override
        public void onReceive(Context context, Intent intent) {
            Log.i(TAG, "BroadcastReceiver::OnReceive() >>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
            showNotification();
        }
    };

    //Register the alarm broadcast here
    registerReceiver(mReceiver, new IntentFilter("com.example.application.myNotification"));
    pendingIntent = PendingIntent.getBroadcast(this, 0, new Intent("com.example.application.myNotification"), 0);
    alarmMgr = (AlarmManager) (this.getSystemService(Context.ALARM_SERVICE));
}

public void onDestroy() {
    super.onDestroy();
    Log.d(TAG, "onDestroy");
}

}

autostart.java

public class autostart extends BroadcastReceiver {

@Override
public void onReceive(Context arg0, Intent arg1)
{
    Intent intent = new Intent(arg0,AlarmService.class);
    arg0.startService(intent);
    Log.i("Autostart", "started");
}
}

AndroidManifest.xml

<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.application" >

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />

<application
    android:allowBackup="true"
    android:icon="@mipmap/ic_launcher"
    android:label="@string/app_name"
    android:theme="@style/AppTheme" >
    <activity
        android:name=".MainActivity"
        android:label="@string/app_name" >
        <intent-filter>
            <action android:name="android.intent.action.MAIN" />

            <category android:name="android.intent.category.LAUNCHER" />
        </intent-filter>
    </activity>
    <receiver android:name=".autostart">
        <intent-filter>
            <action android:name="android.intent.action.BOOT_COMPLETED" />
        </intent-filter>
    </receiver>
    <service
        android:name=".AlarmService"
        android:enabled="true" />
</application>

However I must have done something wrong as it is not working properly. My problems are:
1. When I exit the app, the notification for some reason goes off, whatever the time is.
2. When I reboot, the notification goes off, whatever the time is.

I don't know if these problems are in any way related, maybe I have a piece of code that's messing everything up. But either way I would really appreciate any sort of help I can get. Thanks in advance.

OHS
  • 185
  • 1
  • 2
  • 12
  • I would check this `onStartCommand` and `startForeground` http://developer.android.com/reference/android/app/Service.html and . Whenever I start a Service without startForeground I lost it and stops doing its job. In the BroadcastReceiver you don't seem to be overriding the `onReceive` method (you forgot the @Override annotation), check this http://stackoverflow.com/questions/20441308/boot-completed-not-working-android. – Eric Martinez May 27 '15 at 17:53

1 Answers1

1

The repeating interval should be 24 hours (1000 * 60 * 60 * 24), not 12 hours.

You are individually setting the time to 6 AM. So you can remove the line calendar.setTimeInMillis(System.currentTimeMillis());

EDIT:

I have made some of modifications to your code and finally got it working.

You problem was that you set an alarm for 6:00 AM. But you are setting this alarm at a time after 6:00 AM (say 9:00 AM). That is, you are setting an alarm for a past time. So it will go off immediately.

I made a work around for this. If the time you need to set alarm is past, set the alarm to trigger on the next day.

This is my modified code.

MainActivity.java

public class MainActivity extends Activity {

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);

        SharedPreferences preferences = PreferenceManager
                .getDefaultSharedPreferences(this);
        SharedPreferences.Editor editor = preferences.edit();
        int i = preferences.getInt("numberoflaunches", 1);

        if (i < 2) {
            alarmMethod();
            i++;
            editor.putInt("numberoflaunches", i);
            editor.commit();
        }
    }

    private void alarmMethod() {

        PendingIntent pendingIntent = PendingIntent.getBroadcast(this, 0,
                new Intent("com.example.application.myNotification"),
                PendingIntent.FLAG_UPDATE_CURRENT);
        AlarmManager alarmMgr = (AlarmManager) (this
                .getSystemService(Context.ALARM_SERVICE));

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 30);
        calendar.set(Calendar.HOUR_OF_DAY, 6);

        long mills = calendar.getTimeInMillis();
        if (mills <= System.currentTimeMillis()) {
            Calendar c1 = calendar;
            c1.add(Calendar.DAY_OF_MONTH, 1);
            mills = c1.getTimeInMillis();
        } else {
            mills = calendar.getTimeInMillis();
        }

        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, mills,
                1000 * 60 * 60 * 24, pendingIntent);

        Toast.makeText(MainActivity.this, "Alarm Set", Toast.LENGTH_SHORT)
                .show();

    }

}

Autostart.java

public class Autostart extends BroadcastReceiver {

    @Override
    public void onReceive(Context arg0, Intent arg1)
    {
        PendingIntent pendingIntent = PendingIntent.getBroadcast(arg0, 0, new Intent("com.example.application.myNotification"), 0);
        AlarmManager alarmMgr = (AlarmManager) (arg0.getSystemService(Context.ALARM_SERVICE));

        Calendar calendar = Calendar.getInstance();
        calendar.set(Calendar.SECOND, 0);
        calendar.set(Calendar.MINUTE, 30);
        calendar.set(Calendar.HOUR_OF_DAY, 6);

        long mills = calendar.getTimeInMillis();
        if (mills <= System.currentTimeMillis()) {
            Calendar c1 = calendar;
            c1.add(Calendar.DAY_OF_MONTH, 1);
            mills = c1.getTimeInMillis();
        } else {
            mills = calendar.getTimeInMillis();
        }

        alarmMgr.setRepeating(AlarmManager.RTC_WAKEUP, mills, 1000 * 60 * 60 * 24, pendingIntent);

        Log.i("Autostart", "started");
    }

}

Alarmer.java

public class Alarmer extends BroadcastReceiver {

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

    private void showNotification(Context context) {

        Random r = new Random();
        int r0 = r.nextInt();

        Uri soundUri = RingtoneManager
                .getDefaultUri(RingtoneManager.TYPE_NOTIFICATION);
        Notification notification = new NotificationCompat.Builder(context)
                .setContentTitle("app_name")
                .setContentText("something" + r0)
                .setContentIntent(
                        PendingIntent.getActivity(context, 0, new Intent(context,
                                MainActivity.class),
                                PendingIntent.FLAG_UPDATE_CURRENT))
                .setSound(soundUri).setSmallIcon(R.drawable.ic_launcher)
                .setAutoCancel(true).setOnlyAlertOnce(true).build();

        // NotificationManagerCompat.from(this).notify(0, notification);
        NotificationManager nm = (NotificationManager) context.getSystemService(Context.NOTIFICATION_SERVICE);


        nm.notify(r0, notification);

    }

}

AndroiManifest.xml

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example.alarmtest"
    android:versionCode="1"
    android:versionName="1.0" >

    <uses-sdk
        android:minSdkVersion="8"
        android:targetSdkVersion="16" />

    <application
        android:allowBackup="true"
        android:icon="@drawable/ic_launcher"
        android:label="@string/app_name"
        android:theme="@style/AppTheme" >
        <activity
            android:name=".MainActivity"
            android:label="@string/app_name" >
            <intent-filter>
                <action android:name="android.intent.action.MAIN" />

                <category android:name="android.intent.category.LAUNCHER" />
            </intent-filter>
        </activity>

        <receiver android:name=".autostart" >
            <intent-filter>
                <action android:name="android.intent.action.BOOT_COMPLETED" />
            </intent-filter>
        </receiver>

        <receiver android:name=".Alarmer" android:enabled="true">
            <intent-filter>
                <action android:name="com.example.application.myNotification" />
            </intent-filter>
        </receiver>

        <service
            android:name=".AlarmService"
            android:enabled="true" />
    </application>

</manifest>

Compare it with your code and make changes.

K Neeraj Lal
  • 6,768
  • 3
  • 24
  • 33
  • That didn't work, but I did find a solution to this problem. I got rid of `Calendar.AM_PM` and used the 24-hour format instead of the 12-hour format for the `HOUR_OF_DAY` (e.i. 10 PM will be 22). The notification now comes up only in that hour. But thanks for the heads up about the `calendar.setTimeInMillis(System.currentTimeMillis());`. Any ideas on how to solve the other problems? Again any help is much appreciated. – OHS May 27 '15 at 19:04
  • Which are the problems that still persist? – K Neeraj Lal May 28 '15 at 05:31
  • I've updated it and left the two problems I still have. – OHS May 28 '15 at 15:15
  • Thank you so much. It works perfectly, and I really appreciate your help. One last question though, if I wanted this notification to go off twice a day, once at 6 am and once at 6 pm, what would be the best way to do so? Because if I restarted the phone, the repeat command (which I would set to 12 hours) wouldn't be working until the specified time is reached. – OHS May 29 '15 at 14:06
  • I suggest you set two alarms one for 6 am and one for 6 pm. Its easier to work with two alarms. – K Neeraj Lal May 30 '15 at 06:00
  • Ah okay, so I would have two alarms each set to repeat every 24 hours. Thanks again for all your help. – OHS May 30 '15 at 06:09
  • hi,this is a optional name ->`com.example.application.myNotification` – sadegh Jul 13 '15 at 03:25
  • Yes it can be any name. – K Neeraj Lal Jul 13 '15 at 07:30