Search code examples
androidalarmandroid-10.0

Simple alarm app for Android 10. How to turn on screen by service


I am trying to create a simple alarm app for Android 10.

I use Alarm Manager and start a foreground service with notification by pending intent. It is working fine, but by Android 10 is impossible to start an activity from background service.

I know how to wake up and turn screen on by activity but do not know how to do this by service and notification (the screen stays off).

Is there way to turn screen on programmatically?

My device is Huawei 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, 0, new Intent( this, Main.class).addFlags( Intent.FLAG_ACTIVITY_NEW_TASK ), 0) )
            .setContentTitle( getString(R.string.alarm))
            .setContentText("Test").build();
    startForeground(1, notification);
}

Solution

  • You can start an activity from a foreground service if the app has the SYSTEM_ALERT_WINDOW window permission, unless you are developing for Android Go.

    Declare the SYSTEM_ALERT_WINDOW permission and add the showWhenLocked and turnScreenOn flags to your Activity in your AndroidManifest.xml.

    showWhenLocked allows the Activity to be shown over the lock screen, and turnScreenOn turns on the screen when the Activity is resumed.

    <uses-permission android:name="android.permission.SYSTEM_ALERT_WINDOW"/>
    
    ...
    
    <activity 
       android:name=".YourActivity" 
       android:showWhenLocked="true" 
       android:turnScreenOn="true" />
    
    

    Then, start the Activity like you would normally, i.e.:

    val intent = ...
    startActivity(intent)
    

    If you additionally want to keep the screen on, you can declare a wake lock in the layout of your Activity.

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

    Note that the User needs to grant the 'Display over other apps' special permission. to the app, otherwise the Activity won't be started.

    As an alternative for Android Go, you could acquire a wake lock from your service, but the API has been deprecated for a while.

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

    You need to request the WAKE_LOCK permission in your manifest for that.

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