屏幕关闭时,警报活动不启动 [英] Alarm Activity does not launch when screen is off

查看:68
本文介绍了屏幕关闭时,警报活动不启动的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用一个Intent警报应用程序,该警报应用程序会在警报触发时启动并显示Activity,即使设备屏幕已关闭.该应用的目标是SDK 16+.
我可以通过自定义日志确认AlarmBroadcastReceiver正在按时触发,然后依次启动AlarmActivity.通过自定义日志记录,AlarmActivity在正确的时间没有中断.相反,它要么启动晚,要么在用户再次打开屏幕时启动.

I am working on an alarm app with the Intent of launching and displaying an Activity when the alarm fires, even if the device screen is off. The app is targeting SDK 16+.
I can confirm through custom logging that the AlarmBroadcastReceiver is firing on time, and this in turn launches an AlarmActivity. Through custom logging the AlarmActivity is not luanching at the right time. Instead it either launches late or when the screen is turned on again by the user.

我不知道为什么会这样.我已经尝试过解决SO上发布的其他类似问题的多种解决方案.

I am at a loss as to why this is happening. I have tried multiple solutions from other similar problems posted on SO.

您对我的问题有什么建议吗?谢谢您的帮助!
参见下面的AlarmBroadcastReceiverAlarmActivityAndroidManifest代码.

Do you have any suggestions as to my issue? Thank you for any help!
See code below for AlarmBroadcastReceiver, AlarmActivity, and AndroidManifest.

我正在以下设备上进行测试:
三星Galaxy II,Android 4.1.2,API 16-(这是从不触发AlarmActivity或等到屏幕打开时最糟糕的情况.)
LG Nexus 5,Android 6.0.1,API 23
LG Harmony,Android 7.0,API 24

I am testing on the following devices:
Samsung Galaxy II, Android 4.1.2, API 16 - (This is the worst at never triggering the AlarmActivity or waiting until the screen is turned on.)
LG Nexus 5, Android 6.0.1, API 23
LG Harmony, Android 7.0, API 24

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

    <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=".view.AlarmActivity">
        </activity>
        <activity android:name=".view.TimerActivity">
        </activity>
        <activity android:name=".view.MainActivity">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>

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

        <!-- Register the BroadcastReceiver -->
        <receiver android:name=".AlarmBroadcastReceiver"/>
        <receiver android:name=".TimerBroadcastReceiver"/>
    </application>

</manifest>

AlarmBroadcastReceiver

class AlarmBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent?) {

        // ***** CUSTOM LOGGING HERE *****
        // This code logs at the correct alarm time

        val newIntent = Intent(context, AlarmActivity::class.java)
        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        ContextCompat.startActivity(context, newIntent, null)
    }

}

AlarmActivity

class AlarmActivity : AppCompatActivity() {

    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(com.devbygc.toddlertimer.R.layout.activity_alarm)

        // ***** CUSTOM LOGGING HERE *****
        // This code does NOT log until either
        // - user turns on the devices screen
        // - some lapse in time making the alarm "late" by 1 min to 1+ 

        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
            setTurnScreenOn(true)
            setShowWhenLocked(true)
            val k = this.getSystemService(Context.KEYGUARD_SERVICE) as KeyguardManager
            k.requestDismissKeyguard(this, null)
        } else {
            @Suppress("DEPRECATION")
            window.addFlags(
                WindowManager.LayoutParams.TYPE_APPLICATION_OVERLAY or
                    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED or
                    WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD or
                    WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
                    WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON or
                    WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
            )
        }
    }
}

推荐答案

在针对自己的先前警报调查了Google自己的代码库之后- AlarmClock -我想出了如何使用WakeLock来解决此问题的方法.
AlarmBroadcastReceiveronReceive()中获取部分唤醒锁.然后将其发布到我的AlarmActivityonDestroy()中.
新的类AlertWakeLock处理所有唤醒锁功能.
清单没有更改,请参阅原始问题以获取权限.
该代码未能在停机时间超过12小时的多次测试的多个设备上成功触发警报.

After investigating Google's own codebase for their previous alarm - AlarmClock - I figured out how to answer this issue using WakeLock.
The AlarmBroadcastReceiver acquires a partial wakelock in onReceive(). This is then released in the onDestroy() of my AlarmActivity.
A new class, AlertWakeLock, handles all the wakelock functionality.
There were no changes to the manifest, see original question for permissions.
This code has no successfully triggered the alarm on multiple devices with multiple tests with downtimes of 12+ hours.

值得称赞的是,我仍然发现WindSekirun代码很有帮助,如果发现类似的问题,建议考虑使用它.

To give credit I still found WindSekirun code helpful and suggest considering it if you find you have a similar problem.

请参见下面的代码:

class AlarmBroadcastReceiver : BroadcastReceiver() {

    override fun onReceive(context: Context, intent: Intent?) 

        AlertWakeLock.acquireWakeLock(context)

        val newIntent = Intent(context, AlarmActivity::class.java)
        newIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
        ContextCompat.startActivity(context, newIntent, null)
    }

}

AlarmActivity

class AlarmActivity : AppCompatActivity() {

    override fun onDestroy() {
        super.onDestroy()
        AlertWakeLock.releaseWakeLock()
    }

}

AlertWakeLock

class AlertWakeLock {

    companion object {

        private var wakeLock: PowerManager.WakeLock? = null

        fun acquireWakeLock(context: Context) {
            Log.d(TAG,"Acquiring cpu wake lock")
            if (wakeLock != null) {
                return
            }

            val pm = context.getSystemService(Context.POWER_SERVICE) as PowerManager

            wakeLock = pm.newWakeLock(
                PowerManager.PARTIAL_WAKE_LOCK or
                    PowerManager.ACQUIRE_CAUSES_WAKEUP or
                    PowerManager.ON_AFTER_RELEASE, "ToddlerTimer:WakeLock"
            )
            wakeLock!!.acquire()
        }

        fun releaseWakeLock() {
            Log.d(TAG,"Releasing cpu wake lock")
            if (wakeLock != null) {
                wakeLock!!.release()
                wakeLock = null
            }
        }
    }

}

这篇关于屏幕关闭时,警报活动不启动的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