Conectar-se a serviços Web locais de emuladores do Android e simuladores do iOS

Browse sample. Procurar no exemplo

Muitos aplicativos móveis e de área de trabalho consomem serviços Web. Durante a fase de desenvolvimento de software, é comum implantar um serviço Web localmente e consumi-lo de um aplicativo em execução no emulador do Android ou simulador do iOS. Isso evita a necessidade de implantar o serviço Web em um ponto de extremidade hospedado e habilita uma experiência de depuração simples porque o aplicativo e o serviço Web estão sendo executados localmente.

Os aplicativos .NET Multi-Platform App UI (.NET MAUI) executados no Windows ou no MacCatalyst podem consumir serviços Web do ASP.NET Core executados localmente por HTTP ou HTTPS sem nenhum trabalho adicional, desde que você tenha confiança em seu certificado de desenvolvimento. No entanto, trabalho adicional é necessário quando o aplicativo está sendo executado no emulador Android ou simulador iOS, e o processo é diferente dependendo se o serviço Web está sendo executado sobre HTTP ou HTTPS.

Endereço do computador local

O emulador Android e o simulador iOS fornecem acesso aos serviços Web em execução por HTTP ou HTTPS em seu computador local. No entanto, o endereço do computador local é diferente para cada um deles.

Android

Cada instância do emulador do Android é isolada das interfaces de rede de seu computador de desenvolvimento e é executado atrás de um roteador virtual. Portanto, um dispositivo emulado não pode ver seu computador de desenvolvimento ou outras instâncias do emulador na rede.

No entanto, o roteador virtual para cada emulador gerencia um espaço de rede especial que inclui os endereços alocados previamente, sendo que o endereço 10.0.2.2 é um alias para a sua interface host de loopback (127.0.0.1 em seu computador de desenvolvimento). Portanto, considerando um serviço Web local que expõe uma operação GET por meio do URI relativo /api/todoitems/, o aplicativo em execução no emulador do Android pode consumir a operação enviando uma solicitação GET ao http://10.0.2.2:<port>/api/todoitems/ou https://10.0.2.2:<port>/api/todoitems/.

iOS

O simulador do iOS usa a rede do computador host. Portanto, os aplicativos em execução no simulador podem se conectar aos serviços Web em execução no computador local por meio do endereço IP dos computadores ou por meio do nome do host localhost. Por exemplo, considerando um serviço Web local que expõe uma operação GET por meio do URI relativo /api/todoitems/, o aplicativo em execução no simulador do iOS pode consumir a operação enviando uma solicitação GET ao http://localhost:<port>/api/todoitems/ou https://localhost:<port>/api/todoitems/.

Observação

Ao executar um aplicativo .NET MAUI no simulador do iOS do Windows, o aplicativo é exibido no simulador do iOS remoto para Windows. No entanto, o aplicativo está em execução no Mac emparelhado. Portanto, não há acesso localhost a um serviço Web em execução no Windows para um aplicativo iOS em execução em um Mac.

Serviços Web locais em execução via HTTP

Um aplicativo MAUI do .NET em execução no emulador do Android ou simulador do iOS pode consumir um serviço Web do ASP.NET Core em execução localmente por HTTP. Isso pode ser feito configurando seu projeto de aplicativo .NET MAUI e seu projeto de serviço Web ASP.NET Core para permitir tráfego HTTP de texto não criptografado.

No código que define a URL do serviço Web local no aplicativo .NET MAUI, verifique se a URL do serviço Web especifica o esquema HTTP e o nome de host correto. A classe DeviceInfo pode ser usada para detectar a plataforma em que o aplicativo está sendo executado. O nome de host correto pode então ser definido da seguinte maneira:

public static string BaseAddress =
    DeviceInfo.Platform == DevicePlatform.Android ? "http://10.0.2.2:5000" : "http://localhost:5000";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";

Para obter mais informações sobre a classe DeviceInfo, consulte Informações do dispositivo.

Além disso, para executar seu aplicativo no Android, você deve adicionar a configuração de segurança de rede necessária e, para executar seu aplicativo no iOS, você deve desativar o Apple Transport Security (ATS). Para obter mais informações, consulte Configuração de segurança de rede do Android e Configuração do ATS do iOS.

