12

我从广播接收器开始一个活动,该活动由警报(RTC_WAKEUP 类型)触发。在该活动的 onCreate 中,我添加了这些标志

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() 方法

@Override
public void onReceive(Context context, Intent intent) {
    m_Context = context;

    Bundle extras = intent.getExtras();
    final int id = extras.getInt("timer_id");

    Intent activityIntent = new Intent(m_Context, MyActivity.class);
    activityIntent.putExtra("timer_id", id);
    activityIntent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK | Intent.FLAG_ACTIVITY_SINGLE_TOP);
    m_Context.startActivity(activityIntent);

    // and now load the alarm sound and play it for the desired time
    showFinishedNotification();
}

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

可能是什么问题?logcat 没有显示任何问题...

4

6 回答 6

11

根据我对此主题的经验和研究:

  • FLAG_TURN_SCREEN_ON不能用于在您的应用程序中多次打开和关闭屏幕。

  • FLAG_TURN_SCREEN_ON在创建新活动(最好在 onCreate() 方法中)或重新创建视图时只能使用一次来打开屏幕。

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

  • 启动一个新活动并在那里设置标志,然后完成活动(由用户或以编程方式)让屏幕关闭。
  • params.screenBrightness参数设置为尽可能“暗”,有时屏幕“显示为关闭”。然后,您可以增加亮度以“打开”屏幕。但是,这通常不起作用,因为屏幕仍然昏暗但可见,如果用户锁定手机,这也不起作用。
  • 使用Power Manager Wakelock(这仍然有效,但 Android 已弃用此功能,因此他们不鼓励使用此技术)。但是,据我所知,这是让我的应用程序可靠地打开/关闭屏幕的唯一方法。

这些都不是理想的(实际上它们感觉像黑客),但只需使用更适合您的应用程序需求的那个。

你可以在这里阅读更多:

于 2016-05-16T20:09:41.067 回答
8

我在这里参加聚会有点晚了,但我已经为此奋斗了一段时间,终于找到了一种每次都能解锁屏幕的方法。我在 onAttachToWindow() 事件中添加了标志。通常我从 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);
}
于 2015-04-30T02:55:30.613 回答
4

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

如果我不得不猜测,该设备会在活动开始之前重新入睡。一旦onReceive()返回,设备可以并且将会重新进入睡眠状态,并且在onReceive()返回后的一段时间内您的活动将开始。

同样的场景,但替换startActivity()startService(),这就是我必须编写 的原因WakefulIntentService,它使用 aWakeLock来确保设备保持清醒足够长的时间以完成其工作,然后释放WakeLock.

于 2012-03-31T17:35:42.380 回答
4

迟到的答案但这对任何人都有帮助。

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

@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);
}

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

于 2020-04-01T06:13:34.323 回答
3

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

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));
}
于 2018-09-19T10:12:04.310 回答
0

针对SDK 30

以下代码可以从 PendingIntent 打开 Activity,即使应用程序

  • 已从最近的应用程序中清除
  • 屏幕变暗
    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)
    }
于 2021-01-11T20:45:58.560 回答