Xamarin C# cannot convert c# class to Android.content.context - c#

i'm trying to test the DependencyService of my app by displaying an alert dialog from an android project when i press a button i created in the share code project.
When i try to set the Context property in the 'AlertDialog.Builder' by entering 'this' in the parenthesis i get this error: "Cannot convert from 'CallDiverter2.Droid.CallDiverter_Android' to 'Android.Content.Context'.
Also the namespace is decorated with: '[assembly: Dependency(typeof(CallDiverter_Android))]' if its matter.
this is the function in the android project i want to call using the DependecyService:
public class CallDiverter_Android : ICallDiverter
{
public void DivertCall(string callForwardString)
{
//Divert call code
//String callForwardString = "**21*1234567890#";
//Intent callIntent = new Intent(Intent.ActionDial); // ACTION_CALL
//Android.Net.Uri uri = Android.Net.Uri.Parse(callForwardString);
//callIntent.SetData(uri);
//Android.App.Application.Context.StartActivity(callIntent);
AlertDialog.Builder dialog = new AlertDialog.Builder(this);
AlertDialog alert = dialog.Create();
alert.SetTitle("Title");
alert.SetMessage("Simple Alert");
alert.SetButton("OK", (s, ev) =>
{
alert.SetMessage("This is an alert message");
});
alert.Show();
}
public void StopCallDiverting()
{
//Stop the call diverting action
}
}
How should i fix this so i can successfully test the dependencyService?

If you have a single activity application you could probably just get away with passing in
Android.App.Application.Context
Eg
AlertDialog.Builder dialog = new AlertDialog.Builder(Android.App.Application.Context);
However to get the current Activity Context in a Multiple Activity Application, then you will need to keep track of it
See this answer for how to keep track of the current context
https://stackoverflow.com/a/47363378/1612975

There is a trick in xamarin to do so.
and most people also consider it very handy approach that is
create a static property of your MainActivity Class inside it (Singleton approach)
internal static MainActivity Instance { get; private set; }
Assign this Instance object value at the end of the construct of MainActivity like this
Instance = this;
Now use it like this to get context where ever you need
AlertDialog.Builder dialog = new AlertDialog.Builder(MainActivity.Instance);
This works well because most of the xamarin forms app have only one activity i.e. MainActivity

this does not work, because your class does not inherit from the Activity/Context class. Therefore this cannot be converted to Android.Content.Context
Just use Android.App.Application.Context to get the current Android Context.

I just had this error and fixed it.
This question is pretty old now but I put my insight for any person meeting the issue.
It turns out it did not like me to put my classes to work with SQLite into the AppName.Android.Persistance namespace instead of AppName.Droid.Persistance.
I just put Droid back and the error has gone.

Related

"(object name) does not exist in the current context" when the item is clearly in scope?

I am building a Blazor serverside application and I've run into what seems to be a trivial problem, but I can't figure out what's wrong. I have a class called TestMonitorDUT.cs in my ViewModels folder, and a page called TestMonitor.razor. In the razor page, I have the following lines where I simply make a new TestMonitorDUT and try to call a member function:
#code {
TestMonitorDUT DUT = new TestMonitorDUT("1");
DUT.PopulateDictionaries();
In this situation, I get the error message:
"The name 'DUT' does not exist in the current context."
I am very confused because DUT is clearly defined right there. Thanks for your time
It is transpiled to:
class X
{
TestMonitorDUT DUT = new TestMonitorDUT("1");
DUT.PopulateDictionaries();
}
DUT.PopulateDictionaries(); is a statement where only declarations are expected. It should be inside a method. Like
#code {
TestMonitorDUT DUT = new TestMonitorDUT("1");
//DUT.PopulateDictionaries();
overide void OnInitialized()
{
DUT.PopulateDictionaries();
}
}

What is syntax for creating a class in C# that would be equal to a Module in VB.net

