実現したいこと
Androidスマホの目覚まし時計を作る
前提
kotlin、AndroidStudioで目覚まし時計を作っています。
setAlarmClockを使い、時間になると「StopSnooze」というActivityが立ち上がって音を鳴らすという作りですが、正確な時間に鳴らないので困っています。
発生している問題・エラーメッセージ
2~9分程度遅れて鳴ることが多くあります。数分後に鳴るようなセットをするとほぼ正確に鳴りますが、8時間後に鳴るなどのセットをすると、遅れるなどの問題が起きることが多いです。
インストールして最初の2,3回はほぼ正確に鳴り、数日後(数回の使用後)に不正確になるように思われます。
お願いしたいこと
解決方法がわかればもちろん良いですが、それ以外でも、最近setAlarmClockを使ってうまくいった、あるいはうまくいかなかった経験がある方などに、そのことを教えていただけるだけでもありがたいです。というのも、そもそも今のAndroidにおいてsetAlarmClockを使って正確な時間に鳴る目覚まし時計を作ることはできないのではないか?無理なことをしようとしているのではないか?と疑問が湧いているのです。
該当のソースコード
メインアクティビティでアラームを鳴らす時刻(alarmTime)を取得してからサービスを立ち上げます。スマホがスリープ中にアラーム時刻となった場合にアクティビティの画面が立ち上がり、さらにPINの入力をせずに音を止められすようにするなどのために、Manifestにいくつかのpermissionを記述しています。
以下はサービスとマニフェストに含まれるコードの主要部分です。
kotlin
class ForAlarmService : Service() { override fun onCreate() { ・・・ override fun onStartCommand(intent: Intent?, flags: Int, startId: Int): Int { ・・・ alarmManager = getSystemService(ALARM_SERVICE) as AlarmManager val intentItsAlarmTime = Intent(this, StopSnooze::class.java) //StopSnoozeは音を鳴らしSTOPのボタン等を表示するアクティビティ intentItsAlarmTime.addFlags(Intent.FLAG_ACTIVITY_CLEAR_TASK) intentItsAlarmTime.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK) val alarmPendingIntent = PendingIntent.getActivity(this, 23, intentItsAlarmTime, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT ) val clockInfo: AlarmManager.AlarmClockInfo = AlarmManager .AlarmClockInfo(alarmTime.atZone(ZoneId.of("Asia/Tokyo")) .toInstant().toEpochMilli(),null) //alarmTimeはアラームを鳴らす時刻:LocalDateTime alarmManager.setAlarmClock (clockInfo,alarmPendingIntent) } override fun onDestroy() { super.onDestroy() val intentItsAlarmTime = Intent(this, StopSnooze::class.java) val alarmPendingIntent = PendingIntent.getActivity(this, 23, intentItsAlarmTime, PendingIntent.FLAG_IMMUTABLE or PendingIntent.FLAG_CANCEL_CURRENT ) alarmManager.cancel(alarmPendingIntent) alarmPendingIntent.cancel() } }
xml
<uses-permission android:name="android.permission.FOREGROUND_SERVICE" /> <uses-permission android:name="android.permission.SCHEDULE_EXACT_ALARM" /> <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW" /> <uses-permission android:name="android.permission.ACTION_MANAGE_OVERLAY_PERMISSION" /> <uses-permission android:name="android.permission.DISABLE_KEYGUARD" /> <uses-permission android:name="android.permission.WAKE_LOCK" /> <uses-permission android:name="android.permission.RECEIVE_BOOT_COMPLETED"/> <application ・・・ <activity android:name=".StopSnooze" android:exported="false" /> <service android:name=".ForAlarmService" android:enabled="true"/> </application>
問題に対して試したこと
以下のことをやってみましたが、状況は変わりませんでした(アプリをインストールしなおすと2~3回は正確に動き、その後再び問題が起きました。)
・PendingIntentのFLAGをあれこれ変えた。
・PendingIntentのリクエストコードを変えた。
・最初はalarmPendingIntentをメンバ変数にしていたが、onCreate と onDestroy のそれぞれで初期化するようにした。
・アプリをアンインストールしてスマホを再起動し、再インストールした。
・コードをテキストベースでコピーペーストして新しいプロジェクトを作った。
・Clean Projectを実施した。
・スマホの設定から、省電力機能の電池の最適化の対象外とした。
約4分間アラームが鳴るのが遅れた際に、adb shell dumpsys deviceidle を使ってその時のアラームの状態を調べてみました(Pixel5a(5G)を使用)。すると、
deep-idle: -2h12m52s503ms
normal: -20m40s929ms (alarm)
light-idle: -18m40s7ms
light-maint: -12m38s985ms
light-idle: -12m33s911ms
normal: -7m51s496ms (unlocked)
のような表記が出ました。アラームを設定したのはこの時間に合わせると -12m頃です。すなわち、-20m40sの時点でスマホは起きたにも関わらず、-12mの時点でアラームは鳴らず、-7m51s頃の時点でようやく鳴ったということと思われます。
これはなぜなのでしょうか。コードを工夫することによって改善する可能性はあるのでしょうか。
補足情報
これらの問題は、実機3台(Pixel5a(5G):Android12、Xperia8:Android11、京セラ(かんたんスマホ2)で起こりました。時間がかかるためエミュレータでは試していません。
回答1件
あなたの回答
tips
プレビュー