你好,我正在开发一个应用程序,需要在Web服务器上执行同步操作(数据提交和检索)。
用户可以离线提交表单(即将数据存储到设备上的本地数据库)。每当有网络连接时,后台服务应该将这些数据提交到Web服务器。
后台服务的详细要求如下:
- 后台服务将首先检查网络是否可用
- 如果网络可用,它将收集存储在设备上的本地数据库(SQLite)中的数据
- 它将提交数据到服务器
- 请求服务器是否有任何新数据,如果有,则获取该数据并更新设备上的本地数据库。
我对iOS和xamarin/monotouch还比较陌生,想知道如何实现这个功能?
我知道iOS有各种后台模式,例如后台获取、nsurlsession、后台传输等。
我尝试实现后台获取,我认为它适合我的情况。但是它运行在自己的时间。
另外,如果用户关闭了我的应用程序,后台获取是否仍会被调用并继续运行我的应用程序?
代码在我的appdelegate中类似于 PerformFetch 方法:
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);
}
更新:最终我按照以下方式实现了它(希望对某些人有所帮助):
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;
}
}
}
}