Replace WebView with WKWebView in Xamarin Forms application - xamarin.forms

I have a webview inside my Xamarin Forms application which opens report downloaded from server in html format. Today I uploaded my archived application to app store and get information about ITMS-90809: UIWebView API Deprecation.
The problem is that I have no idea how to replace UIWebView with WKWebView in cross platform application. I've tried several solutions:
1) Creating Custom renderer for WebView - but this is no solution really because I need to inherit my new class by WebView superclass. So Apple warn me again with the same message.
2) Creating dependency service and use custom renderer in ios project only. But this is the same problem - there is still WebView reference in shared project.
So, is there any way to inject WKWebView directly to StackLayout in iOS? I know that WKWebView is iOS only and StackLayout is Xamarin.Forms component but really I don't have any idea how to do this.
Can anyone help me?

There is an issue in Github you can follow: Deprecated API Usage UIWebView
WebViewRenderer in iOS implements UIWebView, and the file stays even if you switch over the WkWebViewRenderer. That's why you get the error message.
Xamarin team is working on it and it will fixed sometime in the future.
Also, there is an Apple statement says:
The App Store will no longer accept new apps using UIWebView as of
April 2020 and app updates using UIWebView as of December 2020.
So you can still submit app with UIWebView right now and the error messgae is just a warning.
Relevant links: Make WkWebViewRenderer default for iOS WebView

Related

Xamarin Forms Globalization

I have looked over this article regarding globalization in Xamarin Forms. The article indicates I need to create an interface in order to access the language on each platform. However, in my last App, I was able to simply put this line of code in my shared code and it seemed to work fine for getting the language:
ls_Language = CultureInfo.CurrentUICulture.TwoLetterISOLanguageName;
Is there a reason a line of code similar to this wont work for Globalization using a resource file in Xamarin Forms?
Yes, your code is to set resource Culture when the application first loads, it is the same as using the DependencyService in the Xamarin.Forms App class to call the interface and set our RESX resources culture to the correct value.
You may optionally update this value according to platform-specific events that may be raised on iOS or Android if the user updates their language preferences while the app is running. So you need to use ILocalize interface.

What's the proper way of setting up MvvmCross 6.0 Xamarin.Forms UWP application code?

I have my UWP Application inherited from Base class, which inherits from MvxApplication<Setup, CoreApp>:
public sealed partial class App : WindowsApplication
{
public App()
{
InitializeComponent();
}
}
public class WindowsApplication : MvxApplication<Setup, CoreApp>
{
}
public class Setup : MvxWindowsSetup<CoreApp>
{
public override IEnumerable<Assembly> GetViewAssemblies()
{
// need to do this as otherwise I receive the message that corresponding view to view model is not found
var assemblies = base.GetViewAssemblies().ToList();
assemblies.Add(typeof(Forms.App).Assembly);
return assemblies;
}
}
However, when launching it, receiving the following error message:
The type MvxContentPagePresentationAttribute is not configured in the
presenter dictionary
As I understand, all that is not proper way to launch Xamarin.Forms MvvmCross application, as UWP App and Setup should be inherited from something like MvxFormsApplication and MvxFormsWindowsSetup<CoreApp, Forms.App> respectively (to have Xamarin.Forms app properly initialized).
But:
MvxFormsApplication is not generic and doesn't provide ability of passing Forms-generic setup.
even if I inherit the App from MvxFormsApplication and use this.RegisterSetupType<MvxFormsWindowsSetupInheritor>();, Visual Studio compiler never allows me to compile the project because of some weird error message (something like The name “WindowsApplication” does not exist in the namespace “…”) (this might be some issue of Visual Studio, but I have VS 15.7 version, which expects the code to work (again, MvvmCross declares they support UWP and XF)).
So, from my understanding, if there is Xamarin.Forms app, there must be also some way of passing actually Xamarin.Forms App class to the UWP App class initialization.
MvvmCross, again, stands for UWP and Xamarin.Forms support, but I can't see any clear example of the way to setup such type of application.
MvvmCross documentation as always is quite "modest". There are some instructions about setting up MvvmCross UWP app as well as setting up MvvmCross XF iOS/Android, but the only word about MvvmCross XF UWP is:
You are now free to place your custom renderers in a different
assembly. All you have to do to make it work is to add your assembly
to the Setup.ViewAssemblies collection.
(in official website docs)
(which is still sounds weird, as iOS and Android versions don't need that additional code, which makes me think that such (current) documentation isn't quite actualized)
and
UWP, WPF
Extend App from MvxApplication. ( App : MvxApplication { } )
from MvvmCross.Forms package readme.txt file, when all other platforms, again, expect inheritance for the app classes from MvxForms*-based ones.
MvvmCross guys, any thoughts on that?
When I set up a new Xamarin.Forms project, I always follow the Playground sample in the MvvmCross GitHub as this example evolves along with the API and is always up-to-date, as it is part of the MvvmCross solution, so any commits need to preserve its functionality. So if you want to see how everything should look in a minimal UWP + Xamarin.Forms project see the Playground.Forms.UI and Playground.Forms.Uwp projects in the linked folder.

BackgroundUploader for Xamarin.Forms C#

