You must add a reference to assembly 'UnityEngine.AndroidJNIModule - c#

I am very new at Unity and I tried to integrate Huawei Mobile Service plugin and I got this error.
The type 'AndroidJavaObject' is defined in an assembly that is not referenced. You must add a reference to assembly 'UnityEngine.AndroidJNIModule
Is there anyone who encounter this problem before?
Thank you.
Edit
This code is belong to plugin.
using HuaweiMobileServices.Id;
using HuaweiMobileServices.Utils;
using System;
using UnityEngine;
namespace HmsPlugin
{
public class AccountManager : MonoBehaviour
{
public static AccountManager GetInstance(string name = "AccountManager") => GameObject.Find(name).GetComponent<AccountManager>();
private static HuaweiIdAuthService DefaultAuthService
{
get
{
Debug.Log("[HMS]: GET AUTH");
var authParams = new HuaweiIdAuthParamsHelper(HuaweiIdAuthParams.DEFAULT_AUTH_REQUEST_PARAM).SetIdToken().CreateParams();
Debug.Log("[HMS]: AUTHPARAMS AUTHSERVICE" + authParams);
var result = HuaweiIdAuthManager.GetService(authParams);
Debug.Log("[HMS]: RESULT AUTHSERVICE"+ result);
return result;
}
}
public AuthHuaweiId HuaweiId { get; private set; }
public Action<AuthHuaweiId> OnSignInSuccess { get; set; }
public Action<HMSException> OnSignInFailed { get; set; }
private HuaweiIdAuthService authService;
// Start is called before the first frame update
void Awake()
{
Debug.Log("[HMS]: AWAKE AUTHSERVICE");
authService = DefaultAuthService;
}
public void SignIn()
{
Debug.Log("[HMS]: Sign in " + authService);
authService.StartSignIn((authId) =>
{
HuaweiId = authId;
OnSignInSuccess?.Invoke(authId);
}, (error) =>
{
HuaweiId = null;
OnSignInFailed?.Invoke(error);
});
}
public void SignOut()
{
authService.SignOut();
HuaweiId = null;
}
}
}
Picture of the problem is here.

The problem is about my unity. I had no AndroidJNI module so I got this error. Finally I uninstall current version then install new version of Unity and problem is solved. In the new version AndroidJNI module is came automatically.

Related

Unity Container resolve calling same parameterized constructor twice

I'm using a unity container and I'm trying to resolve by passing the object to the parameterized constructor, I noticed the same constructor is called twice, the first time it takes appropriate values, and not sure why it is calling again and it overrides with a blank object, can someone help me what is happening over here, not able to solve it.
//////////////////////////////////////////////////////////////////////
if (container == null)
{
container = new UnityContainer().AddExtension(new Diagnostic());
container.RegisterType<ISubscribeService,OOrderProc.Common.SubscribeService.SubscribeService>();
container.RegisterType<IBaseOrderProcessing, BaseSubscribe>("Subscribe");
}
SubscribeDetails m = new SubscribeDetails();
m.SubscribeType = SubscribeType.ACTIVATE;
m.SubscribeName = "TEST";
var b = container.Resolve<IBaseOrderProcessing>("Subscribe",new DependencyOverride<BaseSubscribe>(new OOrderProc.Common.SubscribeService.SubscribeService(m)));
//////////////////////////////////////////////////////////////////////
public interface IBaseOrderProcessing
{
void ProcessOrder();
}
public interface ISubscribeService
{
SubscribeType SubscribeType { get; set; }
void ActivateSubscribe();
void UpgradeSubscribe();
}
// Strategy Pattern 1 => Subscribe is one of the "if" condition
public class BaseSubscribe : IBaseOrderProcessing
{
private ISubscribeService _SubscribeService = null;
public BaseSubscribe(ISubscribeService SubscribeService)
{
_SubscribeService = SubscribeService;
}
public void ProcessOrder()
{
if (_SubscribeService.SubscribeType == SubscribeType.ACTIVATE)
_SubscribeService.ActivateSubscription();
if (_SubscribeService.SubscribeType == SubscribeType.UPGRADE)
_SubscribeService.UpgradeSubscription();
}
}
// Writing another class to simplify is correct ?????
public class SubscribeService : ISubscribeService
{
private SubscribeDetails _Subscribedetails = null;
public SubscribeType SubscribeType { get; set; }
public SubscribeService(SubscribeDetails Subscribedetails)
{
_Subscribedetails = Subscribedetails;
SubscribeType = Subscribedetails.SubscribeType;
}
public void ActivateSubscription()
{
// Code to save the Subscribe details in the database
Console.WriteLine($"\n\nSubscribe {_Subscribedetails.SubscribeId} for {_Subscribedetails.SubscribeName} activated for order Id: {_Subscribedetails.OrderId}" +
$" from {_Subscribedetails.SubscribeStartDate} to {_Subscribedetails.SubscribeEndDate}");
}
public void UpgradeSubscription()
{
// Code to upgrade the Subscribe details in the database
Console.WriteLine($"\n\nSubscribe {_Subscribedetails.SubscribeId} for {_Subscribedetails.SubscribeName} upgraded for order Id: {_Subscribedetails.OrderId}" +
$" from {_Subscribedetails.SubscribeStartDate} to {_Subscribedetails.SubscribeEndDate}");
}
}
I resolved using below code:
container.RegisterType<IBaseOrderProcessing, BaseSubscribe>("Subscribe", new InjectionConstructor(new OOrderProc.Common.SubscribeService.SubscribeService((SubscribeDetails)obj)));
return container.Resolve<IBaseOrderProcessing>("Subscribe");

