Xamarin Forms - Shiny.AndroidShinyHost not available - xamarin.forms

I am using Shiny for xamarin to schedule background jobs.
I am trying to call my startup class from my mainApplication class but AndroidShinyHost is not available. My Target is Android 10.
I used the following sample
https://github.com/shinyorg/samples/tree/main/Jobs
MainApplication.CS
using System;
using Shiny;
using Android.App;
using Android.Runtime;
namespace Inventory.Droid
{
[Application]
public class MainApplication : Application
{
public MainApplication(IntPtr handle, JniHandleOwnership ownerShip) : base(handle, ownerShip)
{
}
public override void OnCreate()
{
base.OnCreate();
Shiny.AndroidShinyHost.Init(this, new Startup()); //Not available
}
}
}

Related

Xamarin SQLite db connections issue

I am trying to connect my xamarin app with SQLite, everything seems fine but in App.xaml.cs i get the following error: System.NullReferenceException: 'Object reference not set to an instance of an object.'
This is how my App.xaml.cs page looks like:
using System;
using TestAppDemo.Services;
using Xamarin.Forms;
using Xamarin.Forms.Xaml;
namespace TestAppDemo
{
public partial class App : Application
{
public App()
{
InitializeComponent();
DependencyService.Get<ISQLite>().GetConnectionWithCreateDatabase();
MainPage = new NavigationPage(new MainPage());
}
protected override void OnStart()
{
}
protected override void OnSleep()
{
}
protected override void OnResume()
{
}
}
}
Can anyone help? Do I need to provide you with more information?
Thanks!

How to access ViewWillAppear/ViewDidDisappear in ViewRenderer<HybridWebView, WkWebViewRenderer>?

I'm trying to port an Android existing custom ViewRenderer to iOS.
I'm using version 4.8 of Xamarin.Forms.
Specifically, I need to match Android's OnAttachedToWindow & OnDetachedFromWindow.
The Android Code is like the following:
public partial class HybridWebViewRenderer : ViewRenderer<HybridWebView, Android.Webkit.WebView>
{
protected override void OnAttachedToWindow()
{
base.OnAttachedToWindow();
...
}
protected override void OnDetachedFromWindow()
{
base.OnDetachedFromWindow();
...
}
}
According to this link, I would need to override ViewWillAppear which is the iOS equivalent to OnAttachedToWindow.
The custom Renderer for iOS is the following:
public partial class HybridWebViewRenderer : ViewRenderer<HybridWebView, WkWebViewRenderer>, IWKScriptMessageHandler
{
}
But the overrides are not available.
How can I do that?
ViewWillAppear and ViewWillDisappear are the life cycle method of UIViewController.So you could create the custom renderer of ContentPage
in the ContentPage that contains the WebView
using Foundation;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using UIKit;
using Xamarin.Forms;
using Xamarin.Forms.Platform.iOS;
using App1;
using App1.iOS;
[assembly:ExportRenderer(typeof(MainPage),typeof(MyPageRenderer))]
namespace App1.iOS
{
public class MyPageRenderer:PageRenderer
{
public override void ViewWillAppear(bool animated)
{
base.ViewWillAppear(animated);
MessagingCenter.Send<Object,UIViewController>(this,"ViewWillAppear",this); // send message when the method been called .
}
public override void ViewWillDisappear(bool animated)
{
base.ViewWillDisappear(animated);
MessagingCenter.Send<Object, UIViewController>(this, "ViewWillDisappear", this);
}
}
}
in WebViewRenderer
Subscribe the message in the constructor .
MessagingCenter.Subscribe<Object, UIViewController > (this, "ViewWillDisappear",(arg,controller)=> {
// controller is the current UIViewController
});

How save session storage in Xamarin Forms?

