Android Question How to replace a local notification 'Service' with a 'Receiver'

Cliff McKibbin

Member
Licensed User
I have brought up B4A v12.2 in hopes it would solve a problem I have with my 'local notification' logic not working cleanly on Android 13.

Erel points out that 'Receivers' should now be used instead of services:

My current logic consists of modules 'FSService' and 'Scheduler' shown below.
I can't find the forum/examples that I originally used but I'm sure I didn't invent them.

The process is started in B4XMainPage by calling:
B4X:
        ' get alerts- note it will fire starter.getnotifications
        Starter.bFireService=False
        StartServiceAt (Scheduler, DateTime.now,False)

'Scheduler' in turn calls 'starter.getnotifications' to determine if the local notification should be other than a daily notification which I have set at 0700 daily. If an event starts at 3pm of the same day, it will supersede the 0700 notification. In turn, when the 3pm notification is fired, 'FSService' is fired which then calls 'Scheduler' and the process will reset to 0700 the next day unless there is another notification before then. etc., etc.

The current logic works fine on a pre-Android 13 device even when asleep. On the Android 13 device it does not wake the device up and beep. It also has crashed the App when I turn it on in the morning, but that phenomenon is intermittent.

The question for today is how to replace any of this with the new 'receiver' module. If there is an example in the forum, please let me know, otherwise, It would be good to have a new forum tutorial on local notifications using the receiver.

Thanks, Cliff McKibbin

'FSService'
B4X:
#Region  Service Attributes
    #StartAtBoot: False
   
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
End Sub

Sub Service_Create
End Sub

Sub Service_Start (StartingIntent As Intent)
   
    ' Service.StopAutomaticForeground 'Call this when the background task completes (if there is one)
   
    ' logic of FSService changed on 6/24/19 cwm
    Starter.bFireService=True
    StartServiceAt (Scheduler, DateTime.now,False)
   
End Sub

'Scheduler'
B4X:
#Region  Service Attributes
    #StartAtBoot: true
#End Region

Sub Process_Globals
    'These global variables will be declared once when the application starts.
    'These variables can be accessed from all modules.
    Public NextStartTime, OtherStartTime As Double
    Public X1, X2, sNotes1, sNotes2 As String
    Public i As Int
End Sub

Sub Service_Create
End Sub

Sub Service_Start (StartingIntent As Intent)
    ' Service.StopAutomaticForeground 'Call this when the background task completes (if there is one)
    StartSchedule
                           
End Sub

public Sub StartSchedule
    ' sub to schedule the next notification    6/3/19 cwm
    Dim ITime As Int
   
    ' fire sync read  1/8/23 cwm
    If Starter.bIntSync Then
        Starter.HTTPReadsync (1,Starter.SSyName)
    End If
   
    ' get notifications for next alert/notif time
    Starter.getnotifications
       
    ' only notif if SNotifTime is non zero
    If Starter.SNotifTime.trim.CompareTo("")=0 Then Starter.SNotifTime=0
    If Starter.SNotifTime>0 Then
   
        ' get the current time and compare to the notif time
        ' this was very tricky-had to add 5 minutes to itime and compare to our time with '00' added
        '   in order not to loop and do multiple notifications.
        DateTime.DateFormat="HHmmss"
        ITime=DateTime.date (DateTime.Now+(DateTime.TicksPerMinute)*5)
        Log ("Comparing Notification times " & ITime & " " & Starter.SNotifTime & "00")
       
        If ITime< Starter.SNotifTime & "00" Then
            ' not yet the time for the notify-keep it to today's date
            NextStartTime=DateTime.Now
         Else
            ' bump the notify to tomorrow
            NextStartTime=DateTime.Add(DateTime.now,0,0,1)
        End If
       
        ' now change the hhmm to use the SNotifTime
        DateTime.DateFormat="yyyyMMddHHmm"
        X1=DateTime.Date (NextStartTime)
        ' get string for Snotiftime
        X2=NumberFormat(Starter.SNotifTime,4,0)
        ' note numberformat puts commas in a 4 digit number
        X2=X2.SubString2(0,1) & X2.SubString2(2,5)
        ' now put together the date and hhmm
        X1=X1.SubString2(0,8) & X2
        NextStartTime=DateTime.DateParse(X1)
       
        ' test every 15 seconds
        '  NextStartTime=DateTime.Now+ DateTime.TicksPerMinute/4
              
        ' now compare the nextstarttime to the alertstarttime   6/13/19 cwm
        If Starter.NextAlerttime.CompareTo("300012312400") <>0 Then
            ' we have a valid next alert time
            If Starter.NextAlertTime.CompareTo(X1) <0 Then
                NextStartTime=DateTime.DateParse(Starter.nextalerttime)
                End If   
        End If
   
        ' get final x1 formated
        DateTime.DateFormat="yyyy/MM/dd HH:mm"
        X1=DateTime.Date (NextStartTime)
       
        ' set up the notification
        Dim n As Notification
        n.Initialize
        n.Sound=False
        n.Vibrate=False
        n.Icon="icon"
       
        ' mod to vary the display depending if alerts are available  6/24/19 cwm
        If Starter.SNotif.Size>0 Then
            sNotes1="FS has alerts for you. Touch here."
            If Starter.SnotifSound=1 Then n.Sound = True
            If Starter.SnotifSound=3 Then n.Sound = True
            If Starter.SnotifSound=2 Then n.Vibrate = True
            If Starter.SnotifSound=3 Then n.vibrate = True
            ' check if the notification situation has changed-  10/8/20 cwm
            '  if so mod the starter.nextstarttime to force a notif
            If Starter.Notifications=False Then
                Starter.NextStartTime=0
                Starter.Notifications=True
                End If
            Else
            sNotes1="FS has no alerts for today."
            ' check if the notification situation has changed- 10/8/20 cwn
            ' if so mod the starter.nextstarttime to force a notif
            If Starter.Notifications=True Then
                Starter.NextStartTime=0
                Starter.Notifications=False
                End If
            End If
       
        sNotes2= "Next Notification:" & X1
        ToastMessageShow ( sNotes2,False)
       
        ' fire the notification
        ' only if the starter.nextStartTime has changed or the notification status changed   10/8/20 cwm