Você também deve garantir que seu serviço Web do ASP.NET Core esteja configurado para permitir tráfego HTTP. Isso pode ser obtido adicionando um perfil HTTP à profiles seção de launchSettings.json em seu projeto de serviço Web ASP.NET Core:

{
  ...
  "profiles": {
    "http": {
      "commandName": "Project",
      "dotnetRunMessages": true,
      "launchBrowser": true,
      "launchUrl": "api/todoitems",
      "applicationUrl": "http://localhost:5000",
      "environmentVariables": {
        "ASPNETCORE_ENVIRONMENT": "Development"
      }
    },
    ...
  }
}

Um aplicativo .NET Maui em execução no emulador do Android ou no simulador do iOS pode consumir um serviço Web do ASP.NET Core executado localmente por HTTP, desde que o serviço Web seja iniciado com o perfil http.

Configuração de segurança de rede do Android

Para habilitar o tráfego local de texto não criptografado no Android, você deve criar um arquivo de configuração de segurança de rede. Isso pode ser obtido adicionando um novo arquivo XML chamado network_security_config.xml à pasta Platforms\Android\Resources\xml em seu projeto de aplicativo .NET MAUI. O arquivo XML deve especificar a seguinte configuração:

<?xml version="1.0" encoding="utf-8"?>
<network-security-config>
  <domain-config cleartextTrafficPermitted="true">
    <domain includeSubdomains="true">10.0.2.2</domain>
  </domain-config>
</network-security-config>

Observação

Verifique se a ação de compilação do arquivo network_security_config.xml está definida como AndroidResource.

Em seguida, configure a propriedade networkSecurityConfig no nó do aplicativo no arquivo Platforms\Android\AndroidManifest.xml em seu projeto de aplicativo .NET MAUI:

<?xml version="1.0" encoding="utf-8"?>
<manifest>
    <application android:networkSecurityConfig="@xml/network_security_config" ...>
        ...
    </application>
</manifest>

Para obter mais informações sobre arquivos de configuração de segurança de rede, consulte Configuração de segurança de rede em developer.android.com.

Configuração do ATS do iOS

Para habilitar o tráfego local de texto não criptografado no iOS, você deve desativar o Apple Transport Security (ATS) em seu aplicativo .NET MAUI. Isso pode ser obtido adicionando a seguinte configuração ao arquivo Platforms\iOS\Info.plist em seu projeto de aplicativo .NET MAUI:

<key>NSAppTransportSecurity</key>    
<dict>
    <key>NSAllowsLocalNetworking</key>
    <true/>
</dict>

Para obter mais informações sobre o ATS, consulte Impedindo conexões de rede inseguras em developer.apple.com.

Serviços Web locais em execução via HTTPS

Um aplicativo MAUI do .NET em execução no emulador do Android ou simulador do iOS pode consumir um serviço Web do ASP.NET Core em execução localmente por HTTPS. O processo para habilitar isso é o feito da seguinte forma:

  1. Confie no certificado de desenvolvimento autoassinado em seu computador. Para obter mais informações, consulte Confiar em seu certificado de desenvolvimento.
  2. Especifique o endereço do computador local. Para saber mais, confira as informações sobre como especificar o endereço do computador local.
  3. Ignore a verificação de segurança do certificado de desenvolvimento local. Para saber mais, veja Ignorar a verificação de segurança do certificado.

Cada item será apresentado separadamente.

Confie no seu certificado de desenvolvimento

A instalação do SDK do .NET Core instala o certificado de desenvolvimento HTTPS do ASP.NET Core no repositório de certificados do usuário local. No entanto, embora o certificado tenha sido instalado, ele não é confiável. Para confiar no certificado, realize a única etapa a seguir para executar a ferramenta do dotnet dev-certs:

dotnet dev-certs https --trust

O comando a seguir fornece ajuda para a ferramenta dev-certs:

dotnet dev-certs https --help

Como alternativa, quando você executa um projeto do ASP.NET Core 2.1 (ou superior), que usa HTTPS, o Visual Studio detectará se o certificado de desenvolvimento está ausente e oferecerá a possibilidade de instalá-lo e de confiar nele.

Observação

O certificado de desenvolvimento HTTPS do ASP.NET Core é autoassinado.

Para saber mais sobre como habilitar o HTTPS local em seu computador, confira o artigo Habilitar o HTTPS local.