I am working on converting my WindowsPhone project to Xamarin.Forms project.
I had a BackgroundUploader task for uploading my video files to server in background. However, I am not able to find a similar class in Xamarin Forms that does the same job.
Below is my BackgroundUploader code for WindowsPhone project.
Any kind suggestions please.
BackgroundUploader bguploader = new BackgroundUploader();
bguploader.SetRequestHeader(RequestHeader, jsonConverter.Serialize(Video));
UploadOperation upload = bguploader.CreateUpload(new Uri(url), videoFile);
Progress<UploadOperation> callback = new Progress<UploadOperation>(UploadProgress);
await upload.StartAsync().AsTask(canceltoken.Token, callback);
This is definitely a OS-specific functionality and it has no built-in solution in Xamarin.Forms.
As you mentioned BackgroundUploader is the solution working for UWP and Windows Phone.
For some info on iOS background execution check out the documentation. You will probably use NSURLSessionUploadTask.
On Android you should look into Background Services. See Android documentation.
To implement this in a cross-platform manner, you will have to create a shared interface and then provide platform-specific implementations. See Xamarin.Forms DependencyService for more details.

Appium iOS 11 RemoteViewBridge - access default app sdk like Photo, Email

App has access to import image from photo and other option is sending doc via email. In automation I could access photo and email options once my app loads the ui on init. This was working in iOS 10 and Xcode 8. Now, Upon upgrade the Xcode to 9 and iOS 11 the same app is not allowing me to access the element in Photo and Email. When I checked the element in Inspector, it shows me the entire Photo/Email page is RemoteViewBridge. Could you help me on this, how to fix this issue?
UIImagePickerController class has a private view hierarchy. The collection view cannot be accessed anymore from appium. In ios 11 you cannot access these elements. Try using iOS 10.3 or wait for the fix. I am accessing using coordinates in my project for the time being.

how to implement Exif.PCL in xamarin forms?

I am trying to create a project in which picture is taken to upload from mobile camera, but when it is taken with front camera it rotates upside down (especially Android). I have read suggestions to use Exif.PCL nuget package but dont know how to implement the same. Can anybody help me out with this ?
Thanks
Background
I had the same problem in one of my apps. After trying different approaches I've found several problems with current implementations. Generally I use XLabs, which has media picking capabilities.
Issues
First of all it lacked support for scaling and autorotating images after they are taken. That's your question. So, first of all I had to implement some after-processing as soon as the image was picked.
Second, there are problems with Android and Xamarin.Forms due do how Activities are handled in Android. The way it works on Android is you launch CameraActivity or PhotoGalleryActivity which are actually hosted in a different application. Those Activities use substential amount of system memory, and due to this operating system will try to kill non-forground processes, including your app :) Workarround for this was completely implementing photo taking flow inside of my application by creating photo taking activities from scratch. Thus, I will never leave my app, and Android runtime will never kill my application.
Solution
Taking account all of this, I've implement my own flow of Image capturing. You can find the source code HERE. The basic architecture is following:
I've created IImageService, which has methods for picking images from camera or library.
public interface IImageService
{
Task<IImage> GetImageFromLibrary();
Task<IImage> GetImageFromCamera();
}
Then I've implemented this for iOS and Android separately and used dependency injection. For iOS I use XLabs implementation, cause it works as it should there are no problems with it. For Android I've created several activities to support picking images from Camera and Library: CameraActivity, PhotoGaleryActivity, which basically replace the native image picking activities.
After I pick the image I do scaling and rotating procedure. For iOS I've created UIImageToolbox static class which has GetScaledAndRotatedImage method. For Android it's BitmapToolbox static class which has GetScaledAndRotatedBitmap method.
In my sample application I've created ImageViewModel and ImagePage to demonstrate the usage of IImageService. It should be straightforward.
How to use the sample app?
Let me give a small remark. You can use only XLabs implementation for both iOS and Android and just use BitmapToolbox and UIImageToolbox to implement the scaling and rotation. And this is answer to your question. However, if you want your app to be stable on Android you need to go a little bit dipper.
Install all the necessary nuget packages to your Forms, Droid and iOS projects. You can find the packages that are used by sample application in packages.config file of each project
I use MvvmCross Messenger plugin for broadcast messaging, if you have alternative you can easily replace it. But if you want to use it, don't forget to register dependencies in your AppDelegate and MainActivity
DependencyService.Register();
Add necessary classes to your Forms, iOS and Android projects from sample application. You can use Resharper to fix namespaces for you.
For xaml files, if you drug and drop to forms project default build action and Custom Tool are set to wrong values. Thus click the xaml file, select properties set Build Action to Embedded Resource, and Custom Tool to MSBuild:UpdateDesignTimeXaml
For android project add necessary resources from drawable, drawable-xxhdpi, layout and values folders.
In grid_cell_photo_galery_item.axml file fix namespaces. Replace ImageSample.Droid.Views.SquareRelativeLayout by your namespace.
For Android, right click Android project, select properties, go to Android Manifest and add CAMERA, READ_EXTERNAL_STORAGE and WRITE_EXTERNAL_STORAGE permissions.
For Android, right click Android project, select properties, go to Advanced and set Max Heap Size to something like 1G, this is needed because PhotoGalaryActivity uses substantial amount of memory to display images and we need an increased heap size.
For iOS, don't forget to add dependency injection for MediaPicker in AppDelegate - DependencyService.Register<MediaPicker>();
That's all.

Resources