'        Log ("Before:" & Starter.NextStartTime & " " & NextStartTime & " " & Starter.Notifications)
   
        If Starter.NextstartTime<>NextStartTime Then
            n.SetInfo(sNotes1,sNotes2,  "Main")
'            Log (sNotes1 & CRLF & sNotes2)
            ' note the significance of the '1'/it indicates to replace any other notification from FS with a '1' in it
            ' if you wanted multiple notifications you could use '2', '3', etc.
            n.Notify(1)
           
            ' start the next service-
            StartServiceAt (FSService, NextStartTime,False)
            ' save the nextstarttime so we don't repeat unless it does change 10/8/20 cwm
            Starter.NextStartTime=NextStartTime
'            Log ("After:" & DateTime.Date(NextStartTime) & " " & Starter.Notifications)
        End If   
    End If
End Sub

Sub Service_Destroy
End Sub
 
Last edited:

Cliff McKibbin

Member
Licensed User
Based on Erel's suggestion, I did the following:
1. Changed the 'FSService' above to a 'receiver' named 'FSReceiver' and changed the StartServiceat to StartReceiverAt. I have also changed the 'false' in all the calls to 'True' to attempt to wake up the app when it is not even started.

2. I changed the 'Scheduler' service above to a 'receiver' named 'FSScheduler', I changed the Startserviceat to startreceiverat, again with 'true'

3. I changed the startup process in B4XMainPage to startreceiverat.

4. I modified the manifest to:
B4X:
AddPermission(android.permission.SYSTEM_ALERT_WINDOW)
AddPermission(android.permission.RECEIVE_BOOT_COMPLETED)
AddReceiverText(FSReceiver, <intent-filter>
<action android:name="android.intent.action.BOOT_COMPLETED"/>
</intent-filter>)


5. I followed the steps to get alert permission as discussed in:
with the additons of:

a. I added the logic to get alert permission in the b4xMainPage Sub B4XPage_Created:
B4X:
    Dim c  As GetAlertPermission 'this is the name of the class
    c.Initialize
    Wait For (c.GetPermission) Complete (Success As Boolean)
    Log("Alert Permission: " & Success)

b. I added the class 'GetAlertPermission'

B4X:
Sub Class_Globals
    Private ion As Object
    Private phone As Phone
End Sub

Public Sub Initialize
End Sub

Public Sub GetPermission As ResumableSub
    If phone.SdkVersion >= 23 Then
        Dim settings As JavaObject
        settings.InitializeStatic("android.provider.Settings")
        Dim ctxt As JavaObject
        ctxt.InitializeContext
        If settings.RunMethod("canDrawOverlays", Array(ctxt)) = True Then
            Return True
        End If
        Dim i As Intent
        i.Initialize("android.settings.action.MANAGE_OVERLAY_PERMISSION", "package:" & Application.PackageName)
        StartActivityForResult(i)
        Wait For ion_Event (MethodName As String, Args() As Object)
        Return settings.RunMethod("canDrawOverlays", Array(ctxt))
    Else
        Return True
    End If
End Sub

Private Sub StartActivityForResult(i As Intent)
    Dim jo As JavaObject = GetBA
    ion = jo.CreateEvent("anywheresoftware.b4a.IOnActivityResult", "ion", Null)
    jo.RunMethod("startActivityForResult", Array As Object(ion, i))
End Sub

Private Sub GetBA As Object
    Dim jo As JavaObject = Me
    Return jo.RunMethod("getBA", Null)
End Sub


The result is:
1. The app on Android 7 works as it used to. It sends a notification that is fired when the app is active, when the app is not on top, and even when the app has been stopped.
2. The app on Android 13 only fires the notification when the app is active.
3. I just realized that the app is also not firing the sound on Android 12 and 13.

My question: Is this what is expected with Android 13. Will we not be able to fire a local notification and expect the app to wake up or start up?

Or, am I still missing something?

Has the 'sound' action changed in android 12? I looked everywhere to enable the sound and it appears it should work.

Thanks, Cliff McKibbin
 
Upvote 0
Top