Especificar o endereço do computador local

No código que define a URL do serviço Web local no aplicativo .NET MAUI, verifique se a URL do serviço Web especifica o esquema HTTPS e o nome de host correto. A classe DeviceInfo pode ser usada para detectar a plataforma em que o aplicativo está sendo executado. O nome de host correto pode então ser definido da seguinte maneira:

public static string BaseAddress =
    DeviceInfo.Platform == DevicePlatform.Android ? "https://10.0.2.2:5001" : "https://localhost:5001";
public static string TodoItemsUrl = $"{BaseAddress}/api/todoitems/";

Para obter mais informações sobre a classe DeviceInfo, consulte Informações do dispositivo.

Ignorar a verificação de segurança do certificado

A tentativa de invocar um serviço Web seguro local de um aplicativo .NET MAUI em execução em um emulador Android resultará em um lançamento contínuo de java.security.cert.CertPathValidatorException, com uma mensagem indicando que a âncora de confiança para o caminho de certificação não foi encontrada. Da mesma forma, a tentativa de invocar um serviço Web seguro local de um aplicativo .NET MAUI em execução em um simulador iOS resultará em um erro NSURLErrorDomain com uma mensagem indicando que o certificado do servidor é inválido. Esses erros ocorrem porque o certificado de desenvolvimento HTTPS local é autoassinado, e os certificados autoassinados não são confiáveis pelo Android ou iOS. Portanto, é necessário ignorar erros de SSL quando um aplicativo consome um serviço Web seguro local.

Isso pode ser feito passando versões configuradas das classes nativas HttpMessageHandler para o construtor HttpClient, que instruem a classe HttpClient a confiar na comunicação localhost por HTTPS. A classe HttpMessageHandler é uma classe abstrata, cuja implementação no Android é fornecida pela classe AndroidMessageHandler, e cuja implementação no iOS é fornecida pela classe NSUrlSessionHandler.

O exemplo a seguir mostra uma classe que configura a classe AndroidMessageHandler no Android e a classe NSUrlSessionHandler no iOS para confiar na comunicação localhost por HTTPS:

public class HttpsClientHandlerService
{
    public HttpMessageHandler GetPlatformMessageHandler()
    {
#if ANDROID
        var handler = new Xamarin.Android.Net.AndroidMessageHandler();
        handler.ServerCertificateCustomValidationCallback = (message, cert, chain, errors) =>
        {
            if (cert != null && cert.Issuer.Equals("CN=localhost"))
                return true;
            return errors == System.Net.Security.SslPolicyErrors.None;
        };
        return handler;
#elif IOS
        var handler = new NSUrlSessionHandler
        {
            TrustOverrideForUrl = IsHttpsLocalhost
        };
        return handler;
#else
     throw new PlatformNotSupportedException("Only Android and iOS supported.");
#endif
    }

#if IOS
    public bool IsHttpsLocalhost(NSUrlSessionHandler sender, string url, Security.SecTrust trust)
    {
        if (url.StartsWith("https://localhost"))
            return true;
        return false;
    }
#endif
}

No Android, o método GetPlatformMessageHandler retorna um objeto AndroidMessageHandler. O método GetPlatformMessageHandler define a propriedade ServerCertificateCustomValidationCallback no objeto AndroidMessageHandler como um retorno de chamada que ignora o resultado da verificação de segurança do certificado para o certificado de desenvolvimento HTTPS local.

No iOS, o método GetPlatformMessageHandler retorna um objeto NSUrlSessionHandler que define sua propriedade TrustOverrideForUrl para um representante chamado IsHttpsLocalHost que corresponde à assinatura do representante NSUrlSessionHandler.NSUrlSessionHandlerTrustOverrideForUrlCallback. O representante IsHttpsLocalHost retorna true quando a URL começa com https://localhost.

O objeto resultante HttpClientHandler pode então ser passado como um argumento para o construtor HttpClient para compilações de depuração:

#if DEBUG
            HttpsClientHandlerService handler = new HttpsClientHandlerService();
            HttpClient client = new HttpClient(handler.GetPlatformMessageHandler());
#else
            client = new HttpClient();
#endif

Um aplicativo .NET MAUI em execução no emulador do Android ou simulador do iOS pode, então, consumir um serviço Web do ASP.NET Core em execução localmente por HTTPS.