Xamarin UI Testing - xamarin

I would like to add UnitTest into my Xamarin app, I get the splash screen displaying on the Andriod emulator and then the landing page loads but the next page it seems to closes the app . I have break point around the Platform.Android and that hits but it never hit the end of that method. I added WaitTimes for 5 minutes and I will get the timeout exception
Any idea why the app closes ?
static class AppManager
{
private const string ApkPath = #"C:\pathtoapkfile.apk";
static IApp app;
public static IApp App
{
get
{
if (app == null)
throw new NullReferenceException("'AppManager.App' not set. Call 'AppManager.StartApp()' before trying to access it.");
return app;
}
}
static Platform? platform;
public static Platform Platform
{
get
{
if (platform == null)
throw new NullReferenceException("'AppManager.Platform' not set.");
return platform.Value;
}
set { platform = value; }
}
public static void StartApp()
{
if (Platform == Platform.Android)
{
app = ConfigureApp
.Android
.ApkFile(ApkPath)
.WaitTimes(new WaitTimes())
.StartApp(AppDataMode.Clear);
}
if (Platform == Platform.iOS)
{
app = ConfigureApp
.iOS
.StartApp(AppDataMode.Clear);
}
}
}

Related

Xamarin enabled GPS android / IOS

Good afternoon,
How do I turn on GPS in android and IOS project after giving consent?
The consent code works seamlessly:
public MainPage()
{
InitializeComponent();
CrossConnectivity.Current.ConnectivityChanged += Current_ConnectivityChanged;
CheckPermissions();
}
private async void CheckPermissions()
{
var status = await Permissions.CheckStatusAsync<Permissions.LocationWhenInUse>();
if(status == PermissionStatus.Granted)
{
return;
}
else
{
await Permissions.RequestAsync<Permissions.LocationWhenInUse>();
}
}
How do I turn on the GPS automatically after giving consent?

How do I enable WebGL in Xamarin.Forms WebView on UWP?

I’m new to Xamarin.Forms and tried using WebView on my Windows 10 x64 v1803 machine with UWP but I can’t see how to get it to work with WebGL.
Sites which use WebGL either display a message that “Your video card does not support WebGL or just don’t display and graphical content at all.
Is this a limitation of UWP or WebView itself?
Is it a WebView configuration issue?
WebGL works in all other browsers on this machine.
UWP WebView control is support WebGL. There is similar issue case in msdn you could refer. Please try to use SeparateProcess mode WebView to replace the default one.
public MainPage()
{
this.InitializeComponent();
var MyWebView = new WebView(WebViewExecutionMode.SeparateProcess);
MyWebView.Source = new Uri("http://cycleblob.com/");
this.RootGrid.Children.Add(MyWebView);
}
I had the same problem, but with the newer Xamarin Forms it took a little more poking around to get this took work right. However, I do like that they moved the native WebView resolver back to the responsibility of the UWP/iOS/Android project (as a native XAML object) instead of using code branching with compiler directives in the Shared project.
Start by creating a HybridWebView class in the shared project to use as your WebForm view object:
public class HybridWebView : Xamarin.Forms.WebView
{
Action<string> action;
public static readonly BindableProperty UriProperty = BindableProperty.Create(
propertyName: "Uri",
returnType: typeof(string),
declaringType: typeof(HybridWebView),
defaultValue: default(string));
public string Uri
{
get { return (string)GetValue(UriProperty); }
set { SetValue(UriProperty, value); }
}
public void RegisterAction(Action<string> callback)
{
action = callback;
}
public void Cleanup()
{
action = null;
}
public void InvokeAction(string data)
{
if (action == null || data == null)
{
return;
}
action.Invoke(data);
}
}
Then in the UWP project, create a custom renderer, which will construct the native WebView and relay the events back to the WebForms object in the Shared project:
Put this at the top of the namespace, to link the HybridWebView with the Custom Renderer:
[assembly: ExportRenderer(typeof(HybridWebView), typeof(WebViewRenderer2))]
Then create the renderer class (for the IOS and android projects, if you leave this class out, it defaults to the standard native controls which seem to work fine for me):
public class WebViewRenderer2 : ViewRenderer<Xamarin.Forms.WebView, Windows.UI.Xaml.Controls.WebView>, IWebViewDelegate
{
Windows.UI.Xaml.Controls.WebView _control;
public void LoadHtml(string html, string baseUrl)
{
}
public void LoadUrl(string url)
{
}
protected override void Dispose(bool disposing)
{
}
protected override void OnElementChanged(ElementChangedEventArgs<Xamarin.Forms.WebView> e)
{
if (_control == null) {
_control = new Windows.UI.Xaml.Controls.WebView(WebViewExecutionMode.SeparateProcess);
SetNativeControl(_control);
}
}
protected override void OnElementPropertyChanged(object sender, PropertyChangedEventArgs e)
{
var xamWebView = sender as HybridWebView;
switch(e.PropertyName.ToLower())
{
case "source":
var urlSource = xamWebView.Source as Xamarin.Forms.UrlWebViewSource;
_control.Source = new Uri(urlSource.Url);
break;
case "width":
_control.Width = xamWebView.Width;
break;
case "height":
_control.Height = xamWebView.Height;
break;
case "isfocused":
var focused = xamWebView.IsFocused;
if (focused)
_control.Focus(FocusState.Programmatic);
else
_control.Focus(FocusState.Unfocused);
break;
}
}
}
You can also use the Custom Renderer to inject scripts, and you can use it to communicate from the native webview back to the Xamarin App, as seen here: HybridWebView Communication

