1

since android 10 was launched, there are problems with alarms in my app, I have the following snippet, where I test with AlarmManager to see if the alarms that I program are executed. When I use setAlarmClock, the alarm runs at the set time, but when I try to use setInexactRepeating (or setRepeating), android ignores the alarm, it doesn't run at all.

class MainActivity : AppCompatActivity() {

  override fun onCreate(savedInstanceState: Bundle?) {
    super.onCreate(savedInstanceState)
    setContentView(R.layout.activity_main)
    val am = getSystemService(Context.ALARM_SERVICE) as AlarmManager
    val timeToTrigger = System.currentTimeMillis() + 10 * 1000
    val intervalo: Long = 60 * 1000
    val intent = Intent(this, AlarmReceiver::class.java)
    val pending = PendingIntent.getBroadcast(this, 1, intent, PendingIntent.FLAG_UPDATE_CURRENT)
    
    //am.setAlarmClock(AlarmManager.AlarmClockInfo(timeToTrigger , null), pending)

    am.setInexactRepeating(AlarmManager.ELAPSED_REALTIME_WAKEUP, SystemClock.elapsedRealtime() + intervalo,intervalo,pending)
  }
}

Here is my Manifest

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

<uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED" />
<uses-permission android:name="android.permission.WAKE_LOCK" />
<uses-permission android:name="android.permission.VIBRATE" />
<uses-permission
    android:name="android.permission.WRITE_SETTINGS"
    android:maxSdkVersion="19" />
<uses-permission android:name="android.permission.DISABLE_KEYGUARD" />
<uses-permission
    android:name="android.permission.READ_PHONE_STATE"
    android:maxSdkVersion="22" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="com.android.alarm.permission.SET_ALARM" />

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

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

    <receiver android:name=".AlarmReceiver" />

 </application>

 </manifest>

Thanks in advance

EDIT

According to @Crispert, using android.permission.REQUEST_IGNORE_BATTERY_OPTIMIZATIONS can help the alarm not be ignored. In manifest add the following permission:

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

Then in the activity, create a function to give the user to choose if they want the application to work in the background:

@RequiresApi(Build.VERSION_CODES.M)
private fun ignoreBatteryOptimization() {
    val intent = Intent()
    val packN = packageName
    val pm = getSystemService(Context.POWER_SERVICE) as PowerManager
    if (!pm.isIgnoringBatteryOptimizations(packN)) {
        intent.action = Settings.ACTION_REQUEST_IGNORE_BATTERY_OPTIMIZATIONS
        intent.data = Uri.parse("package:$packN")
        startActivity(intent)
    }
}

If the user agrees to ignore the battery optimization, the execution occurs in the background and the alarms work without any problem (according to the tests I have been doing, so far I have no problems). Thanks.

Russbell G.H
  • 345
  • 4
  • 11

2 Answers2

2

Try adding

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

to the app manifest and ask the user to grant the permission using this code

On a general note the alarms (and background execution in general) have been deliberately throttled and limited for the past few versions of android and there's little apps can do to counter that. The conventional approach would be to consider using alternative mechanisms (which have their own drawbacks) for delayed execution: either JobScheduler or foreground service. JobScheduler /jobs will eliminate the precision and certainty of execution (their purpose being to save energy) while a foreground service is intrusive and more energy inefficient.

If you don't rely on google play for distribution you could try to postpone the inevitable by using a lower targetSdkVersion (no more than 24 probably) for your app to try to force the OS to execute your alarms. Note however that on devices with 8/Oreo and newer versions the app standby buckets and other OEM battery saving mechanisms will practically suspend your app based on arbitrary criteria in the absence of user interaction with your app (so the alarms will be ignored).

Also consider checking if the BroadcastReceiver is not called at all or that what it tries to do can't be accomplished due to OS restrictions. You might find that the alarm is triggered but the app is forbidden to run the code -for example background code (service, broadcast) is no longer allowed to start activities.

Crispert
  • 1,102
  • 7
  • 13
  • 1
    Thanks, apply what you mention in the following way, add `` to the manifest and to enable it use the code according to this post [https://stackoverflow.com/questions/51813961/android-workmanager-scheduled-worker-lost-after-task-killed], after all that, the alarm works, edit the question applying the changes that I mention. – Russbell G.H Nov 06 '20 at 23:13
0

The answer of @Crispert is quite interesting, however, the only problem with it that it requires user's permission to be able to run/schedule Alarm.

I will give you the solution that I am using in one of my apps and that doesn't require any specific permission because it uses methods of Alarm Manager that by default ignore any battery optimizations.

Check this link over here: https://stackoverflow.com/a/64558739/9213980

Edit: I would like to add that this indeed is not a repeating Alarm, however, it can be simply and easily rescheduled with each trigger of Broadcast receiver.

There are some small limitations though, but in my case, those limitations didn't matter and it works exactly as I need. You can read more in details in the official documentation by this link https://developer.android.com/reference/kotlin/android/app/AlarmManager#setexactandallowwhileidle

Vitaliy-T
  • 733
  • 6
  • 23