Starting Help First Android app with c# - c#

I'm trying to write an android app using VS Community 2015 in c#
The App should send a message to a websocket an display it received answer.
This is my MainActivity.cs
public class MainActivity : Activity
{
protected override void OnCreate(Bundle bundle)
{
base.OnCreate(bundle);
// Set our view from the "main" layout resource
SetContentView(Resource.Layout.Main);
// Get our button from the layout resource,
// and attach an event to it
Button button = FindViewById<Button>(Resource.Id.MyButton);
TextView t1 = FindViewById<TextView>(Resource.Id.textView1);
button.Click += delegate
{
string msg = SetStatusText();
t1.SetText(msg,TextView.BufferType.Normal);
};
}
private string SetStatusText()
{
Connector c = new Connector();
c.Connect();
return c.msg;
}
}
The Connector goes like this
class Connector
{
public string msg { get; set; }
WebSocket websocket = new WebSocket("ws://192.168.1.103:2012/");
public void Connect()
{
websocket.Opened += new EventHandler(websocket_Opened);
websocket.MessageReceived += new EventHandler<MessageReceivedEventArgs>(websocket_MessageReceived);
websocket.Open();
}
private void websocket_MessageReceived(object sender, MessageReceivedEventArgs e)
{
msg = e.Message;
}
private void websocket_Opened(object sender, EventArgs e)
{
websocket.Send("Status");
}
}
In debug mode I see the message the websocket returned in msg variable of the Connector, but the way I'm returning it to the MainActivity doesn't work. It stays NULL.

You are using the "msg" variable just after connecting to the WebSocket, that will fail as you still did not received a message, you need to wait in some way to websocket_MessageReceived be executed.
If you want to wait until the message is received you can use an event:
class Connector
{
public string msg { get; set; }
public event EventHandler MessageReceived;
WebSocket websocket = new WebSocket("ws://192.168.1.103:2012/");
public void Connect()
{
websocket.Opened += new EventHandler(websocket_Opened);
websocket.MessageReceived += new EventHandler<MessageReceivedEventArgs>(websocket_MessageReceived);
websocket.Open();
}
private void websocket_MessageReceived(object sender, MessageReceivedEventArgs e)
{
msg = e.Message;
if(MessageReceived != null)
MessageReceived(this, EventArgs.Empty);
}
private void websocket_Opened(object sender, EventArgs e)
{
websocket.Send("Status");
}
}
Then, when you create your connection you can do:
c.MessageReceived += (o,e) => t1.SetText(c.msg,TextView.BufferType.Normal);

Related

Events and Delegates in Xamarin forms parent and child pages

