Android 标志\打开\屏幕\并不总是起作用

Android 标志\打开\屏幕\并不总是起作用,android,screen,wakeup,Android,Screen,Wakeup,我从BroadcastReceiver启动一个活动,该活动由alaram(RTC_唤醒类型)触发。在创建该活动时,我添加了这些标志 getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |

我从BroadcastReceiver启动一个活动,该活动由alaram(RTC_唤醒类型)触发。在创建该活动时,我添加了这些标志

getWindow().addFlags(WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
    WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
    WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON |
    WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON        
);
问题是,有时(大约10%的情况下)屏幕无法打开。警报被正确触发(我在这里听到通知的声音,它也在接收器的onReceive()中触发。然后,如果我按下手机的电源按钮,屏幕将打开,显示我的活动,并立即关闭。之后,电源按钮工作正常。这发生在android 2.3.7上,这里是onReceive()方法

我希望避免使用PowerManager,因为它需要权限,并且标志是首选的方式

有什么问题?logcat没有显示任何问题

问题是,有时(大约10%的情况下)屏幕无法打开

如果非要我猜的话,设备在活动开始之前又睡着了。一旦
onReceive()
返回,设备可以也将重新入睡,并且在
onReceive()
返回之后的一段时间,您的活动才会开始


这是相同的场景,但将
startActivity()
替换为
startService()
,这就是我为什么要写的原因,它使用了一个
唤醒锁来确保设备保持足够长的时间处于唤醒状态以便它工作,然后释放
唤醒锁
,我在这里参加聚会有点晚了,但我已经为此奋斗了一段时间,终于找到了让屏幕每次解锁的方法通常我从WakefulBroadcastReceiver执行此操作,以便屏幕平稳过渡,但这取决于用例

@Override
public void onAttachedToWindow() {
    super.onAttachedToWindow();
    //Screen On
    getWindow().addFlags(
            WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                    | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                    | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                    | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

private void clearFlags() {
    //Don't forget to clear the flags at some point in time.
    getWindow().clearFlags(
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
                        | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
                        | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                        | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

根据我在这方面的经验和研究:

  • 标志\u打开\u屏幕\u打开不能用于在应用程序中多次打开和关闭屏幕

  • 当(最好是在onCreate()方法中)或时,标志\u打开\u屏幕\u打开只能用于打开屏幕一次

现在,您可以通过以下方式绕过此限制:

  • 启动一个新活动并在那里设置标志,然后(由用户或以编程方式)完成该活动以关闭屏幕
  • 参数screenBrightness参数设置为,有时屏幕会“关闭”。然后您可以增加亮度以“打开”屏幕。但是,这通常不起作用,因为屏幕仍然暗淡但可见,如果用户锁定手机,这也不起作用
  • 使用(这仍然有效,但Android不赞成使用此功能,因此他们不鼓励使用此技术)。然而,据我所知,这是让我的应用程序可靠地打开/关闭屏幕的唯一方法
所有这些都不是理想的(事实上,它们感觉像黑客),只是使用一个更适合您的应用程序需要的

您可以在此处阅读更多内容:


我同时使用这三种方法,几乎可以在任何设备上使用

public static void turnScreenOnThroughKeyguard(@NonNull Activity activity) {
    userPowerManagerWakeup(activity);
    useWindowFlags(activity);
    useActivityScreenMethods(activity);
}

private static void useActivityScreenMethods(@NonNull Activity activity) {
    if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) {
        try {
            activity.setTurnScreenOn(true);
            activity.setShowWhenLocked(true);
        } catch (NoSuchMethodError e) {
            Log.e(e, "Enable setTurnScreenOn and setShowWhenLocked is not present on device!");
        }
    }
}

private static void useWindowFlags(@NonNull Activity activity) {
    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

private static void userPowerManagerWakeup(@NonNull Activity activity) {
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    WakeLock wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, tag);
    wakeLock.acquire(TimeUnit.SECONDS.toMillis(5));
}

迟回答,但对任何人都有帮助

对于较高版本和较低版本,请使用以下代码(工作正常)


重要提示:您应该在setContentView()之前放置

以下代码允许从PendingEvent打开活动,即使应用程序

  • 已从最近的应用程序中清除
  • 屏幕变暗了

设备应该处于唤醒状态,因为通知的声音正在播放……我是否可以让接收器与线程一起睡眠。睡眠(…)设备将不会入睡?或者使用延迟消息(new Handler())。postDelayed(…)?@Shell:“我是否可以让接收器与线程一起睡眠。睡眠(…)设备将不会入睡?”--不。首先,这将阻止活动在
sleep()
完成之前启动,因为在主应用程序线程上调用了
onReceive()
。其次,如果主应用程序线程占用时间过长,Android将关闭你的
广播接收器。“我可以用线程使接收器睡眠吗?睡眠(…)设备将不会入睡?”--这不会阻止设备入睡。这会使这个问题发生的频率增加很多。好吧,所以没有睡眠(),但是我怎么能听到通知声音(我重复它直到手动取消),但屏幕没有打开?@shelll:真让我受不了。我建议您添加一个适当的
唤醒锁
,看看您的问题是否消失。如果是这样,你必须做出决定。如果没有,那么您将遇到其他一些问题。如何正确获取BroadcastReceiver中的锁并在活动中释放它?您的WakefulIntentService是我的案例的解决方案吗?您是否设法规避了此问题?@Redwarp唯一的解决方案是使用WAKE_LOCK权限和静态锁。支持库中有一个新的
WakefulBroadcastReceiver
,用于处理部分唤醒锁定。它需要cource的许可。嗨,如果我们多次使用FLAG\u TURN\u SCREEN\u会发生什么?它会为城市显示一个黑屏吗?
public static void turnScreenOnThroughKeyguard(@NonNull Activity activity) {
    userPowerManagerWakeup(activity);
    useWindowFlags(activity);
    useActivityScreenMethods(activity);
}

private static void useActivityScreenMethods(@NonNull Activity activity) {
    if (VERSION.SDK_INT >= VERSION_CODES.O_MR1) {
        try {
            activity.setTurnScreenOn(true);
            activity.setShowWhenLocked(true);
        } catch (NoSuchMethodError e) {
            Log.e(e, "Enable setTurnScreenOn and setShowWhenLocked is not present on device!");
        }
    }
}

private static void useWindowFlags(@NonNull Activity activity) {
    activity.getWindow().addFlags(WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED
            | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD
            | WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
            | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
}

private static void userPowerManagerWakeup(@NonNull Activity activity) {
    PowerManager pm = (PowerManager) context.getSystemService(Context.POWER_SERVICE);
    WakeLock wakelock = pm.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, tag);
    wakeLock.acquire(TimeUnit.SECONDS.toMillis(5));
}
@Override
protected void onCreate(Bundle savedInstanceState) {
    super.onCreate(savedInstanceState);
    if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O_MR1) {
        setShowWhenLocked(true);
        setTurnScreenOn(true);
        KeyguardManager keyguardManager = (KeyguardManager) getSystemService(Context.KEYGUARD_SERVICE);
        keyguardManager.requestDismissKeyguard(this, null);
    }
    else{
        getWindow().addFlags(WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON
                | WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD |
                WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED |
                WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON);
    }

 setContentView(R.layout.activity_incoming_call);
}
    override fun onCreate(savedInstanceState: Bundle?) {
        super.onCreate(savedInstanceState)
        setContentView(view)
        turnOnScreen()
    }

    private fun turnOnScreen() {
        window.addFlags(
            WindowManager.LayoutParams.FLAG_KEEP_SCREEN_ON or
                    WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON
        )
        setTurnScreenOn(true)
        setShowWhenLocked(true)

        val keyguardManager = getSystemService(KEYGUARD_SERVICE) as KeyguardManager
        keyguardManager.requestDismissKeyguard(this, null)
    }