• After 15+ years, we've made a big change: Android Forums is now Early Bird Club. Learn more here.

Apps AlarmManager, setRepeating, but code only runs once

GemmaB89

Lurker
Hi guys,

This is my first time trying to make an app that starts on boot and runs in the background, and I'm finding all the possible ways of doing it a little confusing. I need the app to do a quick check of a few things every half hour, and sleep in between, so I settled for using AlarmManager and setRepeating.

In this test I've set it up so a boot receiver sets the alarm, which should run a service every 60 seconds. The service triggers a notification, but when I reboot the phone, the notification only shows up once. I clear it and never see it again.

I'll post the relevant code below. Can anyone tell me where I'm going wrong? Feel free to tell me if I'm going the wrong using AlarmManager in the first place also! Thanks! :)

AlarmStarter.java
Code:
public class AlarmStarter extends BroadcastReceiver {


 private static final int PERIOD=60000;


 @Override

 public void onReceive(Context context, Intent intent) {

 if (intent.getAction().equals("android.intent.action.BOOT_COMPLETED")) {


 scheduleAlarms(context);


 }

 }


 static void scheduleAlarms(Context ctxt) {

 AlarmManager mgr=

 (AlarmManager)ctxt.getSystemService(Context.ALARM_SERVICE);

 Intent i=new Intent(ctxt, BackService.class);

 PendingIntent pi=PendingIntent.getService(ctxt, 0, i, 0);


 mgr.setRepeating(AlarmManager.ELAPSED_REALTIME,

 SystemClock.elapsedRealtime() + PERIOD, PERIOD, pi);

 }


BackService.java

Code:
public class BackService extends Service {

 public BackService() {


 //showNotification("ticker test", "title test", "content test", "http://google.com");

 Log.d("CF", "Starting BackService");

 showNotification("ticker test", "title test", "content test", "http://google.com");

 }


 @Override

 public IBinder onBind(Intent intent) {

 // TODO: Return the communication channel to the service.

 throw new UnsupportedOperationException("Not yet implemented");

 }


 @Override

 public void onCreate() {

 // Code to execute when the service is first created


 }


 public void showNotification(String ticker, String title, String content, String url) {


 Intent notificationIntent = new Intent(Intent.ACTION_VIEW, Uri.parse(url));

 PendingIntent pi = PendingIntent.getActivity(this, 0, notificationIntent, 0);


 Notification notification = new NotificationCompat.Builder(this).setTicker(ticker)

 .setSmallIcon(android.R.drawable.ic_menu_report_image)

 .setContentTitle(title)

 .setContentText(content)

 .setContentIntent(pi)

 .setAutoCancel(true)

 .build();


 NotificationManager notificationManager = (NotificationManager) getSystemService(NOTIFICATION_SERVICE);

 notificationManager.notify(0, notification);


 }

}



AndroidManifest.xml

Code:
<?xml version="1.0" encoding="utf-8"?>

<manifest xmlns:android="http://schemas.android.com/apk/res/android"

 package="com.testapp.test" >


 <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" >

 <receiver

 android:name=".AlarmStarter"

 android:enabled="true" >

 <intent-filter>

 <action android:name="android.intent.action.BOOT_COMPLETED" />

 </intent-filter>

 </receiver>


 <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>


 <service

 android:name=".BackService"

 android:enabled="true"

 android:exported="true" >

 </service>

 </application>


</manifest>
 
Could you do this with a simple background thread, which just has a loop that sleeps for 60 seconds, then creates the notification?
 
I did consider that, but keep in mind this 60 seconds is just for testing, in the eventual app the delay would be 30 mins (or even and hour), some stuff I read suggested such a large window was better handled by AlarmManager, would work better with Android's battery saving functionality or something.
 
I see, hm.. yes you're probably right to go with the AlarmManager approach then. Sorry I cannot suggest what the problem is there, as I've not used this facility before.
 
The problem I had here was that the BackService class I was trying to trigger with the alarm, was extending from the Service class. It should have extended from the BroadcastReceiver class, as only BroadcastReceivers can be triggered by the externally sent alarms.
 
Back
Top Bottom