适用于 Android 10 的简单闹钟应用如何通过服务打开屏幕

问题描述

我正在尝试为 Android 10 创建一个简单的闹钟应用。

我使用警报管理器并通过挂起的意图启动带有通知前台服务。它工作正常,但在 Android 10 中无法从后台服务启动 Activity。

我知道如何通过活动唤醒和打开屏幕,但不知道如何通过服务和通知执行此操作(屏幕保持关闭)。

有没有办法以编程方式打开屏幕?

我的设备是华为 HRY-LX1T(Android 10)。

if( Build.VERSION.SDK_INT >= 26) {
    NotificationChannel channel = new NotificationChannel( CHANNEL_ID,"Alarm",notificationmanager.IMPORTANCE_HIGH);
    ((notificationmanager) getSystemService( Context.NOTIFICATION_SERVICE)).createNotificationChannel(channel);
    Notification notification = new Notification.Builder(this,CHANNEL_ID)
            .setSmallIcon( R.drawable.ic_launcher_foreground )
            .setContentIntent( PendingIntent.getActivity( this,new Intent( this,Main.class).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK ),0) )
            .setContentTitle( getString(R.string.alarm))
            .setContentText("Test").build();
    startForeground(1,notification);
}

解决方法

如果应用具有 SYSTEM_ALERT_WINDOW 窗口权限,您就可以从前台服务启动 Activity,除非您正在为 Android Go 开发。

声明 SYSTEM_ALERT_WINDOW 权限并将 showWhenLockedturnScreenOn 标志添加到您的 AndroidManifest.xml 中的 Activity。

showWhenLocked 允许 Activity 在锁定屏幕上显示,并且 turnScreenOn 在 Activity 恢复时打开屏幕。

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

...

<activity 
   android:name=".YourActivity" 
   android:showWhenLocked="true" 
   android:turnScreenOn="true" />

然后,像往常一样启动 Activity,即:

val intent = ...
startActivity(intent)

如果您还想保持屏幕开启,您可以在 Activity 的布局中声明一个 wake lock

<ContraintLayout 
...
   android:keepScreenOn="true" >
...
</ConstraintLayout>

请注意,用户需要向应用授予“显示在其他应用之上”的特殊权限。,否则 Activity 将不会启动。

作为 Android Go 的替代方案,您可以从您的服务中获取唤醒锁,但该 API 已弃用一段时间。

val pm = (getSystemService(Context.POWER_SERVICE) as PowerManager)
val levelAndFlags = PowerManager.FULL_WAKE_LOCK or PowerManager.ACQUIRE_CAUSES_WAKEUP
val wakeLock = pm.newWakeLock(levelAndFlags,"MyApp::MyWakelockTag")

wakeLock.acquire()
//... do stuff
wakeLock.release()

您需要为此在清单中请求 WAKE_LOCK 权限。

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