The type or namespace name could not be found with .NET Core Fakes and VS 2019 Preview 6.9.0 Preview 2.0

Update 2
I fixed the problem in Update 1, but the similar code below doesn't work, and has the same error.
The sample is from https://learn.microsoft.com/en-us/visualstudio/test/isolating-code-under-test-with-microsoft-fakes?view=vs-2019#get-started-with-shims
Target code
public class DateShimDemo
{
public int GetTheCurrentYear()
{
return DateTime.Now.Year;
}
}
Test code:
[TestClass]
public class DateShimDemoTest
{
[TestMethod]
public void TestCurrentYear()
{
int fixedYear = 2000;
// Shims can be used only in a ShimsContext:
using (ShimsContext.Create())
{
// Arrange:
// Shim DateTime.Now to return a fixed date:
System.Fakes.ShimDateTime.NowGet
//The type or namespace name 'Fakes' does not exist in the namespace 'System'
= () =>
{ return new DateTime(fixedYear, 1, 1); };
// Instantiate the component under test:
var componentUnderTest = new DateShimDemo();
// Act:
int year = componentUnderTest.GetTheCurrentYear();
// Assert:
// This will always be true if the component is working:
Assert.AreEqual(fixedYear, year);
}
}
}
Update 1
I followed the sample below,
https://medium.com/#ckellywilson/visual-studio-2019-and-net-core-fakes-fea47caccdc8
Target code
public class SampleUserSecurity
{
public SampleUserSecurity()
{
}
public SampleUserSecurity(string domain, string username, string password)
{
this.UserPrincipal = new UserPrincipal(new PrincipalContext(ContextType.Domain, domain, username, password));
}
public UserPrincipal UserPrincipal { get; set; }
public bool IsAccountLocked()
{
return this.UserPrincipal.IsAccountLockedOut();
}
}
Test code:
[TestClass]
public class SampleUserSecurityTests
{
[TestMethod]
public void Test1()
{
using (ShimsContext.Create())
{
var target = new SampleUserSecurity();
var shimUserPrincipal = new ShimUserPrincipal(); //error here
var shimAuthtenticatedPrincipal = new ShimAuthenticablePrincipal(shimUserPrincipal) { IsAccountLockedOut = () => false };
target.UserPrincipal = shimUserPrincipal;
bool isLocked = false;
bool testIsLocked = target.IsAccountLocked();
Assert.Equal(isLocked, testIsLocked);
}
}
}
But an error below occurred
Error CS0246 The type or namespace name 'ShimUserPrincipal' could not
be found (are you missing a using directive or an assembly reference?)
Any idea?
Refs
https://learn.microsoft.com/en-us/visualstudio/test/isolating-code-under-test-with-microsoft-fakes?view=vs-2019
Update
Thanks #magicandre1981 for pointing it out.
The tutorials you follow are for .net framework. For .net core you have to select System.Runtime (not System) and select "Add Fakes Assembly"
Check the page APIsof.net which assembly includes a class in .net core.

MEF ImportCardinalityMismatchException

