What does "public App() : this(null) { }" do when using Xamarin Forms with Prism - xamarin.forms

So I was jsut wondering why in the Prism Doc and VS template this line is included in the App Class.
public App() : this(null) { }
Since today I commented it out and the App still started without any issues in both iOs and Android.
Best Regards
Basecrusher

If you don't need/want an IPlatformInitializer, it's fine to pass null, and the default implementation does so.
I guess the code is in there to remind you that you could pass an IPlatformInitializer if you needed/wanted to.

"With Xamarin.Forms you may have read how you can add the Dependency attribute for an impelementing type in your Platform Specific code and then resolve it with the Xamarin.Forms DependencyService. This is considered a major Anti-Pattern that should be avoided when you are using a proper Dependency Injection container. It is for this reason that Prism has dropped all support for working with the DependencyService as of Prism 7.0. Starting with Prism 6.3 the IPlatformInitializer was introduced. This allows you to easily register types with Prism's container."
https://prismlibrary.com/docs/xamarin-forms/dependency-injection/platform-specific-services.html

Related

Can't get Prism 8 with DryIoc RegisterServices and Platform-Specific support to work

Trying to use Prism 8, ContainerLocator, IHttpClientFactory and Platform-Specific Service registration with DryIoc Extensions (not Magician) in a Xamarin Forms application
I have these nuget packages installed
Prism.DryIoc.Extensions
Prism.Forms
My main Xamarin Application inherits from PrismApplicationBase.
In platform code (eg Android) I have IPlatformInitializer implented by MainActivity and for platform-specific services I use:
LoadApplication(new App(this));
as documented here:
https://prismlibrary.com/docs/dependency-injection/platform-specific-services.html
This line causes the IContainerExtension to be resolved in the shared code
protected override IContainerExtension CreateContainerExtension()
...but I can't find a way to successfully return a valid IContainerExtension implementation.
I've attempted:
https://prismlibrary.com/docs/dependency-injection/container-locator.html
var createContainerExtension = () => new DryIocContainerExtension();
ContainerLocator.SetContainerExtension(createContainerExtension);
But the code given here can't even compile - the DryIocContainerExtension class created is defined INTERNAL and isn't available to my application code.
If I use...
PrismContainerExtension.Init();
or
return ContainerLocator.Current;
...as worked previously (eg Prism 7.2) I get a runtime error as described here:
https://githubmemory.com/repo/dansiegel/Prism.Container.Extensions/issues/180
ValueFactory attempted to access the Value property of this instance.
Please can someone advise what I'm doing wrong, or do I have to get my company to pay for Magician to resolve my issue?

Xamarin Forms: Open downloaded file in default Android/iOS application

I am using Xamarin Forms. I would like to download jpg file (it is done) and then open that jpg in default application on Android/iOS (opening photo browser with this photo). Of course photo is single example, I would like to open any file in default application.
I found several solutions native-only but my application is designed to be cross-platform. I though that I can use Launcher from Xamarin.Essentials package but apparently I can't.
How to achieve this?
You can have a try with Xamarin.Essentials: Launcher:
var fn = "File.txt";
var file = Path.Combine(FileSystem.CacheDirectory, fn);
File.WriteAllText(file, "Hello World");
await Launcher.OpenAsync(new OpenFileRequest
{
File = new ReadOnlyFile(file)
});
I found several solutions native-only
Opening something in another app is quite close to the system for a mobile application and there are some things to consider, which dependend on the platform. Usually, mobile apps run in a sandbox with very limited access to the surrounding system. Particularly this means that, if you downloaded a file to the sandbox of your app, other apps (which native viewers are), aren't allowed to access the file.
On Android, you can copy the file to a shared space (see Application.Context.GetExternalFilesDir(null)) and then open it. This might be possible with Essentials, but I'm not quite sure, but since we're on the Android platform anyway now, you could create an intent now anyway.
On iOS you create controllers from within your app (for example the QLPreviewController to preview the file) that may access items in your sandbox. Depending on the type of controller (e.g. UIActivityViewController) they may open other apps.
How to use this platform-independently?
Since you are programming a platform independent app, you'll have to take care that the correct class is called to the platform dependent work. There are several options how you can achieve this
Use the DependencyService
Use a real dependency injection framework
Use an abstract base class with initialization in the platform dependent projects
DependencyService
To use the Xamarin.Forms DependencyService you need two things
An interface for the functionality you'd like to implement
One implementation per platform
Assuming you hvae a simple interface to share a file
public IShareFile
{
void ShareFile(string fileName);
}
you can implement an implementation of this interface on each platform and add the DependencyAttribute to the assembly. e.g. for iOS:
[assembly: Dependency(typeof(MyApp.iOS.DeviceOrientationService))]
namespace MyApp.iOS
{
public class ShareFile : IShareFile
{
public void Share(string fileName)
{
// implementation goes here
}
}
}
The general scaffold is the same for Android, albeit the implementation differs.
Using a real dependency injection framework
Basically it's pretty much the same. You can skip the DependencyAttribute, though. In order to make the implementation available you'll have to get hold of the DI container from your platform specific code, which might be tricky. This might be an overshoot for a single dependency, but if you're using a DI container anyway and there are X dependencies, it might be worth the effort.
Using an abstract base class
Add an abstract base class to your project
public abstract class ShareFile
{
public static ShareFile Instance { get; protected set; }
public abstract void Share(string fileName);
}
and in your implementation in the platform specific project, you add an Init() method
internal class ShareFileImpl : ShareFile
{
public static void Init()
{
ShareFile.Instance = new ShareFileImpl();
}
public void Share(string fileName)
{
// implementation goes here
}
}
This init method must be called from your platform specific code. Most likely during initialization. The implementation can then be accessed via its abstraction from your platform independent code (of course you'll see only the abstraction, public methods added to ShareFileImpl won't be visible from your platform independent code).
ShareFile.Instance.Share(fileName);
A combination of the abstract class approach and dependency injection is also conceivable. When registering your classes in the DI framework, you could register the platform instance like
container.RegisterInstance<ShareFile>(ShareFile.Instance);
This way you can make use of the DI container features (e.g. constructor injection), while keeping the hassles of using the DI container from your platform specific project away from you. The drawback is, that you'll still have to call ShareFileImpl.Init() from your platform specfic code.

