Monotouch: WebRequest connection ends after disabling airplane mode on iPhone

The monotouch mono application periodically synchronizes the background with the web service. It works great and correctly determines the flight mode. When I turn off WiFi, it automatically starts using WWAN connection (GPRS, 3G). So far I am very pleased, but ... After disabling Airplan mode, there is no way to connect to my application when Wi-Fi is not available.

It correctly detects using the NetworkReachability object accessible by WWAN and that a connection is required. But the first timeout attempt (after 90 seconds, I cancel the start request using the timer). When I try again, I get a WebException "Error: ConnectionFailure (no route to the host)" as soon as I call EndGetRequestStream. The only way to connect again is to start another application, such as Mail, which creates the connection. After that, my application connects flawlessly again. Or wait a few minutes until the iPhone falls asleep. After waking up, the connection is configured ok again.

What am I doing wrong?

The code below runs using 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;
    }
+3
source share
1 answer

MonoTouch (ftp, smtp, http), , BSD. Apple , 3G/EDGE "" . - CFStream NSStream, API GPRS- BSD. , . MonoTouch API:

MonoTouch.ObjCRuntime.Runtime.StartWWAN (Uri uri);

api uri HTTP/HTTPs API WWAN , WWAN , .

+2

Source: https://habr.com/ru/post/1783372/


All Articles