I'm new to Xamarin and Prism, so forgive me if I'm missing something obvious. I am following the example of this project in GitHub. However, I am getting the following error when running my Android project.
System.InvalidOperationException: The current type, MyApp.Abstractions.IFacebookManager, is an interface and cannot be constructed. Are you missing a type mapping?
The error is occurring in EntryPage.xaml.g.cs in the LoadFromXaml() method.
[global::Xamarin.Forms.Xaml.XamlFilePathAttribute("Views\\EntryPage.xaml")]
public partial class EntryPage : global::Xamarin.Forms.ContentPage {
[global::System.CodeDom.Compiler.GeneratedCodeAttribute("Xamarin.Forms.Build.Tasks.XamlG", "2.0.0.0")]
private void InitializeComponent() {
// Exception thrown here!
global::Xamarin.Forms.Xaml.Extensions.LoadFromXaml(this, typeof(EntryPage));
}
}
This leads me to believe that I'm not using the IoC container properly, but I can't see what I'm doing differently from the example. The EntryPageViewModel's constructor takes IFacebookManager as a parameter and I understand that Unity should take care of this. I have a breakpoint on the constructor, but it's not being hit. This is a .NET Standard Xamarin solution. I would appreciate any help and guidance. Thank you!
Here's my App.xaml.cs
using MyApp.Abstractions;
using MyApp.Helpers;
using MyApp.Services;
using MyApp.ViewModels;
using MyApp.Views;
using Prism;
using Prism.Ioc;
using Prism.Unity;
using Xamarin.Forms;
namespace MyApp
{
public partial class App : PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer) { }
protected override void OnInitialized()
{
InitializeComponent();
ServiceResolver.Instance.Add<ICloudService, AzureCloudService>();
NavigationService.NavigateAsync("NavigationPage/EntryPage");
}
protected override void RegisterTypes(IContainerRegistry containerRegistry)
{
containerRegistry.RegisterForNavigation<NavigationPage>();
containerRegistry.RegisterForNavigation<EntryPage, EntryPageViewModel>();
}
}
}
Here's my MainActivity.cs
using Android.App;
using Android.Content.PM;
using Android.OS;
using MyApp.Droid.Services;
using MyApp.Abstractions;
using Android.Content;
using Xamarin.Facebook;
using Xamarin.Forms;
using Prism;
using Prism.Ioc;
namespace MyApp.Droid
{
[Activity(Label = "MyApp", Icon = "#drawable/icon", Theme = "#style/MainTheme", Name = "com.mydomain.myapp.MainActivity", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
ICallbackManager fbCallbackManager;
AndroidLoginProvider loginProvider;
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.Tabbar;
ToolbarResource = Resource.Layout.Toolbar;
base.OnCreate(bundle);
Microsoft.WindowsAzure.MobileServices.CurrentPlatform.Init();
global::Xamarin.Forms.Forms.Init(this, bundle);
DependencyService.Register<IFacebookManager, FacebookManager>();
LoadApplication(new App(new AndroidInitializer()));
}
protected override void OnActivityResult(int requestCode, Result resultCode, Intent data)
{
base.OnActivityResult(requestCode, resultCode, data);
var manager = DependencyService.Get<IFacebookManager>();
if (manager != null)
{
(manager as FacebookManager)._callbackManager.OnActivityResult(requestCode, (int)resultCode, data);
}
}
}
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
}
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IContainerRegistry containerRegistry)
{
}
}
You are mixing the Xamarin Forms Dependency Service with the one provided with Prism.Unity
Instead of calling DependencyService.Register<IFacebookManager, FacebookManager>();
You need to register it with the AndroidInitializer .
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IContainerRegistry container)
{
container.RegisterSingleton<IFacebookManager, FacebookManager>();
}
}
You can then always resolve a dependency manually by calling App.Container.Resolve inside OnActivityResult.
To complete the previous answer that helped me a lot to fix a similar issue:
with prism 7, you need to resolve a dependency via IContainerProvider as follow:
var container = (App.Current as Prism.Unity.PrismApplication).Container;
var manager = container.Resolve<IFacebookManager>();
In this case, Unity is used as the IoC "container"
I'm trying to implement .NET Core 2.2/SignalR 1.1.0.
In startup:
public void ConfigureServices(IServiceCollection services)
services.AddSignalR();
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
app.UseSignalR(routes =>
{
routes.MapHub<ChatHub>("/chatHub");
});
It works smoothly when I apply a one-to-one example.
But I need an architectural change.
My example:
public class ChatHub : Hub
{
ResponseHandler ResponseHandler { get; set; }
public ChatHub()
{
IHubCallerClients hubCallerClients = this.Clients;
ResponseHandler = new ResponseHandler(hubCallerClients);
}
public async Task SendMessage(string user, string message)
{
IHubCallerClients hubCallerClients = this.Clients;
await ResponseHandler.R();
}
}
If I tried to get this.Clients in the constructor it is coming with null data. But if I try to take it in the method, it comes full as expected.
I should get IHubCallerClients in the contructor so that I can forward it to another Response context.
Thanks advance!
OK. I solved the problem by
public class RequestHandler : Hub
{
ResponseHandler ResponseHandler { get; set; }
public RequestHandler(IHubContext<RequestHandler> hubContext)
{
ResponseHandler = new ResponseHandler(hubContext);
}
public async Task SendMessage(string user, string message)
{
await ResponseHandler.R();
}
}
Due to the nature of .net core, context comes to constructor as dependency.
"services.AddSignalR();" we're sure to add it to Scope.
"IHubContext hubContext" In this way, we can collect the contructured object.
People I need help I am in a new project in which I am implementing identity server 4 and I am trying to recover the previously created users with asp.Identity that I have in my database to be able to verify when I make an external login from identity server 4. Sorry my english.
My Startup.cs
public class Startup
{
public IConfiguration Configuration { get; }
public Startup(IConfiguration configuration)
{
Configuration = configuration;
}
public void ConfigureServices(IServiceCollection services)
{
#region --Identity ASP
services.AddDbContext<QGoodDbContext>(options => options.UseSqlServer(Configuration.GetConnectionString("DefaultConnection")),ServiceLifetime.Transient);
services.AddIdentity<ApplicationUser, ApplicationRole>()
.AddEntityFrameworkStores<QGoodDbContext>()
.AddDefaultTokenProviders();
#endregion
services.AddMvc();
services.AddScoped<UserManager<ApplicationUser>>();
services.AddScoped<SignInManager<ApplicationUser>>();
// configure identity server with in-memory stores, keys, clients and scopes
services.AddIdentityServer()
.AddDeveloperSigningCredential()
.AddInMemoryPersistedGrants()
.AddInMemoryIdentityResources(Config.GetIdentityResources())
.AddInMemoryApiResources(Config.GetApiResources())
.AddInMemoryClients(Config.GetClients());
//.AddAspNetIdentity<ApplicationUser>();
}
}
When I initialize my database I already have this error
public void Configure(IApplicationBuilder app, IHostingEnvironment env)
{
if (env.IsDevelopment())
{
app.UseDeveloperExceptionPage();
}
app.UseIdentityServer();
app.UseStaticFiles();
app.UseMvcWithDefaultRoute();
InitializeDatabase(app);
}
private void InitializeDatabase(IApplicationBuilder app)
{
using (var serviceScope = app.ApplicationServices.GetService<IServiceScopeFactory>().CreateScope())
{
//serviceScope.ServiceProvider.GetRequiredService<QGoodDbContext>().Database.Migrate();
var context = serviceScope.ServiceProvider.GetRequiredService<QGoodDbContext>();
}
}
In my AccountController i have exception when call await _userManager.FindByLoginAsync(provider, providerUserId);
public class AccountController : Controller
{
private readonly UserManager<ApplicationUser> _userManager;
private readonly SignInManager<ApplicationUser> _signInManager;
private readonly QGoodDbContext _context;
private readonly TestUserStore _users;
private readonly IIdentityServerInteractionService _interaction;
private readonly IClientStore _clientStore;
private readonly IAuthenticationSchemeProvider _schemeProvider;
private readonly IEventService _events;
public AccountController(
UserManager<ApplicationUser> userManager,
SignInManager<ApplicationUser> signInManager,
QGoodDbContext context,
IIdentityServerInteractionService interaction,
IClientStore clientStore,
IAuthenticationSchemeProvider schemeProvider,
IEventService events,
TestUserStore users = null)
{
// if the TestUserStore is not in DI, then we'll just use the global users collection
// this is where you would plug in your own custom identity management library (e.g. ASP.NET Identity)
_users = users ?? new TestUserStore(TestUsers.Users);
_userManager = userManager;
_signInManager = signInManager;
_context = context;
_interaction = interaction;
_clientStore = clientStore;
_schemeProvider = schemeProvider;
_events = events;
}
public async Task<IActionResult> ExternalLoginCallback()
{
try
{
// read external identity from the temporary cookie
var result = await HttpContext.AuthenticateAsync(IdentityServer4.IdentityServerConstants.ExternalCookieAuthenticationScheme);
if (result?.Succeeded != true)
{
throw new Exception("External authentication error");
}
// lookup our user and external provider info
var (userTest, provider, providerUserId, claims) = FindUserFromExternalProvider(result);
var user = await _userManager.FindByLoginAsync(provider, providerUserId);
}
}
}
Exception is:
Method not found: 'System.Reflection.MethodInfo Microsoft.EntityFrameworkCore.Query.EntityQueryModelVisitor.get_SelectAsyncMethod()'
Hi can you show your packages install ? I have same problem too when i use EFCore. I solved this when I installed package
Microsoft.EntityFrameworkCore.Relational >= 2.2.0
There are several variations of this problem that exhibit the behavior of MissingMethodException, NotImplemementedException or MissingFieldException.
It appears these are caused by conflicting versions within the Microsoft.EntityFrameworkCore namespace. For instance, this error can be caused by referencing Microsoft.EntityFrameworkCore.InMemory 2.2.0 and Microsoft.EntityFrameworkCore.Relational 2.1.4 in the same assembly.
The solution is to harmonize the versions of nuget package references so that they do not internally reference different versions of EF Core components.
I don't know what was the real problem but after downgrade Microsoft.EntityFrameworkCore.Tools to version 2.1.4 and updgrade again to last version problem gone.
I had this problem when I implemented my project on AWS Lambda on an .Net Core 2.2 build- I did two things to fix it:
Include Microsoft.EntityFrameworkCore.Relational package from NuGet.
Included the MySql.Data.EntityFrameworkCore NuGet package in the top level project - for some reason it get included in the zip file that went up to AWS, even though it was a dependency in a sub project.
I suspect it was the second action that fixed it.
I am trying to create a Prism module in a Xamarin Forms application. My module contains platform specific code and a view model that takes in an interface for that. For example:
ThingModule (PCL)
ThingModule
+ Initialize()
IThing
ThingView
ThingViewModel(IThing thing)
ThingModule.Droid (Android)
AndroidThingImplementation : IThing
ThingModule.iOS (iOS)
iOSThingImplementation : IThing
I can register the views for navigation easily enough in the module's Initialize method, but how can I register the platform specific implementations in the module (rather than in the app)?
You don't register platform specifics in the module. You register platform specific in the actual platform specific projects. Your module just has to have reference to the interface, and that's it. You can use the IPlatformInitializer to do this. See a sample here:
Android:
https://github.com/PrismLibrary/Prism/blob/master/Sandbox/Xamarin/HelloWorld/HelloWorld/HelloWorld.Droid/MainActivity.cs#L28
[Activity(Label = "HelloWorld", Icon = "#drawable/icon", MainLauncher = true, ConfigurationChanges = ConfigChanges.ScreenSize | ConfigChanges.Orientation)]
public class MainActivity : global::Xamarin.Forms.Platform.Android.FormsAppCompatActivity
{
protected override void OnCreate(Bundle bundle)
{
TabLayoutResource = Resource.Layout.tabs;
ToolbarResource = Resource.Layout.toolbar;
base.OnCreate(bundle);
global::Xamarin.Forms.Forms.Init(this, bundle);
LoadApplication(new App(new AndroidInitializer()));
}
}
public class AndroidInitializer : IPlatformInitializer
{
public void RegisterTypes(IUnityContainer container)
{
}
}
XF Project:
https://github.com/PrismLibrary/Prism/blob/master/Sandbox/Xamarin/HelloWorld/HelloWorld/HelloWorld/App.cs#L15
public class App : PrismApplication
{
public App(IPlatformInitializer initializer = null) : base(initializer) { }
...
}
I’m creating my first Firebase App. One of its requirements is that it run when the network is not available. The Firebase guide states:
Enabling disk persistence allows our app to also keep all of its state even after an app restart. We can enable disk persistence with just one line of code.
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
With disk persistence enabled, our synced data and writes will be persisted to disk across app restarts and our app should work seamlessly in offline situations.
Another requirement is to use Google Sign In. So in my MainActivity I check if the User is signed in, if not, I launch the SignInActivity. (The SignInActivity is from the Firebase examples.) The SignInActivity works, the user gets logged in, and MainActivity is launched for a second time. Now my app crashes on the code line FirebaseDatabase.getInstance().setPersistenceEnabled(true); with the following message:
Calls to setPersistenceEnabled() must be made before any other usage of FirebaseDatabase instance.
Now if I restart my app, the User is signed in, the SignInActivity is not launched, my app runs fine.
Any suggestions of how I avoid this crash after the User signs in?
As I was posting this question, I received a suggestion to relocate FirebaseDatabase.getInstance().setPersistenceEnabled(true);
to my “Application class”. I get exactly the same result … SignInActivity starts, completes, and I get a crash on the setPersistenceEnabled.
Below is my MainActivity onCreate:
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// Calls to setPersistenceEnabled() must be made before any other usage of FirebaseDatabase instance.
// Crash here upon returning from SignInActivity.
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
mFirebaseDbReference = FirebaseDatabase.getInstance().getReference();
// Initialize Firebase Auth
mFirebaseAuth = FirebaseAuth.getInstance();
mFirebaseUser = mFirebaseAuth.getCurrentUser();
if (mFirebaseUser == null) {
// Not signed in, launch the Sign In activity
Timber.tag("MainActivity").i("onCreate(): User not signed in, launching SignInActivity");
startActivity(new Intent(this, SignInActivity.class));
finish();
} else {
mUsername = mFirebaseUser.getDisplayName();
Timber.tag("MainActivity").i("onCreate(): User \"%s\" signed in.", mUsername);
if (mFirebaseUser.getPhotoUrl() != null) {
mPhotoUrl = mFirebaseUser.getPhotoUrl().toString();
}
}
A FirebaseApp is initialized by a ContentProvider so it is not initialized at the time onCreate() is called.
Get your FirebaseDatabase like this:
public class Utils {
private static FirebaseDatabase mDatabase;
public static FirebaseDatabase getDatabase() {
if (mDatabase == null) {
mDatabase = FirebaseDatabase.getInstance();
mDatabase.setPersistenceEnabled(true);
}
return mDatabase;
}
}
Then call Utils.getDatabase() from any activity you want.
Read more in this article
I fixed this exception by using setPersistenceEnabled(true) in my Application class.
public class MApplication extends Application {
#Override
public void onCreate() {
super.onCreate();
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
}
In AndroidManifest.xml, set the application name as MApplication:
<application
android:name=".MApplication"
... />
I was facing a similar problem and using a static variable seemed to resolve the issue for me. So at first my code looked something like this
#Override
protected void onCreate(Bundle savedInstanceState) {
//..code
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
FirebaseDatabase database = FirebaseDatabase.getInstance();
//..code
}
and now it looks more like
static boolean calledAlready = false;
#Override
protected void onCreate(Bundle savedInstanceState) {
//..code
if (!calledAlready)
{
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
calledAlready = true;
}
FirebaseDatabase database = FirebaseDatabase.getInstance();
//..code
}
Hope it helps!
I bit late but today i got this issue, I solved by adding
static {
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
to my Activity
To me, it is easier to be handled by creating a separate class for Firebase. This is because Firebase has its own instance and if you are using it in more than one activity, there's the possibility for it to crash if you call setPersistenceEnabled again in another activity.
Another good thing is that you can pass your context or parameters into the FirebaseHandler constructor if required. Or if you have fixed location in the database, they can be called easy without the .child("location") boilerplate.
Example:
public class FirebaseHandler {
// parameters
private Context context;
private String userKey;
private DatabaseReference databaseReference;
private static boolean isPersistenceEnabled = false;
private static String fixedLocationA = "locationA";
private static String fixedLocationB = "locationB";
public FirebaseHandler(Context context, String userKey) {
this.context = context; // context can be used to call PreferenceManager etc.
this.userKey = userKey;
if (!isPersistenceEnabled) {
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
isPersistenceEnabled = true;
}
databaseReference = FirebaseDatabase.getInstance().getReference().child(userKey);
}
public DatabaseReference getRefA() {
return databaseReference.child(fixedLocationA);
}
public DatabaseReference getRefB() {
return databaseReference.child(fixedLocationB);
}
}
This can then be called in any Activity as below.
public class MyActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
// get instance
FirebaseHandler firebaseHandler = new FirebaseHander(this, "userKey");
// to set value
firebaseHandler.getRefA().setValue("value");
// to set listener
firebaseHandler.getRefB().addValueEventListener(new ValueEventListener() {
#Override
public void onDataChange(DataSnapshot dataSnapshot) {
// TODO here....
// also, can remove listener if required
if (certain condition) {
firebaseHandler.getRefB().removeEventListener(this);
}
}
}
}
}
I'm facing some problem too, but this is my temporary solution for my app.
Create BaseActivity extends AppcompatActivity and override onCreate, put setPersistenceEnabled there.
public class BaseActivity extends AppCompatActivity {
private static String TAG = "BaseActivity";
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
Log.d(TAG,FirebaseDatabase.getInstance().toString());
}catch (Exception e){
Log.w(TAG,"SetPresistenceEnabled:Fail"+FirebaseDatabase.getInstance().toString());
e.printStackTrace();
}
}
}
And change MainActivity to extend BaseActivity
public class MainActivity extends BaseActivity
EDIT: Follow #imakeApps answer
public class BaseActivity extends AppCompatActivity {
private static String TAG = "BaseActivity";
static boolean isInitialized = false;
#Override
protected void onCreate(#Nullable Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
try{
if(!isInitialized){
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
isInitialized = true;
}else {
Log.d(TAG,"Already Initialized");
}
}catch (Exception e){
e.printStackTrace();
}
}
}
Solved it by making the Firebase reference a static class field like this:
public class MainActivity extends AppCompatActivity
private static FirebaseDatabase fbDatabase;
#Override
protected void onCreate(Bundle savedInstanceState) {
if(fbDatabase == null) {
fbDatabase = FirebaseDatabase.getInstance();
fbDatabase.setPersistenceEnabled(true);
}
It's no problem to create new Firebase references (without setPersistenceEnabled(true)) in other activities too.
If you don't like the static fields, this did the trick for me:
if (FirebaseApp.getApps(context).isEmpty()) {
FirebaseApp.initializeApp(context);
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
This can be caused be more that one process initializing twice firebase or Multidex apps. For more info see this: https://github.com/firebase/quickstart-android/issues/15
I wouldn't recommend using Application to store the data because like its written in CodePath
There is always data and information that is needed in many places within your app. This might be a session token, the result of an expensive computation, etc. It might be tempting to use the application instance in order to avoid the overhead of passing objects between activities or keeping those in persistent storage.
However, you should never store mutable instance data inside the Application object because if you assume that your data will stay there, your application will inevitably crash at some point with a NullPointerException. The application object is not guaranteed to stay in memory forever, it will get killed. Contrary to popular belief, the app won’t be restarted from scratch. Android will create a new Application object and start the activity where the user was before to give the illusion that the application was never killed in the first place.
Thats the reason I would recommend using a Singleton like this:
public class DataBaseUtil {
private static FirebaseDatabase mDatabase;
public static FirebaseDatabase getDatabase() {
if (mDatabase == null) {
mDatabase = FirebaseDatabase.getInstance();
mDatabase.setPersistenceEnabled(true);
}
return mDatabase;
}}
just use it in your code then like
private FirebaseDatabase fdb = DataBaseUtil.getDatabase();
Create a class called Util.java
and add following code
public class Util {
private static FirebaseDatabase mData;
public static FirebaseDatabase getDatabase() {
if (mData == null) {
mData = FirebaseDatabase.getInstance();
mData.setPersistenceEnabled(true);
}
return mData;
}
}
Now replace FirebaseDatabase.getIntance() with Util.getDatabase() every time in each activity. Calling just once will get the error!
I was facing same issue. i changed code as below.
BEFORE(Causing Crash)
var rootRef = FIRDatabase.database().reference()
override func viewDidLoad() {
super.viewDidLoad()
FIRDatabase.database().persistenceEnabled = true
}
AFTER (Resolved Crash)
var rootRef:FIRDatabaseReference!
override func viewDidLoad() {
super.viewDidLoad()
FIRDatabase.database().persistenceEnabled = true
rootRef = FIRDatabase.database().reference()
}
In Menifest
android:name=".AppName
Create java Class that extends Application
public class AppName extends Application {
#Override
public void onCreate() {
super.onCreate();
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
Make sure that .setpersistenceenabled(true) is not happening twice, while sign in by Google in your case, second care setPersistenceEnabled(true) is must be called before any instance of firebase called this resolve my issue.
For Kotlin Try this:
class DatabaseUtil {
companion object {
private val firebaseDatabase: FirebaseDatabase = FirebaseDatabase.getInstance()
init {
firebaseDatabase.setPersistenceEnabled(true)
}
fun getDatabase() : FirebaseDatabase {
return firebaseDatabase
}
}
}
Simply move you code in ExampleFragment.class from onCreateView method to onCreate method:
#Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
}
#Override
public View onCreateView(#NonNull LayoutInflater inflater, #Nullable ViewGroup container,
#Nullable Bundle savedInstanceState) {
....
// Inflate the layout for this fragment
View view = inflater.inflate(R.layout.fragment_home, container, false);
The error message describes the problem:
Calls to setPersistenceEnabled() must be made before any other usage
of FirebaseDatabase instance.
The fix to this problem is described into the documentation: As in SDK 2.x, persistence of the disk must be enabled before other calls to the database are made.
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
https://firebase.google.com/support/guides/firebase-android
You can use:
FirebaseDatabase.getInstance().setPersistenceEnabled(true);
before using FirebaseDatabase.getInstance().getReference();