i want to create data to all the application
using static System.Net.Mime.MediaTypeNames;
public class Session
{
void btnLoginClick()
{
NombreUsuario = Username.Text;
Application.Current.Properties["name"] = NombreUsuario;
Application.Current.Properties["IsLoggedIn"] = true;
}
}
i have this error
'MediaTypeNames.Application' does not contain a definition for 'Current'
My app:
namespace Dinamic.Trailer.Mobile.Forms
{
public partial class App : Application
{
public App()
{
Locator.ConfigureIoC();
InitializeComponent();
}
protected override async void OnStart()
{
await InitNavigation();
}
//onsleep()//OnStart
private Task InitNavigation()
{
var navigationService = Content.Resolve<MainNavigation>();
return navigationService.InitializeAsync();
}
}
}
Remove this line
using static System.Net.Mime.MediaTypeNames;
And use import the using Xamarin.Forms;
After that you can use Application.Current.Properties["key"] = value;
Use using xamarin.forms namespace while you use Application.Current.Properties for storing data. Either you could use App.Current.Properties if you do not want to add xamarin.forms namespace in your cs file.
Here App refer your App class in App.xaml.cs which inherit from Xamarin.forms.Application. so you can use App.Current.Properties instead Application.Current.Properties.
Thank you.

Can't find neither UseLog4Net nor FromThisAssembly using Castle.Core

I'm trying to learn more about .Net Core and Castle dependency injection and inversion of control, but I just can't find neither UseLog4Net in LoggingFacility, while implementing my CompositionRoot, nor FromThisAssembly in Classes while implementing my installers. What am I doing wrong?
CompositionRoot.cs
using Castle.Facilities.Logging;
using Castle.Windsor;
namespace PitchulaBeerNBurger.POS.CrossCuttingConcerns.DependencyInjection
{
public class CompositionRoot
{
public virtual void ComposeApplication(IWindsorContainer container)
{
container.AddFacility<LoggingFacility>(f => f.UseLog4Net());
container.Install(
new Installers.CrossCuttingConcerns(),
new Installers.Persistence(),
new Installers.Domain(),
new Installers.Business()
);
}
}
}
DomainInstaller.css
using Castle.MicroKernel.Registration;
using Castle.MicroKernel.SubSystems.Configuration;
using Castle.Windsor;
namespace PitchulaBeerNBurger.POS.CrossCuttingConcerns.Installers
{
public class Domain : IWindsorInstaller
{
public void Install(IWindsorContainer container, IConfigurationStore store)
{
container.Register(Classes.FromThisAssembly()
.Where(type => type.Name.EndsWith("Factory"))
.LifestyleSingleton());
}
}
}
NuGet packages installed:
Castle.Core.4.3.1
Castle.Core-log4net.4.3.1
Castle.LoggingFacility

Configuring Ninject with Asp.Net MVC & Web Api

i have setup my project with Ninject IoC.
My project has regular Asp.Net MVC controllers and Web Api controllers. Now, Ninject works with Web Api but Ninject doesn't work with regular Asp.MVC controllers.
My regular MVC controller implementation;
public class GalleryController : BaseController
{
public GalleryController(IUow uow)
{
Uow = uow;
}
........
}
Error when using with regular controller
An error occurred when trying to create a controller of type 'Web.Controllers.HomeController'. Make sure that the controller has a parameterless public constructor.]
However, when i try the same code with Web Api, it works
public class GalleryController : BaseApiController
{
public GalleryController(IUow uow)
{
Uow = uow;
}
......
}
my interface which holds difference repositories (the factory pattern)
public interface IUow
{
// Save pending changes to the data store.
void Commit();
//Repositoryries
IRepository<Gallery> Gallery { get; }
IMenuRepository Menus { get; }
}
NinjectDependencyScope class;
public class NinjectDependencyScope : IDependencyScope
{
private IResolutionRoot resolver;
internal NinjectDependencyScope(IResolutionRoot resolver)
{
Contract.Assert(resolver != null);
this.resolver = resolver;
}
public void Dispose()
{
var disposable = resolver as IDisposable;
if (disposable != null)
disposable.Dispose();
resolver = null;
}
public object GetService(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
if (resolver == null)
throw new ObjectDisposedException("this", "This scope has already been disposed");
return resolver.GetAll(serviceType);
}
}
NinjectDependencyResolver class;
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver
{
private IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(kernel.BeginBlock());
}
}
Ninject configuration for Global.asax;
public class IocConfig
{
public static void RegisterIoc(HttpConfiguration config)
{
var kernel = new StandardKernel(); // Ninject IoC
//kernel.Load(Assembly.GetExecutingAssembly()); //only required for asp.net mvc (not for webapi)
// These registrations are "per instance request".
// See http://blog.bobcravens.com/2010/03/ninject-life-cycle-management-or-scoping/
kernel.Bind<RepositoryFactories>().To<RepositoryFactories>()
.InSingletonScope();
kernel.Bind<IRepositoryProvider>().To<RepositoryProvider>();
kernel.Bind<IUow>().To<Uow>();
// Tell WebApi how to use our Ninject IoC
config.DependencyResolver = new NinjectDependencyResolver(kernel);
}
}
Global.asax
protected void Application_Start()
{
// Tell WebApi to use our custom Ioc (Ninject)
IocConfig.RegisterIoc(GlobalConfiguration.Configuration);
FilterConfig.RegisterGlobalFilters(GlobalFilters.Filters);
RouteConfig.RegisterRoutes(RouteTable.Routes);
BundleConfig.RegisterBundles(BundleTable.Bundles);
GlobalConfig.CustomizeConfig(GlobalConfiguration.Configuration);
AreaRegistration.RegisterAllAreas();
}
I have written some gists to help configure Ninject with MVC and Web Api. Simply include the file(s):
https://gist.github.com/odytrice/5821087 (for MVC)
https://gist.github.com/odytrice/5842010 (for WebApi)
To add Bindings for concrete Types, Just put them in the Load() method of the MainModule. You can create as many modules as you like to keep bindings organized. but you'll also have to add them to the array that is returned in the Modules property.
Then Add to the Application_Start() method
NinjectContainer.RegisterModules(NinjectModules.Modules) (for MVC)
NinjectHttpContainer.RegisterModules(NinjectHttpModules.Modules) (for WebApi)
Note that you can use the same NinjectModules.Modules for both the MVC and WebApi registration. I just separated it for clearity
UPDATE: Remember to Remove NinjectWebCommon.cs from your project as it loads and bootstraps a new kernel at Runtime which unfortunately is only for MVC.
UPDATE: You can also use
NinjectContainer.RegisterAssembly() (for MVC)
NinjectHttpContainer.RegisterAssembly() (for WebApi)
This will scan your current assembly for all modules. This way you can put your modules anywhere in your project and it will be registered
With MVC 5 and Web API 2.2 I solved this problem by making sure I included the following NuGet packages:
Ninject.MVC5
Ninject.Web.WebApi.WebHost for Web API
This installed other Ninject dependencies and allowed me to RegisterServices through NinjectWebCommon.cs.
After searching a lot, it turns out there we can't use Ninject with web api and regular mvc. I mean, we have to configure the Repositories separately.
I then found a nice article which explains how you can use Ninject with asp.net mvc & web api: http://www.codeproject.com/Articles/412383/Dependency-Injection-in-asp-net-mvc4-and-webapi-us
And now, I don't get the error and it's working :D
Update 1:
Also try Writing a simple implementation of dependency injection in MVC 4 Web API with .NET Framework 4.5
Here is the simple solution that works fine for me:
In Visual studio, create new web application project named DemoApp and make sure you have selected Empty template with MVC and Web API references:
In Package manager console execute one by one:
Install-Package Ninject
Install-Package Ninject.MVC5
Add NinjectDependencyResolver.cs to IoC folder :
using Ninject;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http.Dependencies;
namespace DemoApp.IoC
{
public class NinjectDependencyResolver : IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return this;
}
public object GetService(Type serviceType)
{
return kernel.TryGet(serviceType);
}
public IEnumerable<object> GetServices(Type serviceType)
{
return kernel.GetAll(serviceType);
}
public void Dispose() { } //it is not necessary to implement any dispose logic here
}
}
Make the following changes in App_Start/NinjectWebCommon.cs :
Add these lines in CreateKernel method:
NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(ninjectResolver); //MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //Web API
Add your bindings in RegisterServices method like:
kernel.Bind< IHelloService>().To< HelloService>();
Now NinjectWebCommon.cs should look like:
[assembly: WebActivatorEx.PreApplicationStartMethod(typeof(DemoApp.App_Start.NinjectWebCommon), "Start")]
[assembly: WebActivatorEx.ApplicationShutdownMethodAttribute(typeof(DemoApp.App_Start.NinjectWebCommon), "Stop")]
namespace DemoApp.App_Start
{
using System;
using System.Web;
using Microsoft.Web.Infrastructure.DynamicModuleHelper;
using Ninject;
using Ninject.Web.Common;
using DemoApp.IoC;
using System.Web.Mvc;
using System.Web.Http;
using DemoApp.Config;
public static class NinjectWebCommon
{
private static readonly Bootstrapper bootstrapper = new Bootstrapper();
/// <summary>
/// Starts the application
/// </summary>
public static void Start()
{
DynamicModuleUtility.RegisterModule(typeof(OnePerRequestHttpModule));
DynamicModuleUtility.RegisterModule(typeof(NinjectHttpModule));
bootstrapper.Initialize(CreateKernel);
}
/// <summary>
/// Stops the application.
/// </summary>
public static void Stop()
{
bootstrapper.ShutDown();
}
/// <summary>
/// Creates the kernel that will manage your application.
/// </summary>
/// <returns>The created kernel.</returns>
private static IKernel CreateKernel()
{
var kernel = new StandardKernel();
try
{
kernel.Bind<Func<IKernel>>().ToMethod(ctx => () => new Bootstrapper().Kernel);
kernel.Bind<IHttpModule>().To<HttpApplicationInitializationHttpModule>();
RegisterServices(kernel);
NinjectDependencyResolver ninjectResolver = new NinjectDependencyResolver(kernel);
DependencyResolver.SetResolver(ninjectResolver); //MVC
GlobalConfiguration.Configuration.DependencyResolver = ninjectResolver; //Web API
return kernel;
}
catch
{
kernel.Dispose();
throw;
}
}
/// <summary>
/// Load your modules or register your services here!
/// </summary>
/// <param name="kernel">The kernel.</param>
private static void RegisterServices(IKernel kernel)
{
kernel.Bind<IHelloService>().To<HelloService>();
}
}
}
Just for the completeness of the example, add some Mvc and Api controllers, and code for IHelloService, HelloService :
HomeController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Mvc;
using DemoApp.Config;
namespace DemoApp.Controllers
{
public class HomeController : Controller
{
private IHelloService helloService;
public HomeController(IHelloService helloService)
{
this.helloService = helloService;
}
// GET: /Home/
public string Index()
{
return "home/index: " + helloService.GetMessage();
}
}
}
UserController.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using System.Web.Http;
using DemoApp.Config;
namespace DemoApp.Controllers
{
public class UserController : ApiController
{
private IHelloService helloService;
public UserController(IHelloService helloService)
{
this.helloService = helloService;
}
[HttpGet]
public string Data()
{
return "api/user/data: " + helloService.GetMessage();
}
}
}
IHelloService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
public interface IHelloService
{
string GetMessage();
}
}
HelloService.cs
using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
namespace DemoApp.Config
{
public class HelloService : IHelloService
{
public string GetMessage()
{
return "Hi";
}
}
}
The final structure should look like:
Now make some tests in browser. For me it was:
http://localhost:51156/home/index
http://localhost:51156/api/user/data
And that's it.
I think the issue is that you are not registering a ControllerFactory that uses Ninject to build the controllers (and resolve their dependencies), have you tried implementing your own ControllerFactory yet? See also here http://bubblogging.wordpress.com/2012/06/04/mvc-controller-factory-ninject/.
There is a more elegant solution for this by Nenad - it took me 3 extra hours because I first tried to implement the solutions here conflicting with existing infrastructure I had. It is in reply to another stack overflow question. I am duplicating that answer here just in case it helps others to save the time I lost.
There is a way to share same container between MVC and ASP.NET Web API.
You just need to implement both interfaces.
public class NinjectDependencyResolver : NinjectDependencyScope, IDependencyResolver, System.Web.Mvc.IDependencyResolver
{
private readonly IKernel kernel;
public NinjectDependencyResolver(IKernel kernel)
: base(kernel)
{
this.kernel = kernel;
}
public IDependencyScope BeginScope()
{
return new NinjectDependencyScope(this.kernel.BeginBlock());
}
}
Check this article for solution:
Simple Way to share Dependency Resolvers between MVC and Web API

Resources