iOS Question What happens with push, if app is in the background?

schimanski

Well-Known Member
Licensed User
Longtime User
I have mentioned the following problem:

I'm sendung push-messages to fcm with

B4X:
Dim m As Map = CreateMap("registration_ids": Devices)
m.Put("data", msg)
Dim iosalert As Map =  CreateMap("title": notifytitle, "body": "neue Informationen")
m.Put("notification", iosalert)
m.Put("priority", 10)
m.Put("content_available", True)
....

As I previously assumed, this works, until I kill the app over the taskmanager. When it is killed, the notification arrives, but it is not possible to read the content_data or play a sound over the mediaplayer, because the app doesn't rais the remote_notification_event.

But now, if the app is not used for a longer time, the app seems to be killed comletly by the ios. The app is continoulsy in the taskmanager, but remote_notification is not raised. Did something changed under the new ios-systems?

And how does the others work with the ios-push?
 

schimanski

Well-Known Member
Licensed User
Longtime User
The process will be started automatically if it is no longer running.

That seems not be correct. If the app is not killed with a swipe but when it is longer not used, the remote_notification is still not raised. After a while, the apps behaviour is the same as after killing it with a swipe...I think, that the app will not started automatically. I tried it in release with four differnt devices and ios 10.2.1.
 
Last edited:
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
Thanks for your efforts!

I followed all the steps and use this for silent-push and background-fetch:

B4X:
'Remote-Notifications, Hintergundtasks und Abspielen von Sounds im Hintergrund zulassen'
#PlistExtra: <key>UIBackgroundModes</key><array><string>fetch</string><string>remote-notification</string><string>audio</string></array>

with the attached main.m-file.

I followed these steps:
Testing

iOS will not start the app automatically if the user has killed it. This makes it a bit difficult to test that it really works.
In order to test it you need to compile it in Release mode and run it once.
Now install the app again and do not start it. Send a silent push message and the process should start.
The app will not be visible. You can show a local notification to see that it is working.
You can also use this tool to monitor the logs in release mode: iReleaseLogger - Read the logs in release mode

and it works. But i would maintain that after a couple of hours, when the app is not used, the os did not start the process after an incoming notification.
This behavior of several devices with ios 10.2.1 is the same as after killing the app with a swipe. Is there something else important to consider?

Thanks for help...
 

Attachments

  • main.zip
    516 bytes · Views: 360
Upvote 0

tufanv

Expert
Licensed User
Longtime User
I experienced the same thing and at last gave up. Some notifications were coming but some of them were not after some time passed. I changed to regular push. Maybe i was doing stg wrong. I don't know.
Thanks for your efforts!

I followed all the steps and use this for silent-push and background-fetch:

B4X:
'Remote-Notifications, Hintergundtasks und Abspielen von Sounds im Hintergrund zulassen'
#PlistExtra: <key>UIBackgroundModes</key><array><string>fetch</string><string>remote-notification</string><string>audio</string></array>

with the attached main.m-file.

I followed these steps:


and it works. But i would maintain that after a couple of hours, when the app is not used, the os did not start the process after an incoming notification.
This behavior of several devices with ios 10.2.1 is the same as after killing the app with a swipe. Is there something else important to consider?

Thanks for help...
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
Much thanks for your answer. I thougt, I'm crazy..:confused:Since more than one year, I try to get the apple-push on the same level as the android-push without success. It needs only two days, than the guys in my company comes and tells me, that the apple-push don't work properly. I'm shortly before to give up....
 
Upvote 0

tufanv

Expert
Licensed User
Longtime User
Much thanks for your answer. I thougt, I'm crazy..:confused:Since more than one year, I try to get the apple-push on the same level as the android-push without success. It needs only two days, than the guys in my company comes and tells me, that the apple-push don't work properly. I'm shortly before to give up....
This is the experience i got from the silent push notifications. I couldnt run it well. But Erel says it works ok and he is generally right about his sayings =) So maybe we are doing stg wrong. Anyways i am not using them anymore hope you can fix it.
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
I'm realy sure, that the mistake is in my code, but your experiences shows me, that silent push in not so simple to do as it seems to be...
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
Hello Erel!

1. I saw this thread on yesterday and some others. It seems, that starting the app from background after an silent-push-notification is depending on many things or isn't it?

2. The main.m file is related to the fetchdownload. Is it no longer required? I thought, that the main-file related to remote-notification is no longer required.

3. Here is my code for Application_RemoteNotification:

