从接收器/服务中打开屏幕

21

我希望我的应用能够点亮屏幕并显示我的应用。假设我正在设置闹钟,每小时我想让我的应用在设备自然休眠之前显示2分钟。

我看到WakeLock(FULL_LOCK)和KeyguardManager已经过时了。

我已经创建了一个WakefulBroadcastReceiver和服务,并且它们可以正常工作。

@Override
protected void onHandleIntent(Intent intent) {
    // I need to show the screen here!

    for (int i=0; i<5; i++) {
        Log.i("SimpleWakefulReceiver", "Running service " + (i + 1)
                + "/5 @ " + SystemClock.elapsedRealtime());
        try {
            Thread.sleep(5000);
        } catch (InterruptedException e) {
        }
    }
    Log.i("SimpleWakefulReceiver", "Completed service @ " + 
          SystemClock.elapsedRealtime());
    SimpleWakefulReceiver.completeWakefulIntent(intent);
}

我如何通过编程打开屏幕,越过锁屏并从IntentService显示我的Activity?

谢谢


我看到WakeLock和KeyguardManager已经被弃用了。请添加链接。 - Mr_and_Mrs_D
FULL锁需要使用http://developer.android.com/reference/android/os/PowerManager.html#FULL_WAKE_LOCK和http://developer.android.com/reference/android/app/KeyguardManager.KeyguardLock.html。 - RuAware
3个回答

27

你可以使用这段代码打开屏幕。

lock = ((KeyguardManager) getSystemService(Activity.KEYGUARD_SERVICE)).newKeyguardLock(KEYGUARD_SERVICE);
powerManager = ((PowerManager) getSystemService(Context.POWER_SERVICE));
wake = powerManager.newWakeLock(PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "TAG");

lock.disableKeyguard();
wake.acquire();
           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
                | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);

您需要在 AndroidManifest.xml 文件中添加以下权限:

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

编辑(请使用此方法,没有任何过时的内容):
还有一种做法是启动一个Activity,在Activity的onCreate()中向窗口添加标志位。 例如:

   @Override
    protected void onCreate(Bundle savedInstanceState) {
      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 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON);`
}

谢谢,但请注意PowerManager.FULL_WAKE_LOCK和Keyguard已经过时。我想要一个应用程序,即使他们删除了它,它仍然可以工作。WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD将帮助您绕过Keyguard,但仍需要唤醒显示器。 - RuAware
1
有另一种方法可以实现这个功能,需要启动一个活动,在活动的 onCreate() 方法中,您需要向窗口添加标志, FLAG_DISMISS_KEYGUARD 并没有被废弃。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 | WindowManager.LayoutParams.FLAG_ALLOW_LOCK_WHILE_SCREEN_ON); - Kartheek
谢谢,使用这些设置启动新的活动是有效的。如果您将此作为解决方案,我会标记为正确。 - RuAware
完成了,抱歉我刚才离开了。现在应该有赏金了,感谢你的帮助。 - RuAware
@Kartheek:当我设置屏幕锁定的密码或图案时,它是否有效? - user3051460
显示剩余2条评论

2

我不知道你在说什么,wakelock绝对没有被弃用。某些类型不再是Google首选的做法,但正常的wakelocks仍然存在,并且仍然是最简单的方法。获取锁时,请确保添加ACQUIRE_CAUSES_WAKEUP标志。实际上,注意到一个WakefulBroadcastReceiver是通过使用wakelocks来实现的。


1
我可以使用PowerManager.FULL_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP唤醒屏幕,但是PowerManager.FULL_WAKE_LOCK在17中已经被弃用。现在需要结合KeyguardManager找到正确的方法来实现。 - RuAware

1
您可以使用此代码来打开屏幕。
private void turnScreenOn() {
    int flags = WindowManager.LayoutParams.FLAG_DISMISS_KEYGUARD | WindowManager.LayoutParams.FLAG_SHOW_WHEN_LOCKED | WindowManager.LayoutParams.FLAG_TURN_SCREEN_ON;
    getWindow().addFlags(flags);
}

你可以使用这段代码让它一直保持唤醒状态,直到唤醒锁被解除。
<uses-permission android:name="android.permission.WAKE_LOCK" />

private PowerManager mPowerManager;
private PowerManager.WakeLock mWakeLock;

@Override
public void onCreate() {
super.onCreate();
    mPowerManager = (PowerManager) getSystemService(Context.POWER_SERVICE);
    mWakeLock = mPowerManager.newWakeLock(PowerManager.SCREEN_DIM_WAKE_LOCK | PowerManager.ACQUIRE_CAUSES_WAKEUP, "Service");
}

private void acquireWakeLock() {
    try {
        mWakeLock.acquire();
    }
    catch (Exception e) {
        e.printStackTrace();
    }
}

private void releaseWakeLock() {
    try {
        mWakeLock.release();
    }
    catch (Exception e) {

    }
}

谢谢,我感觉自己正在取得进展,并添加了类似的东西,但是PowerManager.SCREEN_DIM_WAKE_LOCK已经过时,还有BRIGHT和FULL。你还必须确保在UI线程上添加标志,所以尝试接收消息->运行在UI上添加keep_screen_on->使用Acquire获取部分锁定唤醒。但这并不能打开屏幕,唯一能做到的就是使用过时的参数。 - RuAware
你试过turnScreenOn函数吗?如果接收到某个特定类型的消息(基于优先级),我会在GCM消息接收器中使用它。 - Bojan Kseneman
是的,在没有放在UI线程上,我会收到“只有创建视图层次结构的原始线程才能触摸其视图”的错误,但仍然无法打开屏幕!使用任何弃用选项都可以打开屏幕,看起来他们计划拿走某些东西,而不给我们一个完成它的方法。 - RuAware
是的,在我看来,这毕竟是一个安全问题。在开发该应用程序时,我可以通过GCM消息打开屏幕并解除键盘锁。我不知道现在它是如何运作的,因为我已经离开了那家公司并加入了另一家公司 :) - Bojan Kseneman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接