System.ComponentModel.Composition.ImportCardinalityMismatchException
'No exports were found that match the constraint: ContractName IntroToMEF.DigitalMonitor
RequiredTypeIdentity IntroToMEF.IMonitor'
'
My types are correct. I am able to Get exported value if I have only one instance inheriting from IMonitor. Whenever I need to use contract name I get an error. I am out of ideas.
Clearing Visual Studio Cache does not work.
[Export(typeof(IMonitor))]
public class DigitalMonitor : IMonitor
{
public void start()
{
Console.WriteLine("Digital Monitor: Started monitoring");
}
}
internal class HostMefInApp
{
[Import]
public ILogger logger { get; set; }
[Import]
public IMonitor monitor { get; set; }
private void ComposeMultiple()
{
Console.WriteLine("DEBUG:" + GetType().Assembly);
var assemblyCatalog = new AssemblyCatalog(GetType().Assembly);
var container = new CompositionContainer(assemblyCatalog);
// var contractName = AttributedModelServices.GetContractName(typeof(FileLogger));
try
{
var instancesOfFileLogger = container.GetExports<ILogger>(); //"IntroToMEF.FileLogger"
}
catch (ImportCardinalityMismatchException ex)
{
Console.WriteLine(ex);
}
CompositionBatch batch = new CompositionBatch();
batch.AddPart(AttributedModelServices.CreatePart(new FileLogger()));
batch.AddPart(AttributedModelServices.CreatePart(new DigitalMonitor()));
batch.AddPart(AttributedModelServices.CreatePart(new AnalogMonitor()));
container.Compose(batch);
var digitalMonitorContractName = AttributedModelServices.GetContractName(typeof(DigitalMonitor));
var currentLogger = container.GetExportedValue<ILogger>();
var digitalMonitor = container.GetExportedValue<IMonitor>(digitalMonitorContractName);
logger = currentLogger;
monitor = digitalMonitor;
}
I think that you should:
[Export(typeof(IMonitor))]
[Export(typeof(DigitalMonitor))]
public class DigitalMonitor : IMonitor
{
public void start()
{
Console.WriteLine("Digital Monitor: Started monitoring");
}
}
meaning, export DigitalMonitor as IMonitor and DigitalMonitor. This will give you possibility to import it using both ways. Then of course your code will work with:
var digitalMonitor = container.GetExportedValue<DigitalMonitor>();

Using Moq with NUnit in C#

I am building a simple Airport program where planes can only take off / land if the weather is sunny and not stormy. This depends on the Weather class (which randomises the weather between sunny and stormy). However, for my tests, I want to mock the weather so I can test for all cases.
Here is my Weather.cs:
using System;
namespace ClassNameWeather
{
public class Weather
{
public Weather()
{
}
public string Forecast()
{
Random random = new Random();
var weather = random.Next(1, 11);
if (weather == 1 || weather == 2)
{
return "stormy";
}
else
{
return "sunny";
}
}
}
}
Here is my Airport.cs:
using System;
using System.Collections.Generic;
using ClassNamePlane;
using ClassNameWeather;
namespace ClassNameAirport
{
public class Airport
{
private string _AirportName { get; set; }
public List<Plane> planes;
private Weather _weather = new Weather();
public Airport(string _airportName, Weather weather)
{
planes = new List<Plane>();
_AirportName = _airportName;
}
public void Land(Plane plane)
{
if (_weather.Forecast() != "stormy")
{
planes.Add(plane);
Console.WriteLine($"{ plane.Name } has landed at {_AirportName}");
}
else
{
throw new Exception("It's too stormy to land");
}
}
public void TakeOff(Plane plane)
{
if (_weather.Forecast() != "stormy")
{
planes.Remove(plane);
Console.WriteLine($"{ plane.Name } has departed from {_AirportName}");
}
else
{
throw new Exception("It's too stormy to take off");
}
}
public int GetPlaneCount()
{
Console.WriteLine($"Number of planes at {_AirportName}: {planes.Count}");
return planes.Count;
}
public void GetPlaneNames()
{
planes.ForEach(plane => Console.WriteLine((plane as Plane).Name));
}
public List<Plane> GetPlaneList()
{
return planes;
}
}
}
And here is the test that I'm trying to use the mock in:
using NUnit.Framework;
using ClassNameAirport;
using ClassNamePlane;
using ClassNameWeather;
using Moq;
namespace AirportTest
{
public class AirportTest
{
Airport airport = new Airport("TestAirport", weather);
Plane plane = new Plane("TestPlane");
[Test]
public void PlaneCanLand()
{
var weather = new Mock<Weather>();
weather.Setup(x => x.Forecast()).Returns("sunny");
airport.Land(plane);
Assert.IsTrue(airport.planes.Contains(plane));
}
public void PlaneCanTakeOff()
{
airport.Land(plane);
airport.TakeOff(plane);
Assert.IsFalse(airport.planes.Contains(plane));
}
}
}
This line: Airport airport = new Airport("TestAirport", weather); is not working, saying the name weather does not exist.
Can anyone help me to make sure I am using Moq correctly? I'm new to C# and any advice is much appreciated.
Thank you!
UPDATE
I have fixed this, but now receive the following error:
System.NotSupportedException : Unsupported expression: x => x.Forecast()
Non-overridable members (here: Weather.Forecast) may not be used in setup / verification expressions.
Does anyone know how to fix this please?
You can introduce interface IWeather like
public interface IWeather
{
string Forecast();
}
Than implement it in Weather class. Pass IWeather reference to AirPort class and setup a mock for that.
var weather = new Mock<IWeather>();
weather.Setup(x => x.Forecast()).Returns("sunny");
...
var airport = new Airport("TestAirport", weather.Object)
And do not initialize it in Airport class directly private Weather _weather = new Weather(); (your constructor argument is not used), do like this
public class Airport
{
private string _AirportName { get; set; }
public List<Plane> planes;
private readonly IWeather _weather;
public Airport(string _airportName, IWeather weather)
{
planes = new List<Plane>();
_weather = weather;
}
...
}
You have not declared the variable weather. I suggest that you create an Initialize method and attribute it with TestInitialze
[TestInitialize]
public void TestInitialize()
{
var weather = new Mock<Weather>();
var airport = new Airport("TestAirport", weather)
}

How to get the app version from ContentPage?

I tried this: iPhone MonoTouch - Get Version of Bundle
NSBundle.MainBundle.ObjectForInfoDictionary("CFBundleVersion").ToString();
But this didn't work. As NSBundle can't be found.
How can I get the app version (iOS and Android) from ContentPage?
The code which i ended up with (thanks to Steven Thewissen):
PCL (shared code)
using System;
namespace MyApp.Interfaces
{
public interface IApplicationVersion
{
string ApplicationsPublicVersion { get; set; }
string ApplicationsPrivateVersion { get; set; }
}
}
Android
using System;
using MyApp.Droid.Helpers;
using MyApp.Interfaces;
using Xamarin.Forms;
[assembly: Dependency(typeof(ApplicationVersion))]
namespace MyApp.Droid.Helpers
{
public class ApplicationVersion : IApplicationVersion
{
public string ApplicationsPublicVersion { get; set; }
public string ApplicationsPrivateVersion { get; set; }
public ApplicationVersion()
{
var context = Android.App.Application.Context;
var info = context.PackageManager.GetPackageInfo(context.PackageName, 0);
ApplicationsPublicVersion = info.VersionName;
ApplicationsPrivateVersion = info.VersionCode.ToString();
}
}
}
iOS
using System;
using MyApp.Interfaces;
using MyApp.iOS.Helpers;
using Foundation;
using Xamarin.Forms;
[assembly: Dependency(typeof(ApplicationVersion))]
namespace MyApp.iOS.Helpers
{
public class ApplicationVersion : IApplicationVersion
{
public string ApplicationsPublicVersion { get; set; }
public string ApplicationsPrivateVersion { get; set; }
public ApplicationVersion()
{
ApplicationsPublicVersion = NSBundle.MainBundle.InfoDictionary[new NSString("CFBundleShortVersionString")].ToString();
ApplicationsPrivateVersion = NSBundle.MainBundle.InfoDictionary[new NSString("CFBundleVersion")].ToString();
}
}
}
You can do this by implementing a Dependency Service. First you define an interface in your shared code:
namespace MyApp
{
public interface IAppVersionProvider
{
string AppVersion { get; }
}
}
In each platform project you then implement the interface.
iOS
[assembly: Dependency(typeof(AppVersionProvider))]
namespace MyApp.iOS
{
public class AppVersionProvider : IAppVersionProvider
{
public string AppVersion => NSBundle.MainBundle.InfoDictionary[new NSString("CFBundleVersion")].ToString();
}
}
Android
[assembly: Dependency(typeof(AppVersionProvider))]
namespace MyApp.Droid
{
public class AppVersionProvider : IAppVersionProvider
{
public string AppVersion
{
get
{
var context = Android.App.Application.Context;
var info = context.PackageManager.GetPackageInfo(context.PackageName, 0);
return $"{info.VersionName}.{info.VersionCode.ToString()}";
}
}
}
}
You can then retrieve the version number from shared code through:
var version = DependencyService.Get<IAppVersionProvider>();
var versionString = version.AppVersion;
If you don't want to use dependency services, you can just use the class VersionTracking.
The property VersionTracking.CurrentVersion will give you the Version you can set in your Android properties and your iOS info.plist.
This class is provided by Xamarin.Essentials and can give you a lot of informations. Please, check the documentation here for more informations.
Edit: listed incorrect nuget package, changes made below.
You should in theory be able to use something like the below inside the OnStart(); method of your App.cs in your forms project.
Context context = this.ApplicationContext;
SupportFunctions.Version = context.PackageManager.GetPackageInfo(context.PackageName, 0).VersionName;
However we use a plugin created by Mark Trinder called "Xam.Plugin.Version" which can be found on nuget1 and on GitHub2. Once it's installed into your forms & native projects it's simply called as so:
using Version.Plugin;
private void SomeMethod()
{
MyLabel.Text = CrossVersion.Current.Version;
}
1 nuget package Here
2 Github Here :

Categories

Resources