Spanish Apagar la pantalla y evitar Sleep

psdos

Active Member
Licensed User
Longtime User
Hola chicos, queria preguntaros como haceis para apagar la pantalla y que no consuma de ella y al mismo tiempo que nuestra aplicacion se mantenga viva sin dejar que la CPU se vaya a sleep mode.

Estoy haciendo pruebas para apagar la pantalla con

B4X:
Phone1.SetScreenBrightness(0)

Pero aunque me la apaga, no parece que el programa siga vivo y no puedo emitir un sonido. Busco hacer una alarma sonora a una determinada hora.

Mantengo viva la CPU con un servicio en el cual ejecuto lo siguiente

B4X:
Sub Service_Start (StartingIntent As Intent)
   
   'ToastMessageShow("At Device Wakeup", True)

    StartServiceAt("", DateTime.Now + .25 * 60 * 1000, True)
   
    Awake.KeepAlive(True)'Esta opcion evita que la pantalla se apague
   
   Awake.PartialLock
   
End Sub


Un saludo y muchas gracias.
 

psdos

Active Member
Licensed User
Longtime User
Solucionado

Bueno, ya encontre solucion, mi programa lo que hace es, cuando marcamos en un CheckBox, nos inicia este servicio que comprueba cada segundo, si hemos llegado al minuto 59 y al segundo 56 de una hora (hago que cada hora me de un aviso por voz). El servicio teneis que agregarlo como "Service Module".

B4X:
'Service module
Sub Process_Globals
   'These global variables will be declared once when the application starts.
   'These variables can be accessed from all modules.
   Dim Awake As PhoneWakeState
   Dim Beeper1 As Beeper
   DateTime.TimeFormat = "HH:mm:ss"
   
End Sub

Sub Service_Create

End Sub

Sub Service_Start (StartingIntent As Intent)

    StartServiceAt("", DateTime.Now + 1000, True)'Cada 1 seg envia el servicio
   
   If s.Right(DateTime.Time(DateTime.Now), 5) = "59:55" Then
      
      Awake.KeepAlive(True)
      Beeper1.Beep
      
   End If
   
End Sub

Sub Service_Destroy
   
   CancelScheduledService("")
   
End Sub


Una vez llegado al momento que quiero, en nuestro Activity_Resume ponemos lo siguiente, que trascurridos 5 seg, nos permitira lanzar un sonido o una voz (Al parecer si no le damos este tiempo al dispositivo, aun no ha despertado y no se oyen los avisos ni sonidos).

B4X:
Sub Activity_Resume

   If TTS1.IsInitialized = False Then
      TTS1.Initialize("TTS1")
      TTS1.SetLanguage("es_SP","")
   End If
   
   If CheckBox2.Checked = True Then
   
      SetShowWhenLocked 'Una vez que logramos activar la pantalla, esta rutina muestra lo que hay debajo de la pantalla de bloqueo, o sea nuestro programa.
      Timer2.Initialize("Timer2", 5000)
       Timer2.Enabled = True
      
   End If
   
End Sub

Aqui la parte donde detectamos que se ha pulsado el CheckBox2 que es el que activa los avisos

B4X:
Sub CheckBox2_CheckedChange(Checked As Boolean) 'Opcion avisar lecturas barco
   
   If CheckBox2.Checked = True Then
      
      Beeper1.Beep
      StartServiceAt(DeviceWakupService, DateTime.Now, True)
      
   End If
   
   If CheckBox2.Checked = False Then
   
      Beeper1.Beep
      CancelScheduledService(DeviceWakupService)
   
   End If
   
End Sub

Aqui el codigo que esta en el Timer2

B4X:
Sub Timer2_Tick

      RemoveShowWhenLocked 'Desactiva el mostrar lo que hay debajo de la pantalla de bloqueo al encender el dispositivo.
      Awake.ReleaseKeepAlive 'Habilita de nuevo el control de energia que tuviera el dispositivo.
      Timer2.Enabled = False 'Deshabilita el Timer para que no lo repita mas.

End Sub

El codigo del Timer1 que comprueba que es la hora en punto

B4X:
Sub Timer1_Tick

    DateTime.TimeFormat = "HH:mm:ss"
   DateTime.DateFormat = "dd/MM/yy"
   Label8.TextColor = Colors.Yellow
   Label9.TextColor = Colors.Yellow
   Label8.TextSize = 11
   Label9.TextSize = 11
   Label9.text = DateTime.Time(DateTime.Now)
    Label8.text = DateTime.Date(DateTime.Now)
   
   If CheckBox2.Checked = True Then
   
      
      If Label9.Text = "00:00:00" Then
      
         texto_voz = "Son las doce de la noche"
         Hablar
      
      End If
   
   End If
   
End Sub

Y aqui las rutinas para mostrar lo que hay debajo de la pantalla de bloqueo, es decir, nuetros programa.

