I am trying to grasp push notifications on iOS and also trying to get silent notifications working.
Silent notifications should be supported on iOS7+ according to http://hayageek.com/ios-silent-push-notifications/
I have this code:
My questions:
1. Is the "Application_PushToken" sub called *ONLY* when the device is first registered for PUSH NOTIFICATIONS (like the registration in GCM) - and is the event fired only once and only after calling
App.RegisterUserNotifications(True, True, True) and
App.RegisterForRemoteNotifications
?
2. At the line that has the comment "TODO: What do I need to call here for IOS to be happy ?":
What do I need to call for iOS to be happy ? What confuses me is what I've read here:
http://www.g8production.com/post/72656082173/ios7-multitasking-silent-notifications about
returning a UIBackgroundFetchResult ?
All my processing of push notifications should be completed within the 30 seconds of wall clock time given by Apple. It simply updates the local DB with the data in the push message
3. In the case where the user has not allowed push notifications, will the silent push notifications that I try to get working also be affected ? And if so, what is the alternative to using push notifications ?
4. How can I find out if the user disallows or allows push notifications ? Can I react to some kind of event or can I read the settings ?
5. Will "Application_RemoteNotification" sub be called regardless of wether or not my application is running/is in the foreground ?
6. Is this line:
#PlistExtra: <key>UIBackgroundModes</key><array><string>remote-notification</string></array>
enough to support silent push notifications ?
Sorry for a long post but I hope that the subject is of interest to others as well who are (like me) starting out on the journey of iOS development....
Thanks
/Henrik
Silent notifications should be supported on iOS7+ according to http://hayageek.com/ios-silent-push-notifications/
I have this code:
B4X:
'Code module
#Region Project Attributes
#ApplicationLabel: B4i Example
#Version: 1.0.0
'Orientation possible values: Portrait, LandscapeLeft, LandscapeRight and PortraitUpsideDown
' FIXME
#iPhoneOrientations: Portrait, LandscapeLeft, LandscapeRight
#iPadOrientations: Portrait, LandscapeLeft, LandscapeRight, PortraitUpsideDown
' Register for *SILENT* push notifications
#PlistExtra: <key>UIBackgroundModes</key><array><string>remote-notification</string></array>
' DEFAULT APP FONT
#AppFont: roboto-light.ttf
#End Region
Sub Process_Globals
'These global variables will be declared once when the application starts.
'Public variables can be accessed from all modules.
Public App As Application
Public NavControl As NavigationController
Private Page As Page
Dim theURI As String
Dim Const POSITION_TOP_LEFT As Int = 1
Dim Const POSITION_TOP_RIGHT As Int = 2
Dim Const POSITION_BOTTOM_LEFT As Int = 3
Dim Const POSITION_BOTTOM_RIGHT As Int = 4
Dim Const POSITION_CENTER As Int = 5
Public Const ADS_GRACE_PERIOD_DAYS As Int = 7 ' 7 Days grace period for ads
' Valid anims: zoom_enter, zoom_exit
' card_flip_left_in, card_flip_left_out
' card_flip_right_in, card_flip_right_out
' fade_out, fade_in
Public ACTIVITY_ANIMATION_IN_DEFAULT As String = "zoom_enter" ' Default inAnimation
Public ACTIVITY_ANIMATION_OUT_DEFAULT As String = "zoom_exit" ' Default OutAnimation
' Get from Google Console
Dim GCM_API_KEY As String = "XXXXX"
#If B4A
Dim locale As AHLocale : locale.Initialize
Dim trans As AHTranslator : trans.Initialize(File.DirAssets, locale.ISOCode)
Dim dt As AHDateTime : dt.Initialize
#End if
Public CURRENTUSER As User
Public CurrentNumberOfBeaconsToday As Int = 0
' Global ACTIVITY DESIGN
Public Const DEFAULT_FONT As String = "roboto-light.ttf"
Public Const DEFAULT_HEADLINE_SIZE As Int = 20
Public Const FULLSCREEN_ON_GLOBALLY As Boolean = True
Public Const ACTIVITY_GLOBAL_BG_COLOR As Int = Colors.ARGB(255, 255, 255, 255)
Public Const ACTIVITY_GLOBAL_TXT_COLOR As Int = Colors.ARGB(0, 0, 0,0 )
Public STARTED_FROM_HOME_PAGE_SHORTCUT As Boolean = False
Public Const TOPMENU_MAX_NUMBER_OF_VISIBLE_ITEMS_AT_A_TIME As Int = 8
Public Const DIALOGS_ANIMATION_DEFAULT As String = "zoom" ' Default animation to use when showing dialogs
' Available animations:
' zoom
' slide_from_top, slide_from_top_and_back
' slide_from_bottom, slide_from_bottom_and_back,
' slide_from_left,slide_from_left_and_back,
' slide_from_right,slide_from_right_and_back
Dim GPS1 As Location
Dim DB As SQL
'This code is essential if you want to use the menu for most activity.
Dim MenuItem As List
' TODO: Add support for only showing X (configurable at signup) ads from the same company within a 24 hour
' window...
Dim TRACKING_SIMILARITY_PCT As Double = 80.00
' TIMERS
Dim Clear24Timer As Timer
Dim CLEAR_SEEN_ADS_24_INTERVAL As Int = 864000000 : Clear24Timer.Initialize("Clear24Timer", CLEAR_SEEN_ADS_24_INTERVAL) : Clear24Timer.Enabled = True' Every 24 hours
Dim AdsSeenTimer As Timer : AdsSeenTimer.Initialize("AdsSeenTimer", ADS_GRACE_PERIOD_DAYS * 86400) : AdsSeenTimer.Enabled = True
Dim DEVICE_ID As String
Dim PROXIMITY_THRESHOLD_NEAR As Int = 5
Dim PROXIMITY_THRESHOLD_MIDDLE As Int = 15
Dim PROXIMITY_THRESHOLD_FAR As Int = 400
#If DEBUG
Dim APP_VENDOR_ID As String = "F782DA6-4FA2-4E98-8024-BC5B71E0893E"
Dim APP_APPLICATION_NAME As String = ":%s" ' This string *MUST* match the ProximityUUID of the ANDROID APP !!!
#End If
#If RELEASE
Dim APP_VENDOR_ID As String = "FE1D7269-84E6-4E54-BD95-8447D088ED6F"
Dim APP_APPLICATION_NAME As String = "xxxx:%s" ' This string *MUST* match the ProximityUUID of the iOS APP !!!
#End If
#IF DEBUG
Public Const DEBUG As Boolean = True
#End If
#If RELEASE
Public Const DEBUG As Boolean = False
#End If
#If RELEASE_INTERNAL
Public Const DEBUG As Boolean = True
#End If
' MAPS AND LISTS
Public AdsSeen As Map : AdsSeen.Initialize
Public knownBeacons As Map : knownBeacons.Initialize
Dim DB_FILENAME As String = "db.db"
End Sub
Private Sub Application_Start (Nav As NavigationController)
NavControl = Nav
' Register for push notifications
App.RegisterUserNotifications(True, True, True) 'allow badge, sound and alert
App.RegisterForRemoteNotifications
CheckForPushMessage
' Go to First page
FirstPage.Show
End Sub
#Region PUSH NOTIFICATIONS
Private Sub CheckForPushMessage
If App.LaunchOptions.IsInitialized AND _
App.LaunchOptions.ContainsKey("UIApplicationLaunchOptionsRemoteNotificationKey") Then
Dim data As Object = app.LaunchOptions.Get("UIApplicationLaunchOptionsRemoteNotificationKey")
Dim no As NativeObject = app
no.GetField("delegate").RunMethod("application:didReceiveRemoteNotification:", _
Array(App, data))
End If
End Sub
' TODO: Is this sub called *ONLY* when the device is first registered for PUSH NOTIFICATIONS ???
Private Sub Application_PushToken (Success As Boolean, Token() As Byte)
If Success Then
Dim bc As ByteConverter
Dim j As HttpJob
j.Initialize("j", Me)
'Dim paramsStr As String = "deviceID="&Main.DEVICE_ID&"&uuid="&Main.CURRENTUSER.ID&"&apptype=IOS&app="&Main.APP_APPLICATION_NAME.Replace("%s", "")
Dim paramsStr As String = "deviceID=" & bc.HexFromBytes(Token) & "&uuid="&CURRENTUSER.ID&"&apptype=IOS&app="&APP_APPLICATION_NAME.Replace("%s", "")
j.PostString(Callbacks.CB_DEVICE_REGISTRATION_URL & paramsStr)
Else
Utils.Log_("Error getting token: " & LastException)
End If
End Sub
' Called if the app is not in the foreground
Private Sub Application_RemoteNotification (Message As Map)
If DEBUG Then
Utils.Log_("Remote notification: " & Message)
End If
Dim m As Map = Message.Get("aps")
Dim tempMap As Map = Message.Get("data")
Dim thetype As String = tempMap.Get("type")
' Parse the Data
Dim Map1 As Map
Dim List1 As List
Map1.Initialize
List1.Initialize
Dim TYPE_OF_NOTIFICATION As Int = thetype
If m.Get("content-available") = "1" Then ' It's a silent notification
' Select what to do
Select TYPE_OF_NOTIFICATION
Case PushIncomingHandler.NOTIFICATION_TYPE_BEACONS_FOUND_CLEAR
knownBeacons.Clear
Case PushIncomingHandler.NOTIFICATION_TYPE_COMPANY_BOUGHT_MEMBERSHIP_ADDON
Map1 = tempMap.Get("data")
PushIncomingHandler.MarkThatCompanyHasMembership(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_COMPANY_CANCELLED_MEMBERSHIP_ADDON
Map1 = tempMap.Get("data")
PushIncomingHandler.RemoveThatCompanyHasMembership(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_DELETED_CATEGORIES
List1 = tempMap.Get("data")
PushIncomingHandler.DeleteCategories(List1)
Case PushIncomingHandler.NOTIFICATION_TYPE_DELETED_TAGS
List1 = tempMap.Get("data")
PushIncomingHandler.DeleteTags(List1)
Case PushIncomingHandler.NOTIFICATION_TYPE_DO_APPLICATION_UPDATE
Map1 = tempMap.Get("data")
Dim v As String = Map1.Get("version")
CallSubDelayed2(Updater, "AskUpdate", v)
Case PushIncomingHandler.NOTIFICATION_TYPE_EDITED_COMPANY
Map1 = tempMap.Get("data")
PushIncomingHandler.updateCompanyNaming(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_NEW_CATEGORY_ADDED
Map1 = tempMap.Get("data")
PushIncomingHandler.addNewCategory(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_NEW_COMPANY
Map1 = tempMap("data")
PushIncomingHandler.addNewCompany(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_NEW_SERVERS_INDEX
PushIncomingHandler.reloadServersIndex
Case PushIncomingHandler.NOTIFICATION_TYPE_NEW_TAGS_ADDED
List1 = tempMap.Get("data")
PushIncomingHandler.addNewTags(List1)
Case PushIncomingHandler.NOTIFICATION_TYPE_PUSHED_AD_FROM_COMPANY
Map1 = tempMap.Get("data")
CallSubDelayed2(AdViewer, "onAdFromCompanyArrival", Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_RELOAD_CATEGORY_TREE
PushIncomingHandler.reloadCategoriesTree
Case PushIncomingHandler.NOTIFICATION_TYPE_DELETED_COMPANIES
List1 = tempMap.Get("data")
PushIncomingHandler.DeleteCompanies(List1)
Case PushIncomingHandler.NOTIFICATION_TYPE_RELOAD_TAGS_INDEX
PushIncomingHandler.reloadTagsIndex
Case PushIncomingHandler.NOTIFICATION_TYPE_EDITED_LOCATION
Map1 = tempMap.Get("data")
PushIncomingHandler.updateLocationInfo(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_NEW_LOCATIONS_ADDED
List1 = tempMap.Get("data")
PushIncomingHandler.AddNewLocations(List1)
Case PushIncomingHandler.NOTIFICATION_TYPE_DELETED_LOCATIONS
List1 = tempMap.Get("data")
PushIncomingHandler.DeleteLocations(List1)
Case PushIncomingHandler.NOTIFICATION_TYPE_DELETED_ADS
List1 = tempMap.Get("data")
PushIncomingHandler.removeAdIDs(List1)
Case PushIncomingHandler.NOTIFICATION_TYPE_EDITED_AD
Map1 = tempMap.Get("data")
PushIncomingHandler.updateAd(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_NEW_AD_ADDED
Map1 = tempMap.Get("data")
PushIncomingHandler.AddNewAd(Map1)
' When a user removes a friend from his friend list -> a notification of type
' "NOTIFICATION_TYPE_UNFRIEND_CURRENT_USER_FROM_REMOTE_USER" is sent to the device of
' the removed user. The message should carry info on what list the recipient should
' be removed from
Case PushIncomingHandler.NOTIFICATION_TYPE_UNFRIEND_CURRENT_USER_FROM_REMOTE_USER
Map1 = tempMap.Get("data")
PushIncomingHandler.UnfriendCurrentUserFrom(Map1)
' When a user adds a friend from his friend list -> a notification of type
' "NOTIFICATION_TYPE_UNFRIEND_CURRENT_USER_FROM_REMOTE_USER" is sent to the device of
' the removed user. The message should carry info on what list the recipient should
' be added from
Case PushIncomingHandler.NOTIFICATION_TYPE_BEFRIEND_CURRENT_USER_WITH_REMOTE_USER
Map1 = tempMap.Get("data")
PushIncomingHandler.BefriendCurrentUserWith(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_ADD_TO_A_SHARED_LIST
Map1 = tempMap.Get("data")
PushIncomingHandler.receiveMessageForShoppingList(Map1)
Case PushIncomingHandler.NOTIFICATION_TYPE_REMOVE_FROM_A_SHARED_LIST
Map1 = tempMap.Get("data")
PushIncomingHandler.removeItemsFromUserFromShoppingList(Map1)
Case Else
If DEBUG Then
Utils.Log_("Unknown type of push notification received: "& TYPE_OF_NOTIFICATION)
End If
End Select
If DEBUG Then
Utils.Log_("Received silent push notification: " & m)
End If
' TODO: What do I need to call here for IOS to be happy ?
Else ' Not a silent notification
If DEBUG Then
Utils.Log_("Received a normal push notification: " & m)
End If
End If
End Sub
Private Sub JobDone(j As HttpJob)
If j.Success Then
If DEBUG Then
Utils.Log_("Token uploaded successfully.")
End If
Else
If DEBUG Then
Utils.Log_("Error uploading token")
End If
End If
j.Release
End Sub
#End Region
Private Sub Page1_Resize(Width As Int, Height As Int)
End Sub
Private Sub Application_Background
End Sub
My questions:
1. Is the "Application_PushToken" sub called *ONLY* when the device is first registered for PUSH NOTIFICATIONS (like the registration in GCM) - and is the event fired only once and only after calling
App.RegisterUserNotifications(True, True, True) and
App.RegisterForRemoteNotifications
?
2. At the line that has the comment "TODO: What do I need to call here for IOS to be happy ?":
What do I need to call for iOS to be happy ? What confuses me is what I've read here:
http://www.g8production.com/post/72656082173/ios7-multitasking-silent-notifications about
returning a UIBackgroundFetchResult ?
All my processing of push notifications should be completed within the 30 seconds of wall clock time given by Apple. It simply updates the local DB with the data in the push message
3. In the case where the user has not allowed push notifications, will the silent push notifications that I try to get working also be affected ? And if so, what is the alternative to using push notifications ?
4. How can I find out if the user disallows or allows push notifications ? Can I react to some kind of event or can I read the settings ?
5. Will "Application_RemoteNotification" sub be called regardless of wether or not my application is running/is in the foreground ?
6. Is this line:
#PlistExtra: <key>UIBackgroundModes</key><array><string>remote-notification</string></array>
enough to support silent push notifications ?
Sorry for a long post but I hope that the subject is of interest to others as well who are (like me) starting out on the journey of iOS development....
Thanks
/Henrik
Last edited: