0

I'm creating a geolocation app, and I wanted to start the startup automatically of a service that sent me coordinates every time.

Looking at the internet I read that technically it is not possible on ios, but there are some methods to overcome the problem.

I wanted to adopt the silent notification.

I implemented the method and when the app is in the backgorund everything works, but when I turn on the device and send a silent notification, the event: didReceiveRemoteNotification: does not trigger. or even when I close the app from the app switcher and then send a notification is not triggered.

I wanted to know if there is something wrong if you can do it.

ps: I'm using: didReceiveRemoteNotification: and no application: didReceiveRemoteNotification: fetchCompletionHandler: (can this be the problem?)

My Code in AppDelegate:

 public override async   void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action<UIBackgroundFetchResult> 
   completionHandler)
        {

             await Manager.SendPosition(completionHandler);
        }

in my FinishedLaunching:

if (Convert.ToInt16(UIDevice.CurrentDevice.SystemVersion.Split('.')[0].ToString()) < 8)
            {
                UIRemoteNotificationType notificationTypes = UIRemoteNotificationType.Alert | UIRemoteNotificationType.Badge | 
                UIRemoteNotificationType.Sound;
                UIApplication.SharedApplication.RegisterForRemoteNotificationTypes(notificationTypes);
            }
            else
            {
                UIUserNotificationType notificationTypes = UIUserNotificationType.Alert | UIUserNotificationType.Badge | UIUserNotificationType.Sound;
                var settings = UIUserNotificationSettings.GetSettingsForTypes(notificationTypes, new NSSet(new string[] { }));
                UIApplication.SharedApplication.RegisterUserNotificationSettings(settings);
                UIApplication.SharedApplication.RegisterForRemoteNotifications();
            }

and in my info.plist:

   <key>UIBackgroundModes</key>
      <array>
        <string>location</string>
        <string>remote-notification</string>
      </array>

UPDATE:

public async Task<bool> SendPosition(Action<UIBackgroundFetchResult> completionHandler = null)
        {
            StartLocationUpdates();
            var setting = ConnectDb()?.Table<Settings>().FirstOrDefault() ?? new Settings();
            _currentLong = 14.52538;
            _currentLat = 36.82842;
            if (_currentLong != 0 && _currentLat != 0)// && setting.TimeNotification != 0)
            {
                var objectSend = new
                {
                    unique_key = setting.UniqueKey, 
                    lat = _currentLat,
                    lng = _currentLong, 
                    idPlayerOneSignal = setting.IdPlayerOneSignal,
                    token = "" 
                };

                var client = new HttpClient { BaseAddress = new Uri("http://amywebservice.com/") };
                var data = JsonConvert.SerializeObject(objectSend);

                var content = new StringContent(data, Encoding.UTF8, "application/json");
                var response = await client.PostAsync("api/setPosition", content);
                if (response.IsSuccessStatusCode)
                {
                    var successResult = response.Content.ReadAsStringAsync().Result;
                    Debug.WriteLine("k", successResult);
                    if (completionHandler != null)
                    {
                        completionHandler(UIBackgroundFetchResult.NoData);
                    }
                    return true;
                }
                else
                {
                    var failureResulr = response.Content.ReadAsStringAsync().Result;
                    Debug.WriteLine("f", failureResulr);
                    if (completionHandler != null)
                    {
                        completionHandler(UIBackgroundFetchResult.NoData);
                    }
                    return false;
                }
            }
            return false;
        }

but not work, if I send a silent notification, I only run the first fly and only if the app is in the backgorund.

If I turn my phone on and notify notification will not work.

1 Answers1

0
  1. According to Xamarin documentation on DidReceiveRemoteNotification:

    [MonoTouch.Foundation.Export("application:didReceiveRemoteNotification:fetchCompletionHandler:")]

    DidReceiveRemoteNotification in Xamarin is the same as application:didReceiveRemoteNotification:fetchCompletionHandler: in native. So, the method is right.

  2. If you have force-quit the app, the silent notification will not launch your app unless you relaunch your app or restart the device. Here's the Related Apple documentation:

    In addition, if you enabled the remote notifications background mode, the system launches your app (or wakes it from the suspended state) and puts it in the background state when a remote notification arrives. However, the system does not automatically launch your app if the user has force-quit it. In that situation, the user must relaunch your app or restart the device before the system attempts to launch your app automatically again.

  3. I'm not very clear on your description about turn on the device(unlock your device without open the app? or other.) here:

    but when I turn on the device and send a silent notification

    But according to the application(_:didReceiveRemoteNotification:fetchCompletionHandler:)

    As soon as you finish processing the notification, you must call the block in the handler parameter or your app will be terminated. Your app has up to 30 seconds of wall-clock time to process the notification and call the specified completion handler block. In practice, you should call the handler block as soon as you are done processing the notification. The system tracks the elapsed time, power usage, and data costs for your app’s background downloads. Apps that use significant amounts of power when processing push notifications may not always be woken up early to process future notifications.

    You have to implement the completionHandler when you are done processing the notification.

    Add completionHandler() in DidReceiveRemoteNotification at the corresponding places, such as the if statement:

    • completionHandler(UIBackgroundFetchResult.NewData) when you get what you want.
    • completionHandler(UIBackgroundFetchResult.Failed) when there's any problem with fetching data.
    • completionHandler(UIBackgroundFetchResult.NoData) when there's no data.

    It looks like it is missed in your code, which may affect the silent notification.

Kevin Li
  • 2,258
  • 1
  • 9
  • 18
  • thanks for the clarification, but now with the code I posted on, if I turn off the phone and restart it and send a silent notification, I can not awaken my app. It may be for the completionHandler how do I follow the operation completionHandler? – Bruno Mandarà Sep 27 '17 at 21:02
  • similar a this: `public override async void DidReceiveRemoteNotification(UIApplication application, NSDictionary userInfo, Action completionHandler) { completionHandler(UIBackgroundFetchResult.NoData); await Manager.SendPosition(); }` ??? – Bruno Mandarà Sep 28 '17 at 10:53
  • @BrunoMandarà, execute the `completionHandler` when you finish to send the position, such as in the finished callback of the `SendPosition()` method. – Kevin Li Sep 29 '17 at 06:33