I need some help. I am new to Events and handlers and I would like to begin using events for decoupling purposes but I am confused.
I have a class where I have a list view that is populated on OnAppearing. However to prevent onAppearing to happen each time the page is clicked I load the list once and then I would like to have items to get added or deleted to the list upon being added or removed from the server through the use of events.
The ListView page is a list of my favorite newspaper article Links. When clicking on any one of these links I get redirected to a LinksDetailsPage where I pass in the selected link and then display any details associated with the link.
Anyways...
I would like to add or remove an item on the my Favorites list seamlessly. So when I click on the AddItem or RemoveItem in the LinksDetailsPage I would like the item to either remove or add to theFavoritesPage List. Before I was only relying on the OnAppearing to work its magic and update the favorites list but it would lag to remove the item from the list, so this way I hope it would remove or add as soon as the even is invoked and not when the page loads on OnAppearing. However I think I am either not invoking the event properly or my subscriber is not subscribed properly. Events and delegates have been confusing for me from the get go. On top of that my favorites list is grouped so and it's my first time working with grouped lists as well.
Check out my code:
Subscriber
My Favorites Page:
public FavoritesPage()
{
InitializeComponent();
}
protected override async void OnAppearing()
{
if (_isDataLoaded)
return;
_isDataLoaded = true;
base.OnAppearing();
await LoadFavorites();
}
private async Task LoadFavorites()
{
groups = new ObservableCollection<LinksTypeGroup<string, NewspaperLink>>();
var links = await _db.GetAllFavorites();
var linkType = await _manager.GetLinkCategories();
foreach(var type in linkType)
{
var typegroup = links.FindAll(
delegate(NewspaperLink link)
{
return link.iLinkTypeID == type.iLinkTypeID;
});
groups.Add(new LinksTypeGroup<string, NewspaperLink>(type.Title, typegroup));
MyList.GroupDisplayBinding = new Binding("GroupKey");
MyList.ItemsSource = groups;
}
}
public void Listener(FavoritesPage P)
{
P.LinkAdded += Item_Added;
P.LinkDeleted += Item_Deleted;
}
void Item_Deleted(object sender, int e)
{
Console.WriteLine("Item_Deleted");
// remove item from groups ..see code above
}
void Item_Added(object sender, int e)
{
Console.WriteLine("Item_Added");
// add to groups ..see code above
}
I am not accessing anything so far.
Publisher
LinksDetailsPage:
private NewspaperLink _link;
public event EventHandler< NewspaperLink> ItemAdded;
public event EventHandler< NewspaperLink> ItemDeleted;
public LinksDetailsPage(NewspaperLink link)
{
_link = link;
BindingContext = _link;
InitializeComponent();
}
protected override async void OnAppearing()
{
base.OnAppearing();
await LoadLink();
}
private async Task LoadLink()
{
var url = await db.ReturnRecipeLink(_link.iLinkID);
linkWebView.Source = url;
CheckifExists(_link);
}
}
void AddLink(object sender, System.EventArgs e)
{
var link = BindingContext as NewspaperLink;
db.InsertIntoMyList(_link);
ItemAdded?.Invoke(this, link);
}
void DeleteLink(object sender, System.EventArgs e)
{
var link = BindingContext as NewspaperLink;
db.DeleteFromMyList(_link);
ItemDeleted?.Invoke(this, link);
}
Can someone guide me on how to make this even process work?
Event
If want to use Events, LinksDetailsPage should be declared something like following:
public partial class LinksDetailsPage : ContentPage
{
public event EventHandler<NewspaperLink> ItemAdded;
public event EventHandler<NewspaperLink> ItemDeleted;
public LinksDetailsPage()
{
InitializeComponent();
}
protected virtual void AddLink(NewspaperLink e)
{
EventHandler<NewspaperLink> handler = ItemAdded;
if (handler != null)
{
handler(this, e);
}
}
protected virtual void DeleteLink( NewspaperLink e)
{
EventHandler<NewspaperLink> handler = ItemDeleted;
if (handler != null)
{
handler(this, e);
}
}
// Add click event
private void Add_Clicked(object sender, EventArgs e)
{
AddLink(new NewspaperLink() {link="first link" });
}
// Delete click event
private void Delete_Clicked(object sender, EventArgs e)
{
DeleteLink(new NewspaperLink() { link = "first link" });
}
}
public class NewspaperLink : EventArgs
{
public string link { get; set; }
}
Then you need to subscribe it in the ListView page when navigating to the LinksDetailsPage page:
private async void Button_Clicked(object sender, EventArgs e)
{
LinksDetailsPage detailPage = new LinksDetailsPage();
detailPage.ItemAdded += DetailGridPage_ItemAdded;
detailPage.ItemDeleted += DetailGridPage_ItemDeleted;
await Navigation.PushModalAsync(detailGridPage);
}
private void DetailGridPage_ItemDeleted(object sender, NewspaperLink e)
{
Console.WriteLine("The tlink was deleted : " + e.link);
}
private void DetailGridPage_ItemAdded(object sender, NewspaperLink e)
{
Console.WriteLine("The link was added : "+e.link);
}
Delegate
Similarly, if want to use Delegate, you only need to declare something in List Page as follows:
public partial class ListViewPage : ContentPage
{
public delegate void ItemAddedDelegate(NewspaperLink e);
public delegate void ItemDeletedDelegate(NewspaperLink e);
public ListViewPage()
{
InitializeComponent();
}
private async void Button_Clicked(object sender, EventArgs e)
{
ItemAddedDelegate itemAddedDelegate = AddMethod;
ItemDeletedDelegate itemDeletedDelegate = DeleteMethod;
DetailGridPage detailGridPage = new DetailGridPage(itemAddedDelegate, itemDeletedDelegate);
await Navigation.PushModalAsync(detailGridPage);
}
public static void AddMethod(NewspaperLink item)
{
Console.WriteLine("Add" + item.link);
}
public static void DeleteMethod(NewspaperLink link)
{
Console.WriteLine("Delete" + item.link);
}
}
Then in LinksDetailsPage, you can pass the add or delete delegate method to ListViewPage.
public partial class LinksDetailsPage : ContentPage
{
private ListViewPage.ItemAddedDelegate itemAddedDelegate;
private ListViewPage.ItemDeletedDelegate itemDeletedDelegate;
public DetailGridPage()
{
InitializeComponent();
}
public LinksDetailsPage(ListViewPage.ItemAddedDelegate itemAddedDelegate, ListViewPage.ItemDeletedDelegate itemDeletedDelegate)
{
InitializeComponent();
this.itemAddedDelegate = itemAddedDelegate;
this.itemDeletedDelegate = itemDeletedDelegate;
}
// Add click event
private void Add_Clicked(object sender, EventArgs e)
{
itemAddedDelegate(new NewspaperLink() { link = "first link" });
}
// Delete click event
private void Delete_Clicked(object sender, EventArgs e)
{
itemDeletedDelegate(new NewspaperLink() { link = "first link" });
}
}
public class NewspaperLink : EventArgs
{
public string link { get; set; }
}
MessageCenter
If using MessageCenter, it should be the best convenient method to achieve that.
Only Subscribe it in ListView page:
public ListViewPage()
{
InitializeComponent();
MessagingCenter.Subscribe<object, NewspaperLink>(this, "Add", async (sender, arg) =>
{
await DisplayAlert("Message received", "arg=" + arg.link, "OK");
});
MessagingCenter.Subscribe<object, NewspaperLink>(this, "Delete", async (sender, arg) =>
{
await DisplayAlert("Message received", "arg=" + arg.link, "OK");
});
}
And send message in LinksDetailsPage as follows:
// Add click event
private void Add_Clicked(object sender, EventArgs e)
{
NewspaperLink newspaperLink= new NewspaperLink() { link = "first link" };
MessagingCenter.Send<object, NewspaperLink>(this, "Add", newspaperLink);
}
// Delete click event
private void Delete_Clicked(object sender, EventArgs e)
{
NewspaperLink newspaperLink = new NewspaperLink() { link = "first link" };
MessagingCenter.Send<object, NewspaperLink>(this, "Delete", newspaperLink);
}

