Xamarin.Forms Webview
WebView
는 앱에 웹 및 HTML 콘텐츠를 표시하기 위한 보기입니다.
콘텐츠
WebView
에서는 다음과 같은 유형의 콘텐츠를 지원합니다.
- HTML 및 CSS 웹 사이트 – WebView는 JavaScript 지원을 포함하여 HTML 및 CSS를 사용하여 작성된 웹 사이트에 대한 모든 지원을 제공합니다.
- 문서 – WebView는 각 플랫폼에서 네이티브 구성 요소를 사용하여 구현되므로 WebView는 기본 플랫폼에서 지원하는 형식으로 문서를 표시할 수 있습니다.
- HTML 문자열 – WebView는 메모리의 HTML 문자열을 표시할 수 있습니다.
- 로컬 파일 – WebView는 위에 포함된 콘텐츠 형식을 앱에 표시할 수 있습니다.
참고 항목
WebView
Windows에서는 해당 플랫폼에서 Internet Explorer에서 지원하는 경우에도 Silverlight, Flash 또는 ActiveX 컨트롤을 지원하지 않습니다.
웹 사이트
인터넷에서 웹 사이트를 표시하려면 's Source
속성을 문자열 URL로 설정합니다WebView
.
var browser = new WebView
{
Source = "https://dotnet.microsoft.com/apps/xamarin"
};
참고 항목
URL은 지정된 프로토콜을 사용하여 완전히 구성되어야 합니다(즉, 앞에 "http://" 또는 "https://"이 있어야 함).
iOS 및 ATS
버전 9부터 iOS는 애플리케이션이 기본적으로 모범 사례 보안을 구현하는 서버와만 통신할 수 있도록 허용합니다. 안전하지 않은 서버와의 통신을 사용하려면 값을 설정 Info.plist
해야 합니다.
참고 항목
애플리케이션에 보안되지 않은 웹 사이트에 대한 연결이 필요한 경우 ATS를 완전히 사용하지 NSAllowsArbitraryLoads
않도록 설정하는 대신 항상 do기본를 예외 NSExceptionDomains
로 입력해야 합니다. NSAllowsArbitraryLoads
은 극한의 응급 상황에서만 사용해야 합니다.
다음은 특정 작업기본(이 경우 xamarin.com)을 사용하여 ATS 요구 사항을 우회하는 방법을 보여 줍니다.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSExceptionDomains</key>
<dict>
<key>xamarin.com</key>
<dict>
<key>NSIncludesSubdomains</key>
<true/>
<key>NSTemporaryExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSTemporaryExceptionMinimumTLSVersion</key>
<string>TLSv1.1</string>
</dict>
</dict>
</dict>
...
</key>
일부 do기본s가 ATS를 우회하도록 설정하는 것이 가장 좋습니다. 신뢰할 수 있는 사이트를 사용하는 동시에 신뢰할 수 없는 do기본s에 대한 추가 보안을 활용할 수 있습니다. 다음은 앱에 대한 ATS를 사용하지 않도록 설정하는 덜 안전한 방법을 보여 줍니다.
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads </key>
<true/>
</dict>
...
</key>
iOS 9의 이 새로운 기능에 대한 자세한 내용은 앱 전송 보안을 참조하세요.
HTML 문자열
코드에 동적으로 정의된 HTML 문자열을 표시하려면 다음의 인스턴스 HtmlWebViewSource
를 만들어야 합니다.
var browser = new WebView();
var htmlSource = new HtmlWebViewSource();
htmlSource.Html = @"<html><body>
<h1>Xamarin.Forms</h1>
<p>Welcome to WebView.</p>
</body></html>";
browser.Source = htmlSource;
위의 코드 @
에서 HTML을 축자 문자열 리터럴로 표시하는 데 사용됩니다. 즉, 대부분의 이스케이프 문자는 무시됩니다.
참고 항목
자식인 레이아웃에 WidthRequest
따라 HTML 콘텐츠를 보려면 해당 콘텐츠의 WebView
속성과 HeightRequest
속성을 설정해야 할 수 WebView
있습니다. 예를 들어 .StackLayout
로컬 HTML 콘텐츠
WebView는 앱에 포함된 HTML, CSS 및 JavaScript의 콘텐츠를 표시할 수 있습니다. 예시:
<html>
<head>
<title>Xamarin Forms</title>
</head>
<body>
<h1>Xamarin.Forms</h1>
<p>This is an iOS web page.</p>
<img src="XamarinLogo.png" />
</body>
</html>
Css:
html,body {
margin:0;
padding:10;
}
body,p,h1 {
font-family: Chalkduster;
}
위의 CSS에 지정된 글꼴은 모든 플랫폼에 동일한 글꼴이 없으므로 각 플랫폼에 대해 사용자 지정해야 합니다.
를 사용하여 WebView
로컬 콘텐츠를 표시하려면 HTML 파일을 다른 파일과 마찬가지로 연 다음 콘텐츠를 문자열 Html
로 로드해야 합니다 HtmlWebViewSource
. 파일 열기에 대한 자세한 내용은 파일 작업을 참조 하세요.
다음 스크린샷은 각 플랫폼에 로컬 콘텐츠를 표시한 결과를 보여 줍니다.
첫 번째 페이지가 로드되었지만 HTML이 WebView
어디에서 왔는지에 대한 지식이 없습니다. 로컬 리소스를 참조하는 페이지를 처리할 때 문제가 됩니다. 이러한 경우의 예로는 로컬 페이지가 서로 연결되거나, 페이지가 별도의 JavaScript 파일을 사용하거나, CSS 스타일시트에 대한 페이지 링크가 포함됩니다.
이 문제를 해결하려면 파일 시스템의 파일을 찾을 위치를 알려 WebView
야 합니다. 에서 사용하는 속성을 HtmlWebViewSource
설정 BaseUrl
하여 이 작업을 수행합니다WebView
.
각 운영 체제의 파일 시스템이 다르기 때문에 각 플랫폼에서 해당 URL을 결정해야 합니다. Xamarin.Forms 는 각 플랫폼의 DependencyService
런타임에 종속성을 확인하기 위한 기능을 노출합니다.
사용 DependencyService
하려면 먼저 각 플랫폼에서 구현할 수 있는 인터페이스를 정의합니다.
public interface IBaseUrl { string Get(); }
각 플랫폼에서 인터페이스가 구현될 때까지 앱이 실행되지 않습니다. 공통 프로젝트에서 다음을 사용하여 DependencyService
설정 BaseUrl
해야 합니다.
var source = new HtmlWebViewSource();
source.BaseUrl = DependencyService.Get<IBaseUrl>().Get();
그런 다음 각 플랫폼에 대한 인터페이스 구현을 제공해야 합니다.
iOS
iOS에서 웹 콘텐츠는 아래와 같이 빌드 작업 BundleResource가 있는 프로젝트의 루트 디렉터리 또는 Resources 디렉터리에 있어야 합니다.
기본 BaseUrl
번들의 경로로 설정해야 합니다.
[assembly: Dependency (typeof (BaseUrl_iOS))]
namespace WorkingWithWebview.iOS
{
public class BaseUrl_iOS : IBaseUrl
{
public string Get()
{
return NSBundle.MainBundle.BundlePath;
}
}
}
Android
Android에서 아래와 같이 빌드 작업 AndroidAsset 를 사용하여 자산 폴더에 HTML, CSS 및 이미지를 배치합니다.
Android에서는 다음 BaseUrl
으로 "file:///android_asset/"
설정해야 합니다.
[assembly: Dependency (typeof(BaseUrl_Android))]
namespace WorkingWithWebview.Android
{
public class BaseUrl_Android : IBaseUrl
{
public string Get()
{
return "file:///android_asset/";
}
}
}
Android에서 Assets 폴더의 파일은 속성에 의해 MainActivity.Instance
노출되는 현재 Android 컨텍스트를 통해 액세스할 수도 있습니다.
var assetManager = MainActivity.Instance.Assets;
using (var streamReader = new StreamReader (assetManager.Open ("local.html")))
{
var html = streamReader.ReadToEnd ();
}
유니버설 Windows 플랫폼
UWP(유니버설 Windows 플랫폼) 프로젝트에서 빌드 작업이 Content로 설정된 프로젝트 루트에 HTML, CSS 및 이미지를 배치합니다.
다음 BaseUrl
으로 "ms-appx-web:///"
설정해야 합니다.
[assembly: Dependency(typeof(BaseUrl))]
namespace WorkingWithWebview.UWP
{
public class BaseUrl : IBaseUrl
{
public string Get()
{
return "ms-appx-web:///";
}
}
}
탐색
WebView는 사용할 수 있는 여러 메서드 및 속성을 탐색할 수 있도록 지원합니다.
- GoForward() – true이면
CanGoForward
호출GoForward
이 다음 방문 페이지로 이동합니다. - GoBack() – true이면
CanGoBack
통화GoBack
가 마지막으로 방문한 페이지로 이동합니다. - CanGoBack –
true
브라우저가 시작 URL에 있는 경우 다시 탐색할false
페이지가 있는 경우 - CanGoForward –
true
사용자가 뒤로 이동한 후 이미 방문한 페이지로 이동할 수 있는 경우
페이지 내에서는 WebView
멀티 터치 제스처를 지원하지 않습니다. 콘텐츠가 모바일에 최적화되어 있고 확대/축소 없이 표시되는지 확인하는 것이 중요합니다.
애플리케이션은 디바이스의 브라우저가 아닌 링크를 WebView
표시하는 것이 일반적입니다. 이러한 상황에서는 일반 탐색을 허용하는 것이 유용하지만 사용자가 시작 링크에 있는 동안 다시 적어지면 앱이 일반 앱 보기로 돌아가야 합니다.
기본 제공 탐색 메서드 및 속성을 사용하여 이 시나리오를 사용하도록 설정합니다.
브라우저 보기에 대한 페이지를 만들어 시작합니다.
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebViewSample.InAppBrowserXaml"
Title="Browser">
<StackLayout Margin="20">
<StackLayout Orientation="Horizontal">
<Button Text="Back" HorizontalOptions="StartAndExpand" Clicked="OnBackButtonClicked" />
<Button Text="Forward" HorizontalOptions="EndAndExpand" Clicked="OnForwardButtonClicked" />
</StackLayout>
<!-- WebView needs to be given height and width request within layouts to render. -->
<WebView x:Name="webView" WidthRequest="1000" HeightRequest="1000" />
</StackLayout>
</ContentPage>
코드 숨김에서:
public partial class InAppBrowserXaml : ContentPage
{
public InAppBrowserXaml(string URL)
{
InitializeComponent();
webView.Source = URL;
}
async void OnBackButtonClicked(object sender, EventArgs e)
{
if (webView.CanGoBack)
{
webView.GoBack();
}
else
{
await Navigation.PopAsync();
}
}
void OnForwardButtonClicked(object sender, EventArgs e)
{
if (webView.CanGoForward)
{
webView.GoForward();
}
}
}
정말 간단하죠.
이벤트
WebView는 상태 변경에 응답하는 데 도움이 되는 다음 이벤트를 발생합니다.
Navigating
– WebView가 새 페이지 로드를 시작할 때 발생하는 이벤트입니다.Navigated
– 페이지가 로드되고 탐색이 중지될 때 발생하는 이벤트입니다.ReloadRequested
– 현재 콘텐츠를 다시 로드하라는 요청이 있을 때 발생하는 이벤트입니다.
WebNavigatingEventArgs
이벤트와 함께 Navigating
제공되는 개체에는 다음과 같은 네 가지 속성이 있습니다.
Cancel
– 탐색을 취소할지 여부를 나타냅니다.NavigationEvent
– 발생한 탐색 이벤트입니다.Source
– 탐색을 수행한 요소입니다.Url
– 탐색 대상입니다.
WebNavigatedEventArgs
이벤트와 함께 Navigated
제공되는 개체에는 다음과 같은 네 가지 속성이 있습니다.
NavigationEvent
– 발생한 탐색 이벤트입니다.Result
– 열거형 멤버를 사용하여WebNavigationResult
탐색 결과를 설명합니다. 유효한 값은Cancel
,Failure
,Success
및Timeout
입니다.Source
– 탐색을 수행한 요소입니다.Url
– 탐색 대상입니다.
로드하는 데 시간이 오래 걸리는 웹 페이지를 사용할 것으로 예상되는 경우 이벤트 및 Navigated
이벤트를 사용하여 Navigating
상태 표시기를 구현하는 것이 좋습니다. 예시:
<ContentPage xmlns="http://xamarin.com/schemas/2014/forms"
xmlns:x="http://schemas.microsoft.com/winfx/2009/xaml"
x:Class="WebViewSample.LoadingLabelXaml"
Title="Loading Demo">
<StackLayout>
<!--Loading label should not render by default.-->
<Label x:Name="labelLoading" Text="Loading..." IsVisible="false" />
<WebView HeightRequest="1000" WidthRequest="1000" Source="https://dotnet.microsoft.com/apps/xamarin" Navigated="webviewNavigated" Navigating="webviewNavigating" />
</StackLayout>
</ContentPage>
두 이벤트 처리기:
void webviewNavigating(object sender, WebNavigatingEventArgs e)
{
labelLoading.IsVisible = true;
}
void webviewNavigated(object sender, WebNavigatedEventArgs e)
{
labelLoading.IsVisible = false;
}
그러면 다음과 같은 출력(로드)이 발생합니다.
로드 완료:
콘텐츠 다시 로드
WebView
에는 Reload
현재 콘텐츠를 다시 로드하는 데 사용할 수 있는 메서드가 있습니다.
var webView = new WebView();
...
webView.Reload();
메서드가 Reload
호출되면 ReloadRequested
현재 콘텐츠를 다시 로드하기 위한 요청이 발생했음을 나타내는 이벤트가 발생합니다.
성능
인기 있는 웹 브라우저는 하드웨어 가속 렌더링 및 JavaScript 컴파일과 같은 기술을 채택합니다. Xamarin.Forms 4.4 이전에는 클래스에 Xamarin.FormsWebView
의해 UIWebView
iOS에서 구현되었습니다. 그러나 이러한 기술 중 상당수는 이 구현에서 사용할 수 없었습니다. 따라서 4.4WebView
Xamarin.Forms부터 Xamarin.Forms 더 빠른 검색을 지원하는 클래스에 WkWebView
의해 iOS에서 구현됩니다.
참고 항목
iOS에서 WkWebViewRenderer
인수를 허용하는 생성자 오버로드가 WkWebViewConfiguration
있습니다. 이렇게 하면 렌더러를 만들 때 구성할 수 있습니다.
애플리케이션은 호환성을 위해 iOS UIWebView
클래스를 Xamarin.FormsWebView
사용하여 구현으로 돌아갈 수 있습니다. 애플리케이션에 대한 iOS 플랫폼 프로젝트의 AssemblyInfo.cs 파일에 다음 코드를 추가하여 이 작업을 수행할 수 있습니다.
// Opt-in to using UIWebView instead of WkWebView.
[assembly: ExportRenderer(typeof(Xamarin.Forms.WebView), typeof(Xamarin.Forms.Platform.iOS.WebViewRenderer))]
참고 항목
5.0에서는 Xamarin.Forms 클래스가 WebViewRenderer
제거되었습니다. 따라서 Xamarin.Forms 5.0은 컨트롤에 대한 참조를 UIWebView
포함하지 않습니다.
WebView
기본적으로 Android의 경우 기본 제공 브라우저만큼 빠릅니다.
UWP WebView는 Microsoft Edge 렌더링 엔진을 사용합니다. 데스크톱 및 태블릿 디바이스는 Edge 브라우저 자체를 사용하는 것과 동일한 성능을 확인해야 합니다.
사용 권한
WebView
작동하려면 각 플랫폼에 대해 사용 권한이 설정되어 있는지 확인해야 합니다. 일부 플랫폼에서는 WebView
디버그 모드에서 작동하지만 릴리스용으로 빌드할 때는 작동하지 않습니다. 디버그 모드에서 Android의 인터넷 액세스와 같은 일부 사용 권한은 기본적으로 Mac용 Visual Studio 설정되기 때문입니다.
- UWP – 네트워크 콘텐츠를 표시할 때 인터넷(클라이언트 및 서버) 기능이 필요합니다.
- Android – 네트워크에서 콘텐츠를 표시할 때만 필요합니다
INTERNET
. 로컬 콘텐츠에는 특별한 권한이 필요하지 않습니다. - iOS – 특별한 권한이 필요하지 않습니다.
레이아웃
대부분의 다른 Xamarin.Forms 뷰 WebView
와 달리 StackLayout 또는 RelativeLayout에 포함할 때 이를 요구 HeightRequest
하며 WidthRequest
지정됩니다. 이러한 속성을 WebView
지정하지 않으면 렌더링되지 않습니다.
다음 예제에서는 작동, 렌더링을 초래하는 레이아웃을 WebView
보여 줍니다.
WidthRequest 및 HeightRequest를 사용하여 StackLayout:
<StackLayout>
<Label Text="test" />
<WebView Source="https://dotnet.microsoft.com/apps/xamarin"
HeightRequest="1000"
WidthRequest="1000" />
</StackLayout>
WidthRequest 및 HeightRequest를 사용하여 RelativeLayout:
<RelativeLayout>
<Label Text="test"
RelativeLayout.XConstraint= "{ConstraintExpression
Type=Constant, Constant=10}"
RelativeLayout.YConstraint= "{ConstraintExpression
Type=Constant, Constant=20}" />
<WebView Source="https://dotnet.microsoft.com/apps/xamarin"
RelativeLayout.XConstraint="{ConstraintExpression Type=Constant,
Constant=10}"
RelativeLayout.YConstraint="{ConstraintExpression Type=Constant,
Constant=50}"
WidthRequest="1000" HeightRequest="1000" />
</RelativeLayout>
WidthRequest 및 HeightRequest가 없는 AbsoluteLayout:
<AbsoluteLayout>
<Label Text="test" AbsoluteLayout.LayoutBounds="0,0,100,100" />
<WebView Source="https://dotnet.microsoft.com/apps/xamarin"
AbsoluteLayout.LayoutBounds="0,150,500,500" />
</AbsoluteLayout>
WidthRequest 및 HeightRequest가 없는 그리드입니다. 그리드는 요청된 높이와 너비를 지정할 필요가 없는 몇 안 되는 레이아웃 중 하나입니다.
<Grid>
<Grid.RowDefinitions>
<RowDefinition Height="100" />
<RowDefinition Height="*" />
</Grid.RowDefinitions>
<Label Text="test" Grid.Row="0" />
<WebView Source="https://dotnet.microsoft.com/apps/xamarin" Grid.Row="1" />
</Grid>
JavaScript 호출
WebView
에는 C#에서 JavaScript 함수를 호출하고 모든 결과를 호출하는 C# 코드로 반환하는 기능이 포함되어 있습니다. 이렇게 하려면 WebView.EvaluateJavaScriptAsync
메서드를 사용합니다.
var numberEntry = new Entry { Text = "5" };
var resultLabel = new Label();
var webView = new WebView();
...
int number = int.Parse(numberEntry.Text);
string result = await webView.EvaluateJavaScriptAsync($"factorial({number})");
resultLabel.Text = $"Factorial of {number} is {result}.";
메서드는 WebView.EvaluateJavaScriptAsync
인수로 지정된 JavaScript를 평가하고 결과를 .로 string
반환합니다. 이 예제 factorial
에서는 JavaScript 함수가 호출되어 결과 요소 number
값을 반환합니다. 이 JavaScript 함수는 로드되는 WebView
로컬 HTML 파일에 정의되며 다음 예제에 나와 있습니다.
<html>
<body>
<script type="text/javascript">
function factorial(num) {
if (num === 0 || num === 1)
return 1;
for (var i = num - 1; i >= 1; i--) {
num *= i;
}
return num;
}
</script>
</body>
</html>
쿠키
쿠키는 웹 요청과 함께 지정된 URL로 전송되는 쿠키에 설정할 WebView
수 있습니다. 이 작업은 개체를 CookieContainer
추가 Cookie
한 다음 바인딩 가능한 속성의 WebView.Cookies
값으로 설정하여 수행됩니다. 다음 코드에서 그 예를 볼 수 있습니다.
using System.Net;
using Xamarin.Forms;
// ...
CookieContainer cookieContainer = new CookieContainer();
Uri uri = new Uri("https://dotnet.microsoft.com/apps/xamarin", UriKind.RelativeOrAbsolute);
Cookie cookie = new Cookie
{
Name = "XamarinCookie",
Expires = DateTime.Now.AddDays(1),
Value = "My cookie",
Domain = uri.Host,
Path = "/"
};
cookieContainer.Add(uri, cookie);
webView.Cookies = cookieContainer;
webView.Source = new UrlWebViewSource { Url = uri.ToString() };
이 예제에서는 개체에 CookieContainer
단일 Cookie
이 추가된 다음 속성 값 WebView.Cookies
으로 설정됩니다. WebView
웹 요청을 지정된 URL로 보내면 쿠키가 요청과 함께 전송됩니다.
UIWebView 사용 중단 및 앱 스토어 거부(ITMS-90809)
2020년 4월부터 Apple은 더 이상 사용되지 UIWebView
않는 API를 사용하는 앱을 거부합니다. Xamarin.Forms 기본값으로 전환되지만 WKWebView
이진 파일에는 이전 SDK에 대한 참조가 Xamarin.Forms 여전히 있습니다. 현재 iOS 링커 동작은 이를 제거하지 않으므로 앱 스토어에 제출할 때 더 이상 사용되지 UIWebView
않는 API가 앱에서 참조되는 것처럼 보입니다.
Important
5.0에서는 Xamarin.Forms 클래스가 WebViewRenderer
제거되었습니다. 따라서 Xamarin.Forms 5.0은 컨트롤에 대한 참조를 UIWebView
포함하지 않습니다.
이 문제를 해결하기 위해 링커의 미리 보기 버전을 사용할 수 있습니다. 미리 보기를 사용하려면 링커에 추가 인수 --optimize=experimental-xforms-product-type
를 제공해야 합니다.
이 작업을 위한 필수 구성 요소는 다음과 같습니다.
- Xamarin.Forms 4.5 이상. Xamarin.Forms 앱에서 Material Visual을 사용하는 경우 4.6 이상이 필요합니다.
- Xamarin.iOS 13.10.0.17 이상 Visual Studio에서 Xamarin.iOS 버전을 확인합니다. 이 버전의 Xamarin.iOS는 Mac용 Visual Studio 8.4.1 및 Visual Studio 16.4.3에 포함되어 있습니다.
- 에 대한 참조를
UIWebView
제거합니다. 코드에 대한 참조 또는 을UIWebView
사용하는UIWebView
클래스가 없어야 합니다.
참조 검색 및 제거에 대한 자세한 내용은 UIWebView 사용 중단을 UIWebView
참조 하세요.
링커 구성
링커에서 참조를 제거 UIWebView
하려면 다음 단계를 수행합니다.
- iOS 프로젝트 속성 열기 – iOS 프로젝트를 마우스 오른쪽 단추로 클릭하고 속성을 선택합니다.
- iOS 빌드 섹션으로 이동합니다. iOS 빌드 섹션을 선택합니다.
- 추가 mtouch 인수 업데이트 – 추가 mtouch 인수에서 이 플래그
--optimize=experimental-xforms-product-type
를 추가합니다(이미 있을 수 있는 값 외에). 참고: 이 플래그는 링커 동작이 SDK만 또는 모두 연결로 설정된 상태에서 함께 작동합니다. 어떤 이유로든 링커 동작을 모두로 설정할 때 오류가 표시되는 경우 이는 앱 코드 또는 링커로부터 안전하지 않은 타사 라이브러리 내의 문제일 수 있습니다. 링커에 대한 자세한 내용은 Xamarin.iOS 앱 연결을 참조 하세요. - 모든 빌드 구성 업데이트 – 창 맨 위에 있는 구성 및 플랫폼 목록을 사용하여 모든 빌드 구성을 업데이트합니다. 업데이트해야 하는 가장 중요한 구성은 릴리스/i전화 구성입니다. 일반적으로 App Store 제출용 빌드를 만드는 데 사용되므로
이 스크린샷에서 새 플래그가 있는 창을 볼 수 있습니다.
이제 새(릴리스) 빌드를 만들고 앱 스토어에 제출할 때 사용되지 않는 API에 대한 경고가 없어야 합니다.