How to create a code-only webview with Xamarin.Forms

I'm trying to use a library that doesn't has a .Net SDK, but as I want to use it only to return a string, I thought I could use it's JS SDK by creating a custom WebView that returns strings (https://xamarinhelp.com/xamarin-forms-webview-executing-javascript/).
The first problem that I faced was that a CustomRenderer is not called in Xamarin.Forms until the View is added to a Page (or at least I couldn't make it be called). To fix this I added a call to Platform.CreateRenderer in each platform.
It did the trick and the CustomRenderer executed. But when I tried to call a JS function to retrieve a string, the app just hung and stayed that way.
I didn't try to insert the WebView in a Page because I want it to be independent of the page that the app is current on, and as I want a "code-only" html, I don't see the point of adding it somewhere.
My classes:
JSEvaluator
namespace MyNamespace.Views
{
public class JSEvaluator : WebView
{
public static BindableProperty EvaluateJavascriptProperty = BindableProperty.Create(nameof(EvaluateJavascript), typeof(Func<string, Task<string>>), typeof(JSEvaluator), null, BindingMode.OneWayToSource);
public Func<string, Task<string>> EvaluateJavascript
{
get { return (Func<string, Task<string>>)GetValue(EvaluateJavascriptProperty); }
set { SetValue(EvaluateJavascriptProperty, value); }
}
public JSEvaluator()
{
}
}
}
UWP Renderer
[assembly: ExportRenderer(typeof(JSEvaluator), typeof(JSEvaluatorRenderer))]
namespace MyNamespace.UWP.Renderers
{
public class JSEvaluatorRenderer : WebViewRenderer
{
public JSEvaluatorRenderer() { }
protected override void OnElementChanged(ElementChangedEventArgs<WebView> e)
{
base.OnElementChanged(e);
var webView = e.NewElement as JSEvaluator;
if (webView != null)
webView.EvaluateJavascript = async (js) =>
{
return await Control.InvokeScriptAsync("eval", new[] { js });
};
}
}
}
Creation and use
if (jsEvaluator == null)
{
jsEvaluator = new JSEvaluator { Source = new HtmlWebViewSource { Html = HTML.html } };
#if __ANDROID__
Xamarin.Forms.Platform.Android.Platform.CreateRenderer(jsEvaluator);
#elif __IOS__
Xamarin.Forms.Platform.iOS.Platform.CreateRenderer(jsEvaluator);
#elif WINDOWS_UWP
Xamarin.Forms.Platform.UWP.Platform.CreateRenderer(jsEvaluator);
#endif
}
Thanks for the help :)
I had to add the WebView to a page, as #SushiHangover said in the comment. With this done, it worked as expected.

NativeScript Android API Version check