B4X:
Private Sub Application_RemoteNotification (Message As Map, CompletionHandler As CompletionHandler)
   
   Nachrichten_verarbeiten(Message, True)
   
   'This inits a servers-synch after push-notification:
   If manager.GetString("Anmeldung")="aktiv" Then CallSubDelayed(LadeService, "DeviceDownloadMap_laden")

   CompletionHandler.Complete
End Sub

'This sub does everything i need after a push-notification or after a server-synch:
Sub Nachrichten_verarbeiten(Message As Map, PlaySound As Boolean)
   
   Dim Intent As Map = Message
   
   If Intent.Get("steuerbefehl")="" Then
     Dim AllSpeicher, KonferenzSpeicher, AbsenderSpeicher, SenderSpeicher, FilenameSpeicher, DatenSpeicher, ZeitstempelSpeicher, GroessenSpeicher As String
     KonferenzSpeicher = Intent.Get("konferenz")   
     AbsenderSpeicher = Intent.Get("absender")
     SenderSpeicher = Intent.Get("sender")
     FilenameSpeicher = Intent.Get("filename")
     DatenSpeicher = Intent.Get("daten")
     ZeitstempelSpeicher = Intent.Get("zeitstempel")
     GroessenSpeicher = Intent.Get("groesse")
     
   
     If SenderSpeicher="Kontakte" Then
       AllSpeicher=AbsenderSpeicher
     Else
       AllSpeicher=KonferenzSpeicher
     End If
     
     If File.Exists(File.DirLibrary, AllSpeicher & ".eis")=True Then
       Dim Dokumentdatei As RandomAccessFile
       Dokumentdatei.Initialize(File.DirLibrary, AllSpeicher & ".eis", False)
       ListeDokumente2=Dokumentdatei.Readb4xObject(0)
       Dokumentdatei.Close
     Else
       ListeDokumente2.Initialize
     End If
     
     
     'Jede Notification und jeder Download vom Server im Rahmen der Synchronisierung werden wie eine Notifikation verarbeitet.
     'Zuvor word allerdings immer geprüft, ob das Dokument mit dem Namen bereits vorhanden ist, um dopplete Einträge zu verhindern.
     Dim ts As Boolean=False
     For i=0 To ListeDokumente2.Size-1
       Dim dok As Dokumententyp = ListeDokumente2.Get(i)
       If dok.Name=FilenameSpeicher Then
         ts=True
         Exit
       End If
     Next
     
     'Ist noch kein Dokument mit dem Namen vorhanden, wird es als Notification abgearbeitet.
     If ts=False Then
     
       'Verzeichnis hier schon erstellen, weil ansonsten die App abstürzen kann, wenn Verzeichnis noch nicht erstellt wurde'
       If File.Exists(File.DirDocuments & "/EIS/" & SenderSpeicher & "/" & AllSpeicher, "")=False Then File.MakeDir(File.DirDocuments, "/EIS/" & SenderSpeicher & "/" & AllSpeicher)
       
       Dim Dokument As Dokumententyp
       Dokument.Name=FilenameSpeicher
       Dokument.Groesse=GroessenSpeicher
       
       'Mit Zeitstempelspeicher wird die Zeit vom Server genommen. Da diese aber gegeüber der Zeit des Geräts abweichen kann, kommt es nach der Sortierung der Dokumentenliste oft zu Verschiebungen,
       'weil die eigenen Dokumente mit DateTime.now eingefügt werden. Aus diesem Grund wird jetzt für ankommende Dokumente auch die Geräte- und nicht die Serverzeit genommen'
       'Im Bedarfsfall kann somit in den Logs des Servers die Eingangszeit nachträglich bestimmt und über das Gerät die tatsächliche Empfangszeit bestimmt werden. Über das Sendegerät kann die Versendezeit eingesehen weden,'
       'so dass eine lückenlose Dokumentation möglich wäre.'
       Dokument.Zeitstempel=ZeitstempelSpeicher
       'Dokument.Zeitstempel=DateTime.Now
       
       'Datenspeicher ist verschlüsselt, Dokument.text soll entschlüsselten Text halten, wenn es eine Textdatei ist
       If FilenameSpeicher.ToLowerCase.EndsWith(".txt") Then
         Dim KeySpeicher As String
         KeySpeicher=VerifyKey(SenderSpeicher, AllSpeicher)
         If KeySpeicher<>"" Then
           Dokument.Text=Wandler.decrypt(DatenSpeicher, VerifyKey(SenderSpeicher, AllSpeicher))
         Else
           Dokument.Text=KeySpeicher
         End If
       Else
         Dokument.text=DatenSpeicher
       End If
       
       Dokument.Absender=AbsenderSpeicher
       
       '##########################
       'Hier liegt wahrscheinlich der Fehler beim Schreiben in die falsche Map. Das könnte auch zu dem falschen Nachricjtenschlüssel führen.'
       If KonferenzAktiv=True And SenderSpeicher=Verzeichnis And AllSpeicher=Konferenznummer Then        '########Konferenzaktiv dazu gekommen!!!
         'If SenderSpeicher=Verzeichnis And AllSpeicher=Konferenznummer Then
         ListeDokumente.Add(Dokument)
         Dim Dokumentdatei As RandomAccessFile
         Dokumentdatei.Initialize(File.DirLibrary, AllSpeicher & ".eis", False)
         Dokumentdatei.Writeb4xObject(ListeDokumente, 0)
         Dokumentdatei.Close
       Else
         ListeDokumente2.Add(Dokument)
         Dim Dokumentdatei As RandomAccessFile
         Dokumentdatei.Initialize(File.DirLibrary, AllSpeicher & ".eis", False)
         Dokumentdatei.Writeb4xObject(ListeDokumente2, 0)
         Dokumentdatei.Close
       End If
       '     '###############################

       If FilenameSpeicher.ToLowerCase.EndsWith(".txt") Then
         File.WriteString(File.DirDocuments & "/EIS/" & SenderSpeicher & "/" & AllSpeicher & "/" , Dokument.Name, DatenSpeicher)
       Else
         '       'Hier wird der automatische Download angestoßen, falls die Option in den Einstellungen aktiviert wurde'
         If manager.GetBoolean("Bilder")=True Then
           If FilenameSpeicher.ToLowerCase.EndsWith(".png") Or FilenameSpeicher.ToLowerCase.EndsWith(".jpg") Or FilenameSpeicher.ToLowerCase.EndsWith(".jpeg") Or FilenameSpeicher.ToLowerCase.EndsWith(".bmp") Or FilenameSpeicher.ToLowerCase.EndsWith(".gif") Or FilenameSpeicher.ToLowerCase.EndsWith(".tif") Then
             Dim dd As DownloadData
             dd.Verz=SenderSpeicher
             dd.Konferenznr=AllSpeicher
             dd.DokName=FilenameSpeicher
             CallSubDelayed2(LadeService, "Dokument_downloaden", dd)
           End If
         End If
       End If
       '
       '     'Wenn Konferenz oder Kontakt geöffnet ist, Daten in die ULV eintragen'
       If SenderSpeicher=Verzeichnis And AllSpeicher=Konferenznummer And KonferenzAktiv=True Then
         If FilenameSpeicher.ToLowerCase.EndsWith(".png") Or FilenameSpeicher.ToLowerCase.EndsWith(".jpg") Or FilenameSpeicher.ToLowerCase.EndsWith(".jpeg") Or FilenameSpeicher.ToLowerCase.EndsWith(".bmp") Or FilenameSpeicher.ToLowerCase.EndsWith(".gif") Or FilenameSpeicher.ToLowerCase.EndsWith(".tif") Then
           'Fremdes_Bild_einfuegen(AllSpeicher, Dokument.Zeitstempel, Dokument.Name)
           Fremdes_Bild_einfuegen(AbsenderSpeicher, Dokument.Zeitstempel, Dokument.Name, Dokument.Groesse)
           clv.JumpToItem(clv.GetSize-1)
         Else
           If FilenameSpeicher.ToLowerCase.EndsWith(".txt") Then
             'Fremdes_Dokument_einfuegen(AllSpeicher, Dokument.Text, False, Dokument.Zeitstempel, Dokument.Name)
             Fremdes_Dokument_einfuegen(AbsenderSpeicher, Dokument.Text, False, Dokument.Zeitstempel, Dokument.Name, Dokument.Groesse)
           Else
             'Fremdes_Dokument_einfuegen(AllSpeicher, Dokument.Text, True, Dokument.Zeitstempel, Dokument.Name)
             Fremdes_Dokument_einfuegen(AbsenderSpeicher, Dokument.Text, True, Dokument.Zeitstempel, Dokument.Name, Dokument.Groesse)
           End If
           clv.JumpToItem(clv.GetSize-1)
         End If

         SoundChat.Play
     
         ZeitstempelMap.Put(AllSpeicher, Dokument.Zeitstempel)
       Else
     
         Notification_sound(AllSpeicher, PlaySound)
           
         ZeitstempelMap.Put(AllSpeicher, Dokument.Zeitstempel)
         Ungelesen.Put(AllSpeicher, "True")
         
         CallSub(Konferenz, "ListeKonferenz_erstellen")

       End If
       
       'Löschen der Kontaktgruppe vom Gerät, wenn die Kontaktgruppe bearbeitet wurde, um sie beim nächsten Ausruf der Konferenz neu zu laden
       'Die Löschung wird auch gemacht, wenn Push-Empfang ausgeschaltet ist!
       If SenderSpeicher="Konferenzen" Then
         If FilenameSpeicher.EndsWith(".txt") Then
           If Dokument.Text="Kontaktgruppe bearbeitet!" Then
             If File.Exists(File.DirLibrary, "KG_" & KonferenzSpeicher & ".eis")=True Then File.Delete(File.DirLibrary, "KG_" & KonferenzSpeicher & ".eis")
             If SchluesselDB2.ContainsKey(KonferenzSpeicher) Then SchluesselDB2.Remove(KonferenzSpeicher)
           End If
         End If
       End If
     
     End If
     
   Else
     
     Dim Steuerbefehl, Filename As String
     Steuerbefehl=Intent.Get("steuerbefehl")
     Filename=Intent.get("filename")
     
     'Kontaktgruppe löschen, wenn der entsprechende Steuerbefehl gesendet wurde. Dieser Fall tritt auf, wenn das Gerät aus der Kontaktgruppe genommen wurde'
     If Steuerbefehl="verlassen" Then
       If File.Exists(File.DirLibrary, Filename)=True Then
         File.Delete(File.DirLibrary, Filename)
       End If
     Else
       If Steuerbefehl="schlagzeile" Or Steuerbefehl="schlagzeileserver" Then
         Dim DatenSpeicher, AbsenderSpeicher As String
         If Intent.ContainsKey("daten") Then DatenSpeicher=Intent.Get("daten")
         If Intent.ContainsKey("absender") Then   AbsenderSpeicher = Intent.Get("absender")
         Schlagzeile_anzeigen(DatenSpeicher, AbsenderSpeicher)
       Else
         Steuerbefehl_ausfuehren(Steuerbefehl)
       End If
     End If
   End If

