如何永远在iOS中运行后台服务以同步数据 [英] How to run background service in ios forever for syncing of data

查看:54
本文介绍了如何永远在iOS中运行后台服务以同步数据的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发一个App,该App要求在Web服务器上执行同步操作(数据提交和检索).

Hi I am developing an App which has a requirement to do syncing operation (data submission and retrieval) on web server.

用户可以脱机提交表单(即,将数据存储到设备上的本地db).并且只要网络可用,后台服务应将这些数据提交到Web服务器.

User can submit forms offline (ie. storing data to local db on device). And whenever network is available, background service should submit those data to web server.

后台服务的详细要求如下:

The detail requirement of background service is like:

  • 后台服务将首先检查网络是否可用
  • 如果网络可用,它将在本地数据库(SQLite)中收集数据存储在设备上
  • 它将数据提交到服务器
  • 询问服务器是否有任何新数据,如果有,请获取该数据并更新设备上的本地数据库.

我对iOS和xamarin/monotouch还是很陌生,想知道如何实现?

I am quite new to iOS and xamarin/monotouch, and would like to know how to achieve this?

我了解iOS中的各种后台模式,例如后台获取,nsurlsession,后台传输等.

I know about various background modes in iOS, such as background fetch, nsurlsession, background transfer etc.

我已尝试实现我认为适合我的情况的Background Fetch.但它是在自己的时间上运行的.

I have try to implement Background Fetch which i think is suitable for my situation. but it runs on it's own time.

还想知道,如果用户杀死了我的应用程序,那么后台获取也会调用并仍然运行我的应用程序?

Also would like to know that if user has killed my application, then also background fetch will invoke and still run my application ?

在我的appdelegate-> PerformFetch方法中,代码是这样的:

the code is something like this in my appdelegate -> PerformFetch method:

if(networkService.IsNetworkAvailable())
{
   if(this.syncDataService.DownloadNewDataFromServer())
   {
       Console.WriteLine("Data downloaded successfully from server..");
   }
   if(this.syncDataService.UploadDataToServer())
   {
       Console.WriteLine("Data submitted successfully to server...");
   }
   completionHandler(UIBackgroundFetchResult.NewData);
}
else
{
   completionHandler(UIBackgroundFetchResult.NoData);
}

更新:最终,我以这种方式实现了它(希望它对某人有帮助):

Update: Finally I have implemented it like this way (hope it can be helpful for someone) :

public class LocationUpdatedEventArgs : EventArgs
{
    private CLLocation location;

    public LocationUpdatedEventArgs(CLLocation location)
    {
        this.location = location;
    }

    public CLLocation Location
    {
        get { return this.location; }
    }
}

public class LocationManager
    {
        private static DateTime lastServiceRun;

        private CLLocationManager locMgr;

        public LocationManager()
        {
            this.locMgr = new CLLocationManager();
            this.LocationUpdated += this.PrintLocation;
            this.locMgr.Failed += (object sender, NSErrorEventArgs e) =>
            {
                Console.WriteLine("didFailWithError " + e.Error);
                Console.WriteLine("didFailWithError coe " + e.Error.Code);
            };
        }


        public event EventHandler<LocationUpdatedEventArgs> LocationUpdated = delegate { };


        public static TimeSpan TimeDiff { get; set; }


        public CLLocationManager LocMgr
        {
            get
            {
                return this.locMgr;
            }
        }


        public void StartLocationUpdates()
        {

            if (CLLocationManager.LocationServicesEnabled)
            {
                // sets the accuracy that we want in meters
                this.LocMgr.DesiredAccuracy = 1;

                //// Location updates are handled differently pre-iOS 6. If we want to support older versions of iOS,
                //// we want to do perform this check and let our LocationManager know how to handle location updates.

                if (UIDevice.CurrentDevice.CheckSystemVersion(6, 0))
                {
                    this.LocMgr.LocationsUpdated += (object sender, CLLocationsUpdatedEventArgs e) =>
                    {
                        //// fire our custom Location Updated event
                        this.LocationUpdated(this, new LocationUpdatedEventArgs(e.Locations[e.Locations.Length - 1]));
                    };
                }
                else
                {
                    //// this won't be called on iOS 6 (deprecated). We will get a warning here when we build.
                    this.LocMgr.UpdatedLocation += (object sender, CLLocationUpdatedEventArgs e) =>
                    {
                        this.LocationUpdated(this, new LocationUpdatedEventArgs(e.NewLocation));
                    };
                }

                //// Start our location updates
                this.LocMgr.StartUpdatingLocation();

                lastServiceRun = DateTime.Now;

                // Get some output from our manager in case of failure
                this.LocMgr.Failed += (object sender, NSErrorEventArgs e) =>
                {
                    Console.WriteLine(e.Error);
                };
            }
            else
            {
                //// Let the user know that they need to enable LocationServices
                Console.WriteLine("Location services not enabled, please enable this in your Settings");
            }
        }

        /// <summary>
        /// The stop updating location.
        /// </summary>
        public void StopUpdatingLocation()
        {
            this.locMgr.StopUpdatingLocation();
        }

        /// <summary>
        /// The print location. (This will keep going in the background)
        /// </summary>
        /// <param name="sender"> The sender. </param>
        /// <param name="e"> Location updated event argument </param>
        public void PrintLocation(object sender, LocationUpdatedEventArgs e)
        {
            CLLocation location = e.Location;

            Console.WriteLine("Longitude: " + location.Coordinate.Longitude);
            Console.WriteLine("Latitude: " + location.Coordinate.Latitude);

            var diff = DateTime.Now - lastServiceRun;
            TimeDiff = diff;
            if (TimeDiff.Minutes == 2)
            {
        // RunInBackground() is my method which call the service to upload/download data from server
                if (this.RunInBackground())
                {
                    lastServiceRun = DateTime.Now;
                }
            }
        }
}

推荐答案

计时器永远不会在后台运行,并且您无法在此方法中添加其他线程. DidEnterBackground 用于完成待处理的任务.这通常会持续大约30秒-1分钟.

The timer never works in background, and you cannot add another thread in this method. DidEnterBackground is used to complete pending tasks. This will usually last for approximately 30secs - 1 minute.

您可以使用此方法添加循环或添加长时间运行的任务.

You can add a loop or add a long running task in this method.

这篇关于如何永远在iOS中运行后台服务以同步数据的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