Streamwriter is null even when it has been initialized in C#

I am trying to use sockets to send messages to computers, but I keep getting this error:
System.NullReferenceException: 'Object reference not set to an instance of an object.'
sw was null.
This is my code:
public partial class ServerGUI : Form
{
Socket soc;
StreamReader sr;
StreamWriter sw;
Stream s;
public ServerGUI()
{
InitializeComponent();
try
{
if (Server.port == 0)
{ }
else
{
textBox2.Text = Server.port.ToString();
}
}
catch (Exception) { }
}
private void button1_Click(object sender, EventArgs e)
{
connect();
}
void connect()
{
Server.port = int.Parse(textBox2.Text);
TcpListener listener = new TcpListener(IPAddress.Any, Server.port);
listener.Start();
soc = listener.AcceptSocket();
s = new NetworkStream(soc);
sr = new StreamReader(s);
sw = new StreamWriter(s);
sw.AutoFlush = true; // enable automatic flushing
if (soc.Connected == true)
{
Console.WriteLine("Connected");
sw.WriteLine("Server Connected");
}
this.Hide();
Menu menu = new Menu();
menu.Show();
}
void recieve()
{
Console.WriteLine(sr.ReadLine());
}
public void close()
{
s.Close();
soc.Disconnect(true);
Menu menu = new Menu();
menu.Close();
this.Show();
}
public void send(string msg)
{
sw.WriteLine(msg);
}
This is the code for the button:
ServerGUI sgui = new ServerGUI();
public Menu()
{
InitializeComponent();
}
private void button1_Click(object sender, EventArgs e)
{
sgui.close();
}
private void button2_Click(object sender, EventArgs e)
{
sgui.send(textBox1.Text);
}
The writeline code in the connect method works but the code in the send method doesn't. I have tried this question: What is a NullPointerException, and how do I fix it? but it has not helped me.
Thanks
If the send method is called before the connect method the the StreamWriter sw is set to null and a NullReferenceException is thrown inside the send method.
A quick fix is to check the sw property before using it like:
public void send(string msg)
{
if (sw != null)
sw.WriteLine(msg);
}
or with a newer C# language feature a little bit shorter:
public void send(string msg)
{
sw?.WriteLine(msg);
}
EDIT:
The problem is that with the line ServerGUI sgui = new ServerGUI(); you create a new (second) ServerGUI form after hiding the former one that hat its own sw property. This sw property has been never initialized because the created StreamWriter instance is part of the first gui that you just have hidden.
Although this design (strong coupling of forms without a data/service layer) is not ideal, a way to fix this is to pass the form instance to the Menu. E.g.
var menu = new Menu();
menu.ServerGui = this;
menu.Show();
and of course the Menu class has to introduce a ServerGUI property like public
class Menu {
...
public ServerGUI ServerGui {get; set;}
private void button1_Click(object sender, EventArgs e)
{
ServerGui.close();
}
private void button2_Click(object sender, EventArgs e)
{
ServerGui.send(textBox1.Text);
}

C#: DataReceived Event handler for serialPort not firing

I'm writing a fairly basic application, where one of the tasks is communicating with an Arduino Uno card.
I would like to write the serial communication as a separate module, so the forms only calls for the input from Arduino, and the module will handle the creating and opening of the serialPort and reading data from it.
For testing purposes I wrote a program for the Arduino which prints the elapsed milliseconds every half second to the serialPort.
I would like to populate the textBox of my Form with the output from Arduino after I press a button.
I create the serialPort in the SerialComm class, and although I attach a DataReceived event handler to it, it never seems to fire.
Here is the code for the SerialComm class:
class SerialComm
{
private List<String> availablePorts;
private SerialPort arduino;
private string receivedText;
public String[] portList
{ get
{
EnumPorts();
return availablePorts.ToArray();
}
}
public string receivedData
{
get
{
return receivedText;
}
}
public void InitialiseSerial()
{
arduino = new SerialPort();
arduino.BaudRate = 9600;
arduino.DtrEnable = true;
// Add event handler
arduino.DataReceived += new SerialDataReceivedEventHandler(arduino_DataReceived);
}
public void EnumPorts()
{
availablePorts = new List<string>();
foreach (string s in SerialPort.GetPortNames())
{
availablePorts.Add(s);
}
}
public void StartMC(SerialPort serialPort, String portName)
{
arduino = serialPort;
if (arduino.IsOpen)
{
arduino.Close();
}
else
{
//Initialise Serial Port
arduino.PortName = portName;
arduino.Open();
}
}
//This never fires==================
private void arduino_DataReceived(object sender, SerialDataReceivedEventArgs e)
{
receivedText = arduino.ReadExisting();
}
public void CloseMC()
{
if (arduino.IsOpen)
{
arduino.Close();
arduino.Dispose();
}
}
}
In the Form I call the text from Arduino like this: (I have a button (Button1), a combobox for selecting the COM port (comboBox1) and a textBox on the Form)
public partial class Form1 : Form
{
SerialComm arduino = new SerialComm();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//Arduino
arduino.InitialiseSerial();
String[] portList = arduino.portList;
foreach (String COM in portList)
{
comboBox1.Items.Add(COM);
}
if (portList.Length > 0)
{
comboBox1.SelectedItem = comboBox1.Items[0];
}
else
{
comboBox1.Text = "No microcontroller found!";
}
}
private void button1_Click(object sender, EventArgs e)
{
arduino.StartMC(serialPort1, comboBox1.SelectedItem.ToString());
//as the DataReceived never fires arduino.receivedData stays null
if (arduino.receivedData != null)
{
for (int i = 0; i < 101; i++)
{
textBox1.AppendText(arduino.receivedData);
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
arduino.CloseMC();
}
}
Do you see any reason why the event handler doesn't trigger?
Thank you very much for your help in advance.
Best Regards,
Peter

FiddlerCore C# HTTPS events not firing

Right I have the following code:
public partial class Form1 : Form
{
delegate void UpdateUI();
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
if (!Fiddler.CertMaker.rootCertExists())
{
if (!Fiddler.CertMaker.createRootCert())
{
throw new Exception("Unable to create cert for FiddlerCore.");
}
}
if (!Fiddler.CertMaker.rootCertIsTrusted())
{
if (!Fiddler.CertMaker.trustRootCert())
{
throw new Exception("Unable to install FiddlerCore's cert.");
}
}
Fiddler.FiddlerApplication.OnNotification += delegate (object snder, NotificationEventArgs oNEA) { MessageBox.Show("** NotifyUser: " + oNEA.NotifyString); };
Fiddler.FiddlerApplication.Log.OnLogString += delegate (object snder, LogEventArgs oLEA) { MessageBox.Show("** LogString: " + oLEA.LogString); };
Fiddler.FiddlerApplication.AfterSessionComplete += FiddlerApplication_OnAfterSessionComplete;
Fiddler.FiddlerApplication.Startup(0, FiddlerCoreStartupFlags.Default & FiddlerCoreStartupFlags.DecryptSSL);
}
void FiddlerApplication_OnAfterSessionComplete(Session oSession)
{
if(oSession.fullUrl.Contains("google.com"))
richTextBox1.Invoke(new UpdateUI(() =>
{
richTextBox1.AppendText(oSession.GetResponseBodyAsString());
}));
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
Fiddler.FiddlerApplication.Shutdown();
}
}
The thing is with DecryptSSL flag set on startup the on aftersesssion complete never fires, I also never get any messages from either the notification or logs callbacks.
Any ideas?
I think port 0 might be a problem in the Startup(), I tried with port 8888:
Fiddler.FiddlerApplication.Startup(8888, FiddlerCoreStartupFlags.Default & FiddlerCoreStartupFlags.DecryptSSL);
I tried with these before response and before request handlers instead of OnAfterSessionComplete. In your Form1_Load():
Fiddler.FiddlerApplication.BeforeRequest += new SessionStateHandler(HandleBeforeRequest);
Fiddler.FiddlerApplication.BeforeResponse += new SessionStateHandler(HandleBeforeResponse);
And the handlers:
private void HandleBeforeRequest(Session oSession)
{
oSession.bBufferResponse = true;
}
private void HandleBeforeResponse(Session oSession)
{
if(oSession.fullUrl.Contains("google.com"))
{
richTextBox1.Invoke(new UpdateUI(() =>
{
richTextBox1.AppendText(oSession.GetResponseBodyAsString());
}));
}
}
By the way, don't know if you omitted them from your sample but I needed to add these in the constructor:
Load += Form1_Load;
FormClosing += Form1_FormClosing;
Might also be good to add this before Shutdown():
FiddlerApplication.oProxy.Detach();

Handle serial thread event in WPF GUI class

I have a serial port class, and I would like to control send/receive via my GUI, and have the GUI update based on receipt of data from the serial port (or other events). So the two relevant classes are the serial class and the main window class.
I have the code below which compiles, but I get an exception when I try to run.
public class MySerThread
{
public SerialPort serport;
public event SerialDataReceivedEventHandler newSerData;
public MySerThread()
{
serport = new SerialPort("COM1", 115200);
serport.Open();
serport.DataReceived += DataReceivedHandler;
}
public void DataReceivedHandler(object s, SerialDataReceivedEventArgs e)
{
byte[] data = new byte[serport.BytesToRead];
serport.Read(data, 0, data.Length);
// here's where I think I'm going wrong?
if(newSerData != null)
newSerData(s,e);
}
}
And then in my GUI class...
public partial class MainWindow : Window
{
MySerThread myPort;
public MainWindow()
{
// Exception triggers here
myPort.newSerData += DisplaySerDataHandler;
}
private void DisplaySerDataHandler(object sender, SerialDataReceivedEventArgs e)
{
this.ReceivedCallback(e);
}
private void ReceivedCallback(SerialDataReceivedEventArgs e)
{
if(this.someTextBlock.Dispatcher.CheckAccess())
{
this.UpdateTextBlock(e);
}
else
{
this.someTextBlock.Dispatcher.BeginInvoke(new Action<SerialDataReceivedEventArgs>(this.UpdateTextBlock), e);
}
}
private void UpdateTextBlock(SerialDataReceivedEventArgs e)
{
someTextBlock.Text = "got new data";
}
}
So, what am I doing wrong here? What is the best way to do this?
You can't access myPort without creating an instance.
MySerThread myPort = new MySerThread();

Categories

Resources