End Sub
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
The main.m is indeed still required for fetch downloads. It is worth testing it without this feature.

Your code is wrong. You shouldn't call CompletionHandler.Complete before you actually complete the task.

Ok, i could test it with the normal main-file.
But i also set the CompletionHandler.Complete at the end of my sub Nachrichten_verarbeiten after hands over it as argument...it makes no different..
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
Make sure not to call it twice.

I did not call it twice. Is it a good solution to call it, after the sub Nachrichten_verarbeiten gave back a boolean with true instead of hands over it with an argument?
 
Upvote 0

schimanski

Well-Known Member
Licensed User
Longtime User
Thank you for your efforts. I have changed the code in that way:

B4X:
Private Sub Application_RemoteNotification (Message As Map, CompletionHandler As CompletionHandler)

   if Nachrichten_verarbeiten(Message, True)=true then CompletionHandler.Complete

   'This inits a servers-synch after push-notification:
   If manager.GetString("Anmeldung")="aktiv" Then CallSubDelayed(LadeService, "DeviceDownloadMap_laden")


End Sub

'This sub does everything i need after a push-notification or after a server-synch:
Sub Nachrichten_verarbeiten(Message As Map, PlaySound As Boolean) as booloean
   Dim Intent As Map = Message
   ....
   ..
   Return True
End sub

But this is also not able to wake up the phone every notification arrives. Related to this:

,

I found this:

https://developer.apple.com/library/content/technotes/tn2265/_index.html#//apple_ref/doc/uid/DTS40010376-CH1-TNTAG23


It seems not to be possible to make sure, that the app reads the content-data after an silent push arrives. After testing it with more than 100 users, the determin, that starting the app in not energy-efficient, happens very often. As Erel told in many threads berfore, that it is not possible to rely on push-messages and always make sure to load the needed data from server, silent push is no reliable tool. So far, i didn't thought, that apple controls this feature so massively.
I now use normal push together with content-available-data. If the app is not able to read the content-data, the app makes a synch with the server to download all, which is needed.

But there is only one thing, that i did not understand:

Like the link before, if it is not energy-efficent etc. to start the app, the content-available key will not be delivered. But if pressing the notification, the remote_notification sub is raised and the content-data will be there. For me, it looks like, that the content-available-data is available on the device together with the incomming notification. Why is it not possible to read this data out without pressing on the notify? No user presses the notify, if the app-icon shows a badge-number...
 
Last edited:
Upvote 0
Top