B4X:
Sub SetShowWhenLocked

    Dim r As Reflector
    r.Target = r.GetActivity
    r.Target = r.RunMethod("getWindow")
    r.RunMethod2("addFlags", 6815872, "java.lang.int")
   
End Sub

Y el codigo que deshabilita este metodo

B4X:
Sub RemoveShowWhenLocked

    Dim r As Reflector
    r.Target = r.GetActivity
    r.Target = r.RunMethod("getWindow")
    r.RunMethod2("clearFlags", 6815872, "java.lang.int")
   
End Sub

Espero que este codigo os ayude, me ha costado mucho lograrlo y hacer muchas pruebas.

Un saludo.
 
Last edited:

VictorTandil

Member
Licensed User
Longtime User
Sos un groso, gracias. Me ha ayudado a entender varias cosas que ni en los foros de inglés están. Aguante el foro en Español!
 

bgsoft

Well-Known Member
Licensed User
Longtime User
Hola Psdos:

Varias cosas, seria interesante que antes de bloquear o desbloquear la pantalla, primero comprobaras en que estado está, y dependiendo de este actuar:
B4X:
Sub ComprobarBloqueoPantalla As Boolean
dim PantallaBloqueada as boolean

r.Target = r.GetContext
r.Target = r.RunMethod2("getSystemService", "keyguard", "java.lang.String")
PantallaBloqueada = r.RunMethod("inKeyguardRestrictedInputMode")

Return  PantallaBloqueada
End Sub

Si añades en el servicio:
B4X:
#Region  Service Attributes
   #StartCommandReturnValue: android.app.Service.START_STICKY
harás que el sistema al matar el servicio lo vuelva a ejecutar (https://www.b4x.com/android/forum/threads/b4a-tutorial-módulos-de-servicio.42689/ )

La inicialización del temporizador mejor que la quites donde está, por que si ocurre mas de una vez sin salir de la aplicación (girando la pantalla por ejemplo) te va a crear varias instancias del evento y te volverás loco cuando te ejecute el codigo n veces . Deja donde has puesto el habilitarlo. Y tambien pasa el inicializar las TTS. y Pones en el Sub Process_Globals la declaración del temporizador
B4X:
Sub Activity_Create(FirstTime As Boolean)
If FirstTime Then 
  ' pon tambien el timer1
  Timer2.Initialize("Timer2", 5000) 
  TTS1.Initialize("TTS1")
  TTS1.SetLanguage("es_SP","")
end if
El servicio no lo matas solo con CancelScheduledService(DeviceWakupService) , con eso para las llamadas pendientes que has echo con StartServiceAt , para pararlo debes :
B4X:
StopService(DeviceWakupService)

Otro problema es que "te comeras" la bateria llamando a un servicio cada segundo, si sabes que quieres dar el aviso a las 12 en punto (o cualquier otra hora), haz una llamada al StartServiceAt restando el tiempo actual a esa hora de la alarma.

De la forma que has planteado la aplicación, "siempre" estará activa, por tanto un servicio no tiene sentido, y digo siempre, por que depende de los ajustes, al tiempo se apagará la pantalla y tu aplicación se ira a Pause.
Por otro lado, al poner en marcha el temporizador 2 en el Resume, la primera vez que entres no está el checkbox activo por lo que el timer2 no se pondrá nunca en marcha a menos que gires la pantalla.
Mírate el ciclo de vida de Android https://www.b4x.com/android/forum/t...ia-rápida-del-ciclo-de-vida-de-android.38760/

Que seria mas operativo?
- pon un botón de salir, cuando lo pulses pon en marcha o paras el servicio, grabas el estado del check a un fichero y sal de la aplicación. También puedes mirar el evento Pause y hacerlo allí
- Cuando entres, en Create, lee el fichero y pon el check como estaba la ultima vez
- en el servicio haz que se vuelva a llamar momentos antes de que se cumpla tu hora de alarma, de esa forma ahorras bateria. Cuando esta se cumpla llamas a main (StartActivity(Main)) , en main en
el Sub Activity_Create(FirstTime As Boolean) comprueba si la pantalla está bloqueada, desbloqueala y en Resume llamas a hablar. Emplea la biblioteca Phone y el evento TextToSpeechFinish y así sabrás ciertamente cuando tu mensaje de voz finalizó y te ahorras el timer 2 .

B4X:
Sub Process_Globals
dim EstadoVoz As PhoneEvents
'..........
'..........
'..........

Sub Activity_Create(FirstTime As Boolean) 
Dim PhoneId As PhoneId
Dim PE As PhoneEvents
EstadoVoz.InitializeWithPhoneState("PE",PhoneId)
'..........
'..........
'..........


Sub PE_TextToSpeechFinish (Intent As Intent)
  ' MensajeVozFinalizado
  ' pon tu codigo
End Sub

Saludos
 

VictorTandil

Member
Licensed User
Longtime User
Muy buen aporte, gracias. Sobre todo por la Sub de verificar la pantalla de bloqueo, no la tenia a esa.
 
Top