c# - 一段时间后,在后台(iOS和Android)上传数据以一种奇怪的方式失败
问题描述
我正在努力改进我们用于划船社区的应用程序。其中一部分是网站上的地图,其中包含来自 Boats 的最新位置。到目前为止一切正常,但我想添加一个连续的背景跟踪作为应用程序功能。
该应用程序可以运行一段时间,但由于超时而无法上传。这些并非来自 API 限制,在我看来,该应用程序似乎无法再访问网络了。
我依赖https://github.com/jamesmontemagno/GeolocatorPlugin获取所有位置信息。该插件还在Android 上使用https://github.com/jamesmontemagno/CurrentActivityPlugin/ 。
所以,这就是我从手机收到位置更新后要做的事情。
事件处理程序设置:
[...]
TimeSpan span = new TimeSpan(0, 20, 0); // Prod: 0, 30, 0
double distance = 500; // Prod: 2700
bool includeHeading = false; //don't alert on heading changes
ListenerSettings listenerSettings = new ListenerSettings
{
AllowBackgroundUpdates = true,
DeferralDistanceMeters = distance, // adjustable in app 2-10 nautical Miles
DeferLocationUpdates = true,
DeferralTime = span, // adjustable in app 15-120 Minutes
ListenForSignificantChanges = false,
PauseLocationUpdatesAutomatically = false,
ActivityType = ActivityType.OtherNavigation
};
var success = await CrossGeolocator.Current.StartListeningAsync(span,distance,includeHeading,listenerSettings);
if (success)
{
CrossGeolocator.Current.PositionChanged += async (s, e) =>
{
Console.WriteLine("\n\n -_-_-_-_-_ Position Event -_-_-_-_-_-_ \n\n");
Trackpoint trackpoint = new Trackpoint(e.Position);
Trackpoint point = await Tracking(trackpoint);
};
}
[...]
事件处理程序调用:(在应用程序开发路线图的下方会发生更多事情)
public async Task<Trackpoint> Tracking(Trackpoint trackpoint = null)
{
return await tracker.LogPoint(trackpoint);
}
在tracker.LogPoint(trackpoint)
来自 Hevent Handler 的坐标被添加到列表中(应该是空的,但可能会保存以前的 Trackpoints,以防上传失败。)
public async Task<Trackpoint> LogPoint(Trackpoint location = null)
{
if (location == null)
{
location = await GetCoordinates(); // Call GPS if no Trackpoint is given when Tracking is done fully manual
}
if (location != null)
{
Console.WriteLine("Trackpoint Queue was: {0}", track.Count);
track.Add(location); // Add current location to end of the list (defined as private in the class)
int trackpointQueue = track.Count;
int uploadedTrackpoints = 0;
Console.WriteLine("Trackpoint Queue now: {0}", trackpointQueue);
foreach (var position in track)
{
Console.WriteLine("Uploading Trackpoint: {0} | {1} | {2}", position.Timestamp, position.Latitude, position.Longitude);
if (App.api.UploadTrackPoint(track[track.Count - 1])) // upload first trackpoint in List (ideally current) and remove it from List, repeat with more items in queue.
{
uploadedTrackpoints++;
}
else
{
Console.WriteLine("Error uploading Trackpoint trying again next time");
// Because uploading attempt failed, we don't want to try again now leave the loop until next call.
break;
}
}
track.RemoveRange(0, uploadedTrackpoints); // remove all uploaded Trackpoints from Queue
}
return location;
}
上传是作为 multipart/formdata 到现有 API 的。在 4-10 个事件之后,所有进一步的上传都失败,因为发生网络超时而引发 Exeption。将应用程序带回前台,它几乎没有响应。
public bool UploadTrackPoint(Trackpoint location)
{
bool success = false;
if (CanUseData())
{
string posturl = settings.BlogURL + "(THE API URL)" + "(THE API KEY)";
string agent = "User-Agent: (MY APP NAME)/" + settings.Version + " (" + DeviceInfo.Platform + ", " + DeviceInfo.VersionString + ")";
Console.WriteLine("Uploading: {0} ", Trackpoint.ConvertToString(location));
try
{
var response = MessageUpload.MultipartFormDataPost(false, posturl, agent, location.Pairs);
Console.WriteLine("HTTP response StatusCode: " + response.StatusCode + "\n Content: " + response.ResponseUri);
if (response.StatusCode == System.Net.HttpStatusCode.OK) success = true;
}
catch (Exception ex)
{
Console.WriteLine("FAILED!!! \n\n({0})\n\n", ex);
}
}
return success;
}
完全相同的行为发生在 iOS(物理 iPhone 6)和 iOS 模拟器以及 Android 模拟器中。但是,我阅读了很多关于 iOS 和最近的 Android API 的背景限制,但我怀疑这是这里的问题,因为它在两个平台上都是一致的。所以我假设我在这里做错了什么,在撞墙之前填充了一些缓冲。但是,该应用程序没有被任何操作系统终止,而-_-_-_-_-_ Position Event -_-_-_-_-_-_
在上传开始失败并且积压工作增加后,我可以在控制台上看到一些。最终,在发生一些超时之后,甚至位置更新也会停止。
你会从哪里开始进一步的调试?
解决方案
以防万一有人偶然发现这一点。除了@SushiHangover 提到的缺少背景服务之外,更大的问题是 WebResponse 的处理不正确。
事实证明,撞到某种墙的直觉就在这里:在我的 Http 调用完成后,只读取标题并且从不处理响应对象,应用程序保持所有连接打开。在精确 10 之后(在 iOS 上),应用程序无法打开新连接,导致超时。
推荐阅读
- javascript - jQuery:使用触摸屏设备时防止单击滚动
- css - CSS 表格 - 表格的第一个 td 元素的不同颜色,条纹
- java - Hibernate - 一次保存映射三个表
- chef-infra - 有没有办法使用环境变量设置厨师属性?
- shell - 如何使用选项卡将输出终端写入shell中的文件?
- react-native - React-native:页面导航代码返回错误
- r - 从具有更改名称的列中计算行最大值
- python-3.x - 使用 beautifulsoup 难以访问表数据
- python - 优化嵌套 for 循环
- javascript - 使用模板文字检查两个条件