Can't Resolve Platform Effect in Xamarin Forms component

I am having issues with Platform Effects in Xamarin Forms. These effects worked in a shared library format, and we are now migrating to .NET Standard 2.0 for reasons outside of the scope of this post.
Project Setup
VS 2017 15.8.0
Xamarin Forms 3.1.0.697729
Two .Net Standard 2.0 projects (one is for components, the other for the main UI)
Two Android projects (one that runs, the other is an Android .dll)
Two iOS projects (same deal)
Main Issue
None of my platform effects in the Android .dll work. They all resolve as null effect.
According to the documentation, my setup is correct. (Documentation here)
I found two different issues and have hit a brick wall.
When I follow the instructions exactly and place [assembly: ResolutionGroupName("MyGroupName")] on the platform renderer itself, I get exceptions with Xamarin's dependency resolver. There is no message, just an exception and stack trace that leads back to the constructor of the RoutingEffect.
When I use a slightly different pattern and register that on the namespace of an empty file in my .NET Standard 2.0 project, all effects return as null effect.
I've been Googling and digging through forums to no avail. Does anyone have an idea what could be the problem?
Side notes: All of the custom renderers work after using the static Init() trick, but not the effects. I have also tried making the typeof() statement reference both the Android version of the class and the .NET Standard 2.0 version of the class.
For the sake of completeness, here's what I have going.
NET Standard 2.0:
namespace MyBaseNamespace.Components.Effects
{
public class SearchBarStylingEffect : RoutingEffect
{
public SearchBarStylingEffect() : base("MyGroupName.SearchBarStylingEffect")
{
}
}
}
Android:
[assembly: ResolutionGroupName("MyGroupName")]
[assembly: ExportEffect(typeof(SearchBarStylingEffect), "SearchBarStylingEffect")]
namespace MyBaseNamespace.Components.Android.Renderers.Effects
{
public class SearchBarStylingEffect : PlatformEffect
{
…
}
}
(iOS is the same as Android, only the namespace is different)
I also posted this on Xamarin's forums, and Billy Liu from Xamarin asked a question that ultimately led me down the right path. I'll link to that here and also post what fixed it.
link: Xamarin Forms Post
Here's the resolution from that post:
In short, I had to do the following things to get this functional
(which it now is):
Ensure that the GroupNameResolution tag was on the first Effect ever initialized in the app.
Remove the empty file initializer from my .Net 2.0 project.
???
Profit.

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.

Xamarin Forms Prism Can't access PCL classes from android project

I'm using Xamarin Forms Prism and I can't use my PCL classes in android project.
common example :
here is the Interface in PCL
namespace BlankApp.Helpers
{
public interface IToast
{
void MakeLongToast(string msg);
}
}
and here is the class in android project
namespace BlankApp2.Droid.DependencyService
{
public class ToastImp : IToast
{
}
}
it can not find IToast Interface reference !
there is a suggest from IDE with this msg : "Reference 'projectname-WebAppMAinModule' and use 'projectname.Helpers.IToast' "
screenshot
which does nothing actually !
I don't have these kind of problems in XamarinForms I face theme while using Prism . Do I forget something in referencing my PCL ?
I'm using
Prism.Forms (7.0.0.396)
Xamarin.Forms (2.5.0.122203)
also there are my project dependencies
here
You should be able to implement PCL interfaces and use its classes, etc. in your platform specific code (Android included).
Use the following steps:
Make sure your Android project is referencing your PCL.
Delete your Android obj & bin folders.
Recompile your PCL
After recompiling your PCL, recompile your Android project
See if it recognizes your interface now.
If the above doesn't work, then as one last option is:
Close the solution
Re-open the solution
Both of these typically work when your project won't recognize a newly created Interface.

Resources