I do almost all of my programming in VB.net (all flavors). I am now been assigned a task to make a new routine in an existing C# application. What I want to be able to do is pass a string variable to a class where I can figure out device type of a symbol handheld and figure out where an executable resides on device.
I am trying to keep the class to contain changes we make going forward in one place.
so a brief description is on a screen there will be a button. on that button click I want pass the text of the button to a (what would be a module in VB) a class and depending on text being passed and device type call a separate executable that lives on the device.
Everything I have tried so far has thrown errors.
On my button click i have
String Reponse = clsCallAction("Activity");
but that gets a message that clsCallAction is a type but is used like a variable.
here is the smaple of clsCallaction
internal static partial class clsCallAction
{
public static object GetPath(object lAppName)
{
string resp = "";
if (lAppName.Equals("Activity"))
{
resp = #"\application\activity.exe";
}
return resp;
}
}
If I put new in front of the clsCallAction("Activity") on button click I get a
cannot create instance of the static class 'clsCalACtion'
appreciate any pointers. very new at C#
It would look something like this:
public static class CallAction
{
public static object GetPath(object lAppName)
{
string resp = "";
if (lAppName.Equals("Activity"))
{
resp = #"\application\activity.exe";
}
return resp;
}
}
And would be used like this:
String Reponse = CallAction.GetPath("Activity");
Don't prefix classes with cls
Avoid using object if possible - it just makes everything harder work than it needs to be.. Kinda like calling everything "thing" - ("Put the thing in the thing and open the thing" is harder to understand than "put the key in the lock and open the door")

C# "A registration already exists for URI" XAML Warning

I'm currently working on a "server-app" / "client-app" project where the goal is to get some data from the server-app to the client app. I tried this with a WCF approach but since I've never worked with WCF it ain't an easy task for me.
So what I've already set up are the two apps in one solution à two different projects. Project one contains the server-app (TRunnerServer) and project two contains the client-app (TRunnerClient).
I've setup the interface for the service like that (in ServerApp MainWindowViewModel.cs):
[ServiceContract]
public interface ITRunnerService
{
[OperationContract]
ObservableCollection<Program> GetProgramList();
}
Than I've added the method to the class etc. like following:
[ServiceBehavior(InstanceContextMode = InstanceContextMode.Single)]
internal class MainWindowViewModel : ViewModelBase, ITRunnerService
{
public ObservableCollection<Program> GetProgramList()
{
return this.ProgramList;
}
public MainWindowViewModel()
{
var uris = new Uri[1];
string addr = "net.tcp://localhost:7000/MainWindowViewModel";
uris[0] = new Uri(addr);
ITRunnerService tRunnerService = this;
ServiceHost host = new ServiceHost(tRunnerService, uris);
var binding = new NetTcpBinding(SecurityMode.None);
host.AddServiceEndpoint(typeof(ITRunnerService), binding, string.Empty);
host.Open();
}
}
Now in the GUI of the application TRunnerClient I've got an button that I press to get the data from the TRunnerServer App.
I've just got an method binded with following:
private void Refresh(object parameter)
{
var uri = "net.tcp://localhost:7000/MainWindowViewModel";
NetTcpBinding binding = new NetTcpBinding(SecurityMode.None);
var channel = new ChannelFactory<ITRunnerService>(binding);
var endPoint = new EndpointAddress(uri);
var proxy = channel.CreateChannel(endPoint);
this.ProgramList = proxy.GetProgramList();
}
Yet when I start the app only the client starts normal and the server app gives an exception based on the error warning from the xaml "A registration already exists for URI 'net.tcp://localhost:7000/MainWindowViewModel'".
How could I solve this problem?
Note: Other questions with a similar title didn't really helped me out before someone strikes it as duplicate.
The error message indicates that there is an old server process still hanging around. Try to kill it in the task manager and try again.
In order to avoid hanging processes, make sure that you exit the application gracefully and that you don't create any windows that you don't show and close.

How to know App navigating to HomeActivity or LoginActivity - Appium

