我的monotouch应用程序正在与Web服务进行定期后台同步。它运行完美,可以正确检测飞行模式。当我关闭WiFi时,它会自动开始使用WWAN(GPRS,3G)连接。到目前为止,我非常满意,但是...关闭Airplan模式后,当没有WiFi可用时,我的应用程序无法重新连接。
使用WWAN可用的NetworkReachability对象正确检测并且需要连接。但是第一次尝试超时(90秒后我使用计时器中止运行请求)。当我再次尝试时,一旦调用EndGetRequestStream,我就会收到WebException“错误:ConnectionFailure(无主机路由)”。再次连接的唯一方法是启动另一个应用程序,如Mail,它建立连接。之后,我的应用程序再次完美连接。或等待几分钟直到iPhone进入睡眠状态。唤醒后,连接再次设置好。
我做错了什么?
以下代码使用ThreadPool.QueueUserWorkItem(CreateRequest)启动;
/// <summary>
/// Sync step 1: Create the request and start asynchronously sending the data.
/// </summary>
private void CreateRequest(object state)
{
try
{
Console.WriteLine("Phase 1 started...");
if (!IsNetworkAvailable())
{
Ready(SyncState.NoConnection);
return;
}
UIApplication.SharedApplication.NetworkActivityIndicatorVisible = true;
_request = (HttpWebRequest)WebRequest.Create(SyncUrl);
_request.Method = HttpMethodPost;
_request.ContentType = HttpContentTypeJson;
Console.WriteLine("Phase 2 is starting...");
_request.BeginGetRequestStream(new AsyncCallback(StartRequest), null);
}
catch (WebException e)
{
Console.WriteLine("WebException: " + e.Message + "\r\nStatus: " + e.Status);
Ready(SyncState.ConnectionError);
}
}
/// <summary>
/// Sync step 2: Read syncdata from database and send to server.
/// Start getting the response asynchronously.
/// </summary>
private void StartRequest(IAsyncResult asyncResult)
{
Console.WriteLine("Phase 2 started...");
try
{
using (var stream = _request.EndGetRequestStream(asyncResult))
{
using (var textStream = new StreamWriter(stream))
{
Database.Instance.CreateSyncData().Save(textStream);
}
}
Console.WriteLine("Phase 3 is starting...");
_request.BeginGetResponse(new AsyncCallback(ProcessResponse), null);
}
catch (WebException e)
{
Console.WriteLine("WebException: " + e.Message + "\r\nStatus: " + e.Status);
Ready(SyncState.ConnectionError);
}
}
/// <summary>
/// Sync step 3: Get the response and process.
/// </summary>
private void ProcessResponse(IAsyncResult asyncResult)
{
Console.WriteLine("Phase 3 started...");
try
{
using (HttpWebResponse response = (HttpWebResponse)_request.EndGetResponse(asyncResult))
{
using (var textStream = new StreamReader(response.GetResponseStream()))
{
var data = (JsonObject)JsonObject.Load(textStream);
Database.Instance.ProcessSyncReply(data);
Console.WriteLine("Success: " + data.ToString());
LastSyncTime = DateTime.Now;
Ready(SyncState.Synchronized);
}
}
}
catch (WebException e)
{
Console.WriteLine("WebException: " + e.Message + "\r\nStatus: " + e.Status);
Ready(SyncState.ConnectionError);
}
}
private bool IsNetworkAvailable(out bool connectionRequired, out bool onlyWWAN)
{
bool flagsAvailable;
NetworkReachabilityFlags networkReachabilityFlags = (NetworkReachabilityFlags)0;
using (var networkReachability = new NetworkReachability(HostName))
{
flagsAvailable = networkReachability.TryGetFlags(out networkReachabilityFlags);
}
connectionRequired = 0 != (networkReachabilityFlags & NetworkReachabilityFlags.ConnectionRequired);
onlyWWAN = 0 != (networkReachabilityFlags & NetworkReachabilityFlags.IsWWAN);
return flagsAvailable && 0 != (networkReachabilityFlags & NetworkReachabilityFlags.Reachable);
}
private bool IsNetworkAvailable()
{
bool connectionRequired;
bool onlyWWAN;
bool available = IsNetworkAvailable(out connectionRequired, out onlyWWAN);
string status = "Network status: ";
if (!available)
status += "Not available";
else
{
status += "Available; ";
if (onlyWWAN)
status += "Mobile; ";
if (connectionRequired)
status += "Connection required";
}
Console.WriteLine(status);
return available;
}
答案 0 :(得分:2)
处理网络事务的MonoTouch高级对象(ftp,smtp,http)使用BSD套接字。 Apple有一种机制,即使3G / EDGE连接“活着”,它实际上也会进入睡眠状态。唤醒这一点的唯一方法是使用CFStream或NSStream资源,没有公开暴露的API来唤醒BSD套接字的GPRS连接。谢天谢地,你可以解决这个问题。 MonoTouch提供了一个API:
MonoTouch.ObjCRuntime.Runtime.StartWWAN (Uri uri);
此api仅接受HTTP / HTTPs uri,并将快速连接到指定的API,以便为所有连接重新唤醒WWAN,此时WWAN将保持活动状态,直到空中计划或超时为止。