I added android platform to my nativescript app using the following command
tns platform add android
Now I cannot figure out which API version of the platform was added?
How can I figure this out?
The platform add android command will fetch all necessary files to start building apps for Android. I'll assume that you are asking about the compileSdk version of android apps - that is determined at Build time.
When you execute tns build/run android unless the --compileSdk 21/22/23/24/25 flag is specified, the latest version available on your system will be used.
So for example if I just recently downloaded Android SDK Build-Tools and SDK-Platform 25 from the Android SDK Manager the application package that is uploaded on the device will be built with platform 25.
Medium have a good article about compileSdk, targetSdk and minSdk that I recommend you read -> https://medium.com/google-developers/picking-your-compilesdkversion-minsdkversion-targetsdkversion-a098a0341ebd#.eoe0x9isx
Good luck!
latest docs say:
https://docs.nativescript.org/angular/ng-framework-modules/platform
import { isAndroid, isIOS, device, screen } from "tns-core-modules/platform";
class DeviceInfo {
constructor(
public model: string,
public deviceType: string,
public os: string,
public osVersion: string,
public sdkVersion: string,
public language: string,
public manufacturer: string,
public uuid: string
) { }
}
class ScreenInfo {
constructor(
public heightDIPs: number,
public heightPixels: number,
public scale: number,
public widthDIPs: number,
public widthPixels: number
) { }
}
#Component({
moduleId: module.id,
templateUrl: "./platform-module-example.html"
})
export class PlatformModuleExampleComponent {
public isItemVisible: boolean = false;
public deviceInformation: DeviceInfo;
public isItemVisibleScreenInfo: boolean = false;
public screenInformation: ScreenInfo;
public deviceInfoButton: string = "Show device info";
public screenInfoButton: string = "Show/Hide screen info";
constructor() {
this.deviceInformation = new DeviceInfo(
device.model,
device.deviceType,
device.os,
device.osVersion,
device.sdkVersion,
device.language,
device.manufacturer,
device.uuid);
this.screenInformation = new ScreenInfo(
screen.mainScreen.heightDIPs,
screen.mainScreen.heightPixels,
screen.mainScreen.scale,
screen.mainScreen.widthDIPs,
screen.mainScreen.widthPixels);
}
public checkPlatformType(args) {
let message = "";
if (isAndroid) {
message = "You are using Android device";
} else if (isIOS) {
message = "You are using IOS device";
}
alert(message);
}
public deviceInfo(args) {
if (this.isItemVisible) {
this.isItemVisible = false;
this.deviceInfoButton = "Show device info";
} else {
this.isItemVisible = true;
this.deviceInfoButton = "Hide device info";
}
}
public screenInfo(args) {
if (this.isItemVisibleScreenInfo) {
this.isItemVisibleScreenInfo = false;
this.screenInfoButton = "Show screen info";
} else {
this.isItemVisibleScreenInfo = true;
this.screenInfoButton = "Hide screen info";
}
}
}

Simple navigation in Windows 8 web view

I'm working on porting a Windows Phone 8 application to tablet, and I've bumped into a problem with the WebView API. In Windows Phone 8 and Windows 8.1, the WebBrowser and WebView controls both have a GoBack() method. However, I need my application to be compatible for Windows 8, whose WebView API does not have such a method. Are there any alternatives/workarounds that anyone's used for Windows 8 apps?
In the end I just ended up writing a wrapper for the WebView to manage the navigation stack. Here's the relevant code, for anyone who's interested. Note that I only needed to handle backwards navigation, so I used a Stack. If forwards navigation is also required, it'd probably make sense to replace the Stack with a List and store the index of the current page instead.
public class WebViewWrapper
{
private Stack<Uri> _navigationStack;
private Uri _currentUri;
public WebView WebView { get; private set; }
public bool CanGoBack
{
get { return _navigationStack.Count > 0; }
}
public WebViewWrapper(WebView _webView)
{
_navigationStack = new Stack<Uri>();
WebView = _webView;
WebView.LoadCompleted += (object s, NavigationEventArgs e) => {
if (_currentUri != null)
{
_navigationStack.Push(_currentUri);
}
_currentUri = e.Uri;
};
}
public void GoBack()
{
if (CanGoBack)
{
_currentUri = null;
WebView.Navigate(_navigationStack.Pop());
}
}
}
An example of usage would be as follows:
// Code behind for a view called WebBrowserPage
public sealed partial class WebBrowserPage : Page
{
private WebViewWrapper _webViewWrapper;
public WebBrowserPage()
{
// webView is a WebView in the xaml with x:Name="webView"
_webViewWrapper = new WebViewWrapper(webView);
}
// Other code for navigating to a Uri specified in a ViewModel.
// Event handler for a back button press
private void BackButton_Click(object sender, RoutedEventArgs e)
{
if (_webViewWrapper.CanGoBack)
{
_webViewWrapper.GoBack();
}
else
{
// Code that executes a command in the ViewModel to leave the WebBrowserPage
}
}
}
WinRT XAML Toolkit has a WebBrowser control that does some of that, but I haven't used it in any app, so I can't vouch for its quality.

Resources