I am testing my mobile app using Appium. When app starting it directly navigation to HomeActivity sometimes(if user already logged in). If user not logged in then opening LoginActivity.
So, how can I know which activity starting? so that I can execute logout code accordingly.
This code not executing at all because app navigation to HomeActivity directly instead of LoginActivity.
public void DemoTest()
{
AndroidElement editElement1 = driver.FindElementById("input_name");
editElement1.Clear();
editElement1.SendKeys("ak#ct");
AndroidElement editElement2 = driver.FindElementById("input_password");
editElement2.Click();
editElement2.SendKeys("qa");
driver.HideKeyboard();
driver.Manage().Timeouts().ImplicitWait =TimeSpan.FromSeconds(4);
AndroidElement editElement3 = driver.FindElementById("btnLogin");
editElement3.Click();
}
If you always want to test in fresh app, you can add noReset = false capability in your DesiredCapabilities.
If you want to check which screen is visible, there must be unique element or id in the homeActivityScreen and LoginActivityScreen. Then you can use isDisplayed() function.
If you use Page Object Model it will be very easy for you to check which screen is Display.
I am going to show sample of page object model in java code. Hope you can convert it into C# code
public class HomeActivityScreen {
//you can use accessibility, id or xpath
#AndroidFindBy(id = " your element id")
private MobileElement element1;
#AndroidFindBy(id = "element id")
private MobileElement element2;
public HomeActivityScreen(AppiumDriver<MobileElement> driver) {
PageFactory.initElements(new AppiumFieldDecorator(driver), this);
}
public boolean isScreenDisplayed() {
try {
return element1.isDisplayed();
} catch (Exception e) {
return false;
}
}
}
Similarly you can add page object model for other screen. Then in your test class you can check which screen is visible like
HomeActivityScreen homeScreen = new HomeActivityScreen(driver);
LoginActivityScreen loginScreen = new LoginActivityScreen(driver);
if(homeScreen.isScreenDisplayed){
//write your code
}else if(loginScreen.isScreenDisplayed){
//write logout code
}else{
//none of above screen is visible
}
You'll need a way to identify the page as being the home page or login page.
If you have access to the mobile app source code, you could give your home page a "homePage" AutomationId and your login page a "loginPage" AutomationId. If that is not possible, ask the developer to add them for you. Use these Id's in your appium code to uniquely identify the page that got loaded.
In your appium code, these are the steps you need to take:
Start your app: driver = new AndroidDriver<AndroidElement>(url, cap);
Give the app some time to get loaded.
Check what page you are on, e.g. by checking the AutomationId or a other unique value for those pages.
In your test script, you can do it like this:
try
{
control = driver.FindElementByAccessibilityId("loginPage");
}
catch (Exception ex)
{
// No login page found, your in the home page.
// Code for logging out here.
}
As Suban Dhyako already suggested, a page object design pattern is a very good practice. It keeps your code clean and clear to read. You can read more about it here.

Reading activity InArgument values

I am creating a custom native activity using workflow foundation 4.5. I want to set a bookmark for the activity and do some custom handling in the WorkflowApplication's PersistableIdle callback. Within that callback I want to read the data that was provided into the activity's InArgument<> and/or Properties before the workflow instance is persisted away. So essentially, I want to read these values from outside the context of the activity that executed and outside the run time as a pre-step before completing the persistence process.
I thought I might be able to do this with the WorkflowInspectionServices helper class but it's unclear if that works given I have to context to read from that activity instance's InArgument<>.
Is there another helper class that can make this happen with wf4.5 that I haven't discovered yet? Thanks.
wfApp.PersistableIdle += args =>
{
using (var scope = new TransactionScope(TransactionScopeOption.RequiresNew))
{
wfApp.Unload();
args.Bookmarks.ForEach(bookmark =>
{
var activityId = bookmark.BookmarkName;
//Doesn't seem this will really work?
var activityInfo = WorkflowInspectionServices.Resolve(activity, activityId) as MyCustomActivity;
var recipientId = activityInfo.RecipientId.Get(<I have no context>);
workflowSuspendedCallback.Invoke(activityId, recipientId));
});
scope.Complete();
}
return PersistableIdleAction.None;
};
The use of activity extensions did the trick.
Thanks Will.

Categories