There are a lot of related questions and I beleive I've read them all twice or so. For some reason I seem to have tomatoes on my eyes. I do not see the error.
I've got an alarm set up using Alarm manager. (Happy to share more code if required.)
private static String ALARM_ACTION = "de.klecker.BigBen.Alarm";
private static PendingIntent createPendingIntent() {
Intent alarmIntent = new Intent(getContext(), BigBenAlarm.class);
alarmIntent.setAction(ALARM_ACTION);
return PendingIntent.getBroadcast(getContext(), 0, alarmIntent, 0);
}
getContext() returns a reference to the application.
public static void setAlarmFromNow() {
AlarmManager manager = (AlarmManager) getContext().getSystemService(Context.ALARM_SERVICE);
PendingIntent intent = createPendingIntent();
// First cancel any ongoing alarm
manager.cancel(intent);
manager.set(AlarmManager.RTC_WAKEUP, System.currentTimeMillis()
+ (5 * 1000), intent);
Log.d("BigBen", "Alarm is set!");
}
The alarm is properly registered. This is an extract of the output of
adb shell dumpsys alarm
Batch{2f6ac936 num=1 start=68344020 end=68344020}:
RTC_WAKEUP #0: Alarm{f8a5037 type 0 when 1453976393037 de.klecker.bigben}
tag=*walarm*:de.klecker.BigBen.Alarm
type=0 whenElapsed=+4s155ms when=2016-01-28 11:19:53
window=-1 repeatInterval=0 count=0
operation=PendingIntent{3df19a4: PendingIntentRecord{18a6130d de.klecker.bigben broadcastIntent}}
And it got actually fired. This is an extract from the log:
01-28 11:19:53.038 V/AlarmManager( 885): sending alarm {18a6130d type 0 *walarm*:de.klecker.BigBen.Alarm}
01-28 11:19:53.039 V/AlarmManager( 885): done {18a6130d, *walarm*:de.klecker.BigBen.Alarm} [1ms]
But the receiver did not get called. This is the receiver class:
public class BigBenAlarm extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Vibrator vibrator = (Vibrator) context.getSystemService(Context.VIBRATOR_SERVICE);
vibrator.vibrate(2000);
Log.d("BigBen", "Alarm fired!!!");
}
}
Neither the log statement appears on the log, nor does the phone vibrate. (Virbration permission was declared in manifest). I tried toasts and playing sounds and setting a breakpoint, but apparently, the method is never called.
This is how the receiver is registered:
AndroidManifest.xml:
<receiver android:name="de.klecker.bigben.BigBenAlarm">
<intent-filter>
<action android:name="de.klecker.BigBen.Alarm"/>
</intent-filter>
</receiver>
So which important detail did I miss?
Thanks to everybody who tried hard.
And yes, I did have tomatoes on my eyes. Although quite embarassing I leave this in and provide an answer in case that anybody else runs into the same issue.
The big mistake was within the android manifest. The receivers need to be registered within the application tags.
AndroidManifest.xml:
<application
android:name=".BigBenApp"
android:allowBackup="true"
android:icon="#mipmap/ic_launcher"
android:label="Big Ben"
android:supportsRtl="true"
android:theme="#style/AppTheme"
>
<activity android:name=".BigBenActivity">
<intent-filter>
<action android:name="android.intent.action.MAIN"/>
<category android:name="android.intent.category.LAUNCHER"/>
</intent-filter>
</activity>
<receiver android:name="de.klecker.bigben.BigBenAlarm"
android:enabled="true" >
<intent-filter>
<action android:name="de.klecker.BigBen.Alarm"/>
</intent-filter>
</receiver>
</application>
For some reason I closed the application and then tried to register the receiver.
Related
I have implemented a service to run with the alarm manager.
I read this link: Should I use android: process =“:remote” in my receiver?
I thought this would be a nice feature for my app, since i want the service to keep running after my app is down.
But when i add this line of configuration to my receiver on the manifest, my service stops being called.
Any clues?
Here is my receiver declaration:
This works:
<receiver
android:name=".service.MyAlarmReceiver"
android:enabled="true"
android:exported="false">
<intent-filter>
<action android:name=".service.MyAlarmReceiver"></action>
</intent-filter>
</receiver>
This wont'n work:
<receiver
android:name=".service.MyAlarmReceiver"
android:enabled="true"
android:process=":remote"
android:exported="false">
<intent-filter>
<action android:name=".service.MyAlarmReceiver"></action>
</intent-filter>
</receiver>
public class MyAlarmReceiver extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
#Override
public void onReceive(Context context, Intent intent) {
Log.d(TAG, "Time to start scan service!");
Intent intent = new Intent(context, BeaconFinderService.class);
context.startService(intent);
}
}
This is how i start my alarm manager:
// Construct an intent that will execute the AlarmReceiver
Intent intent = new Intent(getApplicationContext(), MyAlarmReceiver.class);
final PendingIntent pIntent = PendingIntent.getBroadcast(getApplicationContext(), MyAlarmReceiver.REQUEST_CODE, intent, PendingIntent.FLAG_UPDATE_CURRENT);
AlarmManager alarmManager = (AlarmManager) getSystemService(Context.ALARM_SERVICE);
alarmManager.setInexactRepeating(AlarmManager.RTC_WAKEUP, System.currentTimeMillis(), Constants.BLE_SERVICE_LOOP_TIME, pIntent);
When you configure your service to run in remote mode (android:process=":remote"), you will have to debug the process :remote instead as usual .
Personal bug:
So I was having an exception when trying to access FirebaseUser on the service. When in remote mode, you can't access the FirebaseUser, since your process runs on another context.
I had to pass the user through intent extras when initializing the service.
That was all!
I've an issue with an Alarm Manager. I wan't to execute my service each hour.
Alarm Manager is launched after reboot and work well, even if the app is not open or open and closed (My PhoneStartReceiver call launchBackgroundService one time, after a completed boot).
My problem is when I launch application after installation, without phone reboot. In this case, AlarmManager is killed when application is force closed or destroyed.
Problem is juste between installation, and next reboot. How to maintain AlarmManager enabled until next reboot ?
<receiver
android:name=".helpers.PeriodicalServiceCaller"
android:process=":remote"/>
<receiver
android:name=".helpers.PhoneStartReceiver"
android:process=":remote">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>
</receiver>
Here is my launchBackgroundServiceMethod, called in the both cases.
public static void launchBackgroundService(){
// Construct an intent that will execute the PeriodicalServiceCalle
Intent intent = new Intent(getApplicationContext(), PeriodicalServiceCaller.class);
intent.setFlags(Intent.FLAG_ACTIVITY_NEW_TASK);
// Create a PendingIntent to be triggered when the alarm goes off
final PendingIntent pIntent = PendingIntent.getBroadcast(getApplicationContext(), PeriodicalServiceCaller.REQUEST_CODE,
intent, PendingIntent.FLAG_UPDATE_CURRENT);
// Setup periodic alarm every minute
long firstMillis = System.currentTimeMillis(); // alarm is set right away
AlarmManager alarm = (AlarmManager) getApplicationContext().getSystemService(Context.ALARM_SERVICE);
// First parameter is the type: ELAPSED_REALTIME, ELAPSED_REALTIME_WAKEUP, RTC_WAKEUP
alarm.setInexactRepeating(AlarmManager.RTC_WAKEUP, firstMillis, 1000L, pIntent);
}
PeriodicallServiceCaller code
public class PeriodicalServiceCaller extends BroadcastReceiver {
public static final int REQUEST_CODE = 12345;
// Triggered by the Alarm periodically (starts the service to run task)
#Override
public void onReceive(Context context, Intent intent) {
Log.i("START-SERVICE", "PeriodicalServiceCaller");
Intent i = new Intent(context, MonitorDataService.class);
context.startService(i);
}
EDIT
My launchBackgroundService is launch by an Acitivity if it's after install and by PhoneStartReceiver if it's after a reboot
You need to register a BroadcastReceiver to detect when your are has been updated.
<receiver android:name=".MyBroadcastReceiver">
<intent-filter>
<action android:name="android.intent.action.MY_PACKAGE_REPLACED" />
</intent-filter>
</receiver>
Take a look at
How to know my Android application has been upgraded in order to reset an alarm?
Is launchBackgroundService in a service or run from the activity? If it is run from the service please check this answer Background Service getting killed in android
START_STICKY was the thing I missed.
I am calling the following BroadcastReceiver using AlarmManager every X mins. Its working fine.
public class MyAlarmReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
if (CommonFuncs.isConnectedBySettings(context)) {
if(CommonFuncs.isUpdateTimeValid(context)){
Intent intentCurSvc = new Intent(context, CurrencySvc.class);
context.startService(intentCurSvc);
}
}
}
Manifest
<receiver
android:name=".service.AlarmSvcRecevier"
android:process=":remote" >
</receiver>
I want to use the same BroadcastReceiver for connectivity change as well, by just adding the following manifest.
<receiver
android:name=".service.AlarmSvcRecevier"
android:process=":remote" >
<intent-filter>
<action android:name="android.net.conn.CONNECTIVITY_CHANGE" />
</intent-filter>
</receiver>
But my receiver is not getting called when WIFI is connected. I am not sure what is the problem. Do I need a separate receiver for AlarmManager and CONNECTIVITY_CHANGE to perform same operation? Is my approach correct?
Background and issue
I have checked dozens of tutorial, examples and questions here on stackoverflow which are related to the issue that services don't get registered after the phone is switched off.
My issue is almost similar with a little difference: I use an IntentService (I need to collect data from an external database and show it as a notification) and the service runs without any problem every 30 seconds until I switch the phone off.
The interesting part
Here comes the weird behaviour! I turn my phone back and the IntentService is registered ONLY ONCE. After booting up, I get my notification (in the example i use only logs for the sake of simplicity) only once, then never again.
part of Activity code (where I can set the service)
private void setRecurringAlarm(Context context) {
AlarmManager service = (AlarmManager) context.getSystemService(Context.ALARM_SERVICE);
Intent i = new Intent(context, BackgroundDataServiceReceiver.class);
PendingIntent pending = PendingIntent.getBroadcast(context, 0, i,
PendingIntent.FLAG_CANCEL_CURRENT);
Calendar cal = Calendar.getInstance();
cal.add(Calendar.SECOND, 30);
service.setInexactRepeating(AlarmManager.RTC_WAKEUP,
cal.getTimeInMillis(), 30*1000, pending);
}
IntentService
public class BackgroundDataService extends IntentService {
....
#Override
protected void onHandleIntent(Intent intent) {
Log.i("BACKGROUNDDATASERVICE STATUS", "running");
}
}
BroadcastReceiver
public class BackgroundDataServiceReceiver extends BroadcastReceiver {
#Override
public void onReceive(Context context, Intent intent) {
Intent dailyUpdater = new Intent(context, BackgroundDataService.class);
context.startService(dailyUpdater);
}
}
Manifest
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/>
<application
...
<service android:name="com.example.blgui3.BackgroundDataService" >
</service>
<receiver android:name="com.example.blgui3.BackgroundDataServiceReceiver" >
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
<action android:name="android.intent.action.QUICKBOOT_POWERON" />
</intent-filter>
</receiver>
...
</application>
As far as I know if my service needs to do background tasks e.g. fetch data from external database with AsyncTask then it is recommended to use IntentService. Even if I launch the app after the boot, the service still runs only once, so it simply does not register the BOOT_COMPLETE action. After struggling for hours with this I have absolutely no clue where I go wrong.
The service is started after boot with BOOT_COMPLETED but that does not start any activity and it seems it is only activity that sets the alarm.
My program is implement BroadcastReceiver to setting Alarm. But I got issue : After setting time to alarm, I power off device. After that, I start device and onReceive() function of BroadcastReceiver always call. This is my code :
<receiver android:name="com.futaba.broadcastservice.AlarmBroadCastReceiver"
>
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"></action>
</intent-filter>
</receiver>
How to fix this issue?
Have you read the documentation of BOOT_COMPLETED? It will run when the system is done booting.
Here's what you could do to reschedule your alarm after rebooting.
Code goes on your receiver.
public class AlarmBroadCastReceiver extends BroadcastReceiver {
Context ct;
#Override
public void onReceive(Context context, Intent intent)
{
ct=context;
if(intent.getAction().equals("android.intent.action.BOOT_COMPLETED"))
{
Intent contentIntent = new Intent(ct, AlarmBroadCastReceiver.class);
PendingIntent theappIntent = PendingIntent.getService(ct, 0,contentIntent, 0);
Calendar calendar = Calendar.getInstance();
calendar.set(year, month, day, hour,minute);
AlarmManager am = (AlarmManager) ct.getSystemService(ALARM_SERVICE);
am.set(AlarmManager.RTC_WAKEUP, calendar.getTimeInMillis(), theappIntent);
}
}
Just to be sure, you have to declare the uses-permission as follow
<application android:icon="#drawable/icon" android:label="#string/app_name">
<receiver android:name="com.futaba.broadcastservice.AlarmBroadCastReceiver">
<intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED" />
</intent-filter>
</receiver>
</application>
<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"></uses-permission>