Related article: Android: Fast Communication with .NET Using Protocol Buffers
Introduction
The example bellow implements a simple request-response communication between Android and .NET application.
The Android application is a simple client using the .NET application as a service to calculate length of the text message.
The example can be downloaded from here.
The example bellow uses Eneter Messaging Framework that makes the whole communication very simple.
(The framework is free for non-commercial use and can be downloaded from http://www.eneter.net. You need to download Eneter for.NET and Eneter for Android.
(Here is the step-by-step procedure how to add Eneter library into the Android project.)
More detailed technical info can be found at technical info.)
TCP on Android
When you implement the communication via TCP on Android, you must count with two specifics:
1. You must set INTERNET permission for your Android application!
If the permission is not set, the application is not allowed to communicate across the network. To set the INTERNET permission you must add the following line to AndroidManifest.xml.
<uses-permission android:name="android.permission.INTERNET"/>
Example of AndroidManifest.xml allowing communication across the network:
<?xml version="1.0" encoding="utf-8"?> <manifest xmlns:android="http://schemas.android.com/apk/res/android" package="net.client" android:versionCode="1" android:versionName="1.0" > <uses-sdk android:minSdkVersion="7" /> <uses-permission android:name="android.permission.INTERNET"/> <application android:icon="@drawable/ic_launcher" android:label="@string/app_name" > <activity android:name=".AndroidNetCommunicationClientActivity" android:label="@string/app_name" > <intent-filter> <action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" /> </intent-filter> </activity> </application> </manifest>
The IP address 127.0.0.1 (loopback) cannot be set on the Android emulator to communicate with the .NET application!
The emulator acts as a separate device. Therefore, the IP address 127.0.0.1 is the loopback of that device and cannot be used for the communication with other applications running on the same computer as the emulator.
Instead of that you must use a real IP address of the computer or the emulator can use the special address 10.0.2.2 that is routed to 127.0.0.1 (loopback) on the computer. In my example, the Android emulator uses 10.0.2.2 and the .NET service is listening to 127.0.0.1.
Android Client Application
The Android client is a very simple application allowing user to put some text message and send the request to the service to get back the length of the text.
When the response message is received it must be marshalled to the UI thread to display the result.
Also please do not forget to set android.permission.INTERNET and set the valid IP address - since 127.0.0.1 cannot be used - see the explanation above.
Note: To add the Eneter library into the Android project please follow the recommended procedure.
The whole implementation is very simple with using the Eneter framework:
package net.client; import eneter.messaging.diagnostic.EneterTrace; import eneter.messaging.endpoints.typedmessages.*; import eneter.messaging.messagingsystems.messagingsystembase.*; import eneter.messaging.messagingsystems.tcpmessagingsystem.TcpMessagingSystemFactory; import eneter.net.system.EventHandler; import android.app.Activity; import android.os.Bundle; import android.os.Handler; import android.view.View; import android.view.View.OnClickListener; import android.widget.*; public class AndroidNetCommunicationClientActivity extends Activity { // Request message type // The message must have the same name as declared in the service. // Also, if the message is the inner class, then it must be static. public static class MyRequest { public String Text; } // Response message type // The message must have the same name as declared in the service. // Also, if the message is the inner class, then it must be static. public static class MyResponse { public int Length; } // UI controls private Handler myRefresh = new Handler(); private EditText myMessageTextEditText; private EditText myResponseEditText; private Button mySendRequestBtn; // Sender sending MyRequest and as a response receiving MyResponse. private IDuplexTypedMessageSender<MyResponse, MyRequest> mySender; /** Called when the activity is first created. */ @Override public void onCreate(Bundle savedInstanceState) { super.onCreate(savedInstanceState); setContentView(R.layout.main); // Get UI widgets. myMessageTextEditText = (EditText) findViewById(R.id.messageTextEditText); myResponseEditText = (EditText) findViewById(R.id.messageLengthEditText); mySendRequestBtn = (Button) findViewById(R.id.sendRequestBtn); // Subscribe to handle the button click. mySendRequestBtn.setOnClickListener(myOnSendRequestClickHandler); // Open the connection in another thread. // Note: From Android 3.1 (Honeycomb) or higher // it is not possible to open TCP connection // from the main thread. Thread anOpenConnectionThread = new Thread(new Runnable() { @Override public void run() { try { openConnection(); } catch (Exception err) { EneterTrace.error("Open connection failed.", err); } } }); anOpenConnectionThread.start(); } @Override public void onDestroy() { // Stop listening to response messages. mySender.detachDuplexOutputChannel(); super.onDestroy(); } private void openConnection() throws Exception { // Create sender sending MyRequest and as a response receiving MyResponse IDuplexTypedMessagesFactory aSenderFactory = new DuplexTypedMessagesFactory(); mySender = aSenderFactory.createDuplexTypedMessageSender(MyResponse.class, MyRequest.class); // Subscribe to receive response messages. mySender.responseReceived().subscribe(myOnResponseHandler); // Create TCP messaging for the communication. // Note: 10.0.2.2 is a special alias to the loopback (127.0.0.1) // on the development machine IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory(); IDuplexOutputChannel anOutputChannel = aMessaging.createDuplexOutputChannel("tcp://10.0.2.2:8060/"); // Attach the output channel to the sender and be able to send // messages and receive responses. mySender.attachDuplexOutputChannel(anOutputChannel); } private void onSendRequest(View v) { // Create the request message. MyRequest aRequestMsg = new MyRequest(); aRequestMsg.Text = myMessageTextEditText.getText().toString(); // Send the request message. try { mySender.sendRequestMessage(aRequestMsg); } catch (Exception err) { EneterTrace.error("Sending the message failed.", err); } } private void onResponseReceived(Object sender, final TypedResponseReceivedEventArgs<MyResponse> e) { // Display the result - returned number of characters. // Note: Marshal displaying to the correct UI thread. myRefresh.post(new Runnable() { @Override public void run() { myResponseEditText.setText(Integer.toString(e.getResponseMessage().Length)); } }); } private EventHandler<TypedResponseReceivedEventArgs<MyResponse>> myOnResponseHandler = new EventHandler<TypedResponseReceivedEventArgs<MyResponse>>() { @Override public void onEvent(Object sender, TypedResponseReceivedEventArgs<MyResponse> e) { onResponseReceived(sender, e); } }; private OnClickListener myOnSendRequestClickHandler = new OnClickListener() { @Override public void onClick(View v) { onSendRequest(v); } }; }
.NET Service Application
The .NET service is a simple console application listening to TCP and receiving requests to calculate the length of a given text.
The implementation of the service is very simple:
using System; using Eneter.Messaging.EndPoints.TypedMessages; using Eneter.Messaging.MessagingSystems.MessagingSystemBase; using Eneter.Messaging.MessagingSystems.TcpMessagingSystem; namespace ServiceExample { // Request message type public class MyRequest { public string Text { get; set; } } // Response message type public class MyResponse { public int Length { get; set; } } class Program { private static IDuplexTypedMessageReceiver<MyResponse, MyRequest> myReceiver; static void Main(string[] args) { // Create message receiver receiving 'MyRequest' and receiving 'MyResponse'. IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory(); myReceiver = aReceiverFactory.CreateDuplexTypedMessageReceiver<MyResponse, MyRequest>(); // Subscribe to handle messages. myReceiver.MessageReceived += OnMessageReceived; // Create TCP messaging. IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory(); IDuplexInputChannel anInputChannel = aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8060/"); // Attach the input channel and start to listen to messages. myReceiver.AttachDuplexInputChannel(anInputChannel); Console.WriteLine("The service is running. To stop press enter."); Console.ReadLine(); // Detach the input channel and stop listening. // It releases the thread listening to messages. myReceiver.DetachDuplexInputChannel(); } // It is called when a message is received. private static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<MyRequest> e) { Console.WriteLine("Received: " + e.RequestMessage.Text); // Create the response message. MyResponse aResponse = new MyResponse(); aResponse.Length = e.RequestMessage.Text.Length; // Send the response message back to the client. myReceiver.SendResponseMessage(e.ResponseReceiverId, aResponse); } } }
And here are applications communicating together:
hello sir,i compiled android code but emulator gives force close message???????eclipse gives no error,but yet force close error???please help me,
ReplyDeleteon this email onlyme843@hotmail.com
The most common problem is the Enter Android library is not added correctly to the Android project.
DeletePlease be sure you add the Eneter library into your android project the following way (the procedure works for Eclipse):
1. Right click on the android project -> New -> Folder, create folder libs
2. Right click on the android project -> Import... -> File System
3. In the section 'From directory' click 'Browse...' button and select directory with the eneter library
4. Select the eneter library in the list
5. In the section 'Into folder' click 'Browse...' and select your libs directory
6. Click 'Finish'
7. The eneter library should be now listed under 'Android Dependencies'
8. try to compile ans run your application
I hope my answer will help.
i have added project library but it error" The import eneter cannot be resolved "
Deleteplz help me
hello sir....every thing work all when i run on emmulator then it will response...my problem is that when i change the to my real system ip and i run this on my android mobile hen it will not work pls help me...
ReplyDeleteHello Ittar, the most common reason why there are problems with real device is using incorrect IP address.
DeletePlease be sure your .NET service application does not use IP address 127.0.0.1 but the IP address of the network you want to use for the communication with Android (e.g. tcp://192.168.1.1:8060/).
Your .NET service can also use the IP address 0.0.0.0. The service will then listen to all available addresses (e.g. tcp://0.0.0.0:8060/).
I hope my answer will help.
What do you mean "IP address of the network you want to use for the communication with Android"
DeleteThe network, not the computer hosting the service?
Hi Terry, thank you for your point.
DeleteI mean the IP address the computer has inside a particular network.
is it work over the internet means when my mobile is connected with internet and i want to send a string from any place to on my .net application
ReplyDelete(is it possible)
Yes, it works over Internet too. Is the IP address you are using your IP address on Internet?
Delete(E.g. you can check it here http://whatismyipaddress.com/)
If your computer is behind a router then the IP address of your computer can be just an address of a local network behind that router. In such case you may need to configure your router to forward messages coming from Android to the computer.
new problem arise sir i:e the duplex output channel is not attached in android emmulator when i add my real ip which was taken from(http://whatismyipaddress.com)
ReplyDeleteIs the IP address taken from http://whatismyipaddress.com also the IP address of your computer? Or is your computer hiden behind a router and so it has a different address?
Deleteyes sir my computer is hiden behind a router its address is 192.168.50.107 ....i try both the ip i:e system ip and router ip ...still its not working...help me pls sir
ReplyDeleteIttar, you need to configure the router to forward the communication to your computer.
DeleteYou can check the following link:
http://stackoverflow.com/questions/9559362/simple-tcp-communication-with-a-computer-behind-a-router
My VS2010 doesn't recognize the Eneter library..what should i do?
ReplyDeleteThe libraries are not part of the example.
DeleteTherefore, you must go to http://www.eneter.net/ProductDownload.htm and download Eneter for non-commercial usage. Then you need to add the library into the VS project.
i downloaded that exe file, and installed it, but nothing more then that.
Deletewhat is the next step?
thank you for your answer
Hi Nisim, here are the steps you need to perform:
Delete-> Open VS with the example described in this blog.
-> Right click on 'References' and choose 'Add References...'
-> Choose 'Browse' tab and then navigate to the path where you installed Eneter. Select the library and press 'Ok'.
hello sir,worked on this code,it works fine,thanks for this,just want to ask you how can i make it multi-client? or it is al ready multi client?
ReplyDeleteYes, the code works already with multiple clients.
Deletewith real device ?
ReplyDeleteThe example works with real devices too.
DeleteTo run it on a real device you need to use a real IP address.
E.g. if your service is running on 168.123.10.5. Then you would change the service and also the client code to use that IP address.
(Do not use 127.0.0.1 for your service because it is the loopback that is not visible from outside - use the IP address the machine has in the network.)
Hello Ondrej, you mentioned the code will work for multiple clients (i.e) Multiple Android clients.
ReplyDeleteIf that is the case how should i mention the channel id on multiple clients? can you please help me to make it work.
Hello Nagarajan,
DeleteYou do not have to do anything special. Just execute your service and try to connect it from multiple clients.
The channel id represents the address of the service. So when you run multiple clients they will use the same channel id to connect the same service.
Please try to upload the example application into multiple clients and try to connect the service from all of them. It should work.
This comment has been removed by the author.
ReplyDeleteHi Ondrej,
ReplyDeleteI am trying to connect an Android device which is running the code given on this page, to the .NET Service. I have specified the INTERNET permission in the manifest file. The device is connected to my Laptop using the USB cable. I have specified the Ip address of the Laptop in the .NET service (in CreateDuplexInputChannel). I can also connect to the service from another machine. In the Android code, I have specified the Ip address of the Laptop (in createDuplexOutputChannel). When I try to connect to the .NET service, I get the message : The Tcp duplex output channel 'tcp://192.XXX.X.XX:8060/' detected the duplex input channel is not available. The connection will be closed. Can you please help me resolving this?
Thanks
Hi Stamhaney,
DeleteI think the problem is you connect your device to the laptop via the USB cable. When you connect it via the USB cable then the Android device is not connected to the network.
If you have a wireless router then you can connect your Android to the same network as your laptop via WiFi.
If the wireless connection is not an alternative then you can communicate via the cable but you need to use 'AndroidUsbMessagingSystem' for the communication.
More details about the communication via the cable can be found here:
http://www.eneter.net/OnlineHelp/EneterMessagingFramework/html/T_Eneter_Messaging_MessagingSystems_AndroidUsbCableMessagingSystem_AndroidUsbCableMessagingFactory.htm
i want send object between android and c#application is it possible whe using fastjson ? and if yes where is the library like fastjsonserilize in java because in c# there is one .
ReplyDeleteYes, you can use fastJson too. You can find more details here:
Deletehttp://eneter.blogspot.de/2012/10/using-fastjson-serializer-with-eneter.html
The example in the article is for C#. But since Eneter has identical functionality across platforms the Java code would look very similar.
fastJson library for Java can be found here:
http://sourceforge.net/projects/fastjson/
i have added project library but it error" The import eneter cannot be resolved "
ReplyDeleteplz help me
Hi Arshad,
DeleteI think the problem could the way how to add the library.
Could you please try to follow the following procedure how to add a library to an android project:
http://eneter.blogspot.de/2013/03/how-to-add-eneter-library-into-android.html
Hi ondrej,
ReplyDeleteI am very keen to know, If i have to send message from .net application to android app and get response from android then what should be done?
Hi Shivam,
DeleteI am not sure if I understand what you mean. I think this article and especially attached example explains how to send messages between Android and .NET.
Therefore I think you probably wanted to ask something else.
Hi ondrej,
DeleteIn this example the android app is sending message to .Net application and getting response but i want .NET app to send message first and get response back from android app. Actually i m creating a .Net app which will notify android user to authorize login from a dialog box. if yes then windows form will be navigating to another form else messaage box will appear that "android user rejected login request".
Hi Shivam,
DeleteOk, I think I understand now. In such case you just need to implement it other way around. It means you need to implement your android device using the duplex input channel and your .NET application using duplex output channel.
Hi ondrej,
DeleteI tried doing that but unfortunately not being able to find out where i am doing mistake. neither android nor .Net app is giving compilation error but at runtime it is not attaching input channel. I would be grateful if you can send me code for that or give me some advice for doing that. My mail id is mishrashivam77@gmail.com
Hello friends someone will have an example of how to create the service but in a Windows Form application with c # because so far not receive messages sent from an android device this is my source code but the debug never go to OnMessageReceived:
ReplyDeletepublic void OnMessageReceived(object sender, TypedRequestReceivedEventArgs e)
{
MyResponse aResponse = new MyResponse();
Form1 formulario = new Form1();
aResponse.Length = e.RequestMessage.Text.Length;
myReceiver.SendResponseMessage(e.ResponseReceiverId, aResponse);
}
public Form1()
{
InitializeComponent();
IMessagingSystemFactory aMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel
= aMessaging.CreateDuplexInputChannel("tcp://192.168.0.104:8060/");
IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
myReceiver = aReceiverFactory.CreateDuplexTypedMessageReceiver();
myReceiver.MessageReceived += OnMessageReceived;
// Attach the input channel and start to listen to messages.
myReceiver.AttachDuplexInputChannel(anInputChannel);
}
Hello Josue,
DeleteI will try to support you. Could you please send me via e-mail your project?
I will check what is wrong.
Hi
ReplyDeleteThanks for the code, it works very well, Is it possible to have the c# service part in windows forms? if possible as vb other than c#?
Thanks
Yes, it is possible. Just instead of console project you will create winform project.
DeleteAlso please be aware the received messages will not be received within the main UII thread. It means the method handling the event MessageReceived cannot directly access UI controls but must marshal it to the UI thread.
For more details please see the helper method InvokeInUIThread from the example here:
http://eneter.blogspot.de/2012/01/simple-request-response-communication.html
It is also possible to use VB instead of C#.
hi
Deletethanks for the quick reply
I m still struggling to get the service part of the project as a windows form in c#, this is the code I have, but it doesn't seem to work, please help
using System;
using System.Windows.Forms;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
namespace WindowsFormsApplication1CS
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
// Create message receiver.
// It receives string and responses also string.
IDuplexTypedMessagesFactory aTypedMessagesFactory = new DuplexTypedMessagesFactory();
IDuplexTypedMessageReceiver aMessageReceiver
= aTypedMessagesFactory.CreateDuplexTypedMessageReceiver();
// Subscribe to receive messages.
aMessageReceiver.MessageReceived += OnMessageReceived;
// Create input channel that will listen messages via TCP.
IMessagingSystemFactory aTcpMessaging = new TcpMessagingSystemFactory();
IDuplexInputChannel anInputChannel = aTcpMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8001/");
// Attach the input channel to the message receiver and start listening.
aMessageReceiver.AttachDuplexInputChannel(anInputChannel);
// Console.WriteLine("TCP service is running. To stop press ENTER.");
// Console.ReadLine();
// Detach the input channel and stop listening.
aMessageReceiver.DetachDuplexInputChannel();
}
private void OnMessageReceived(object sender, TypedRequestReceivedEventArgs e)
{
// Display receive message.
// Send back simple response.
string aResponseMessage = "Thanks for " + e.RequestMessage;
IDuplexTypedMessageReceiver aReceiver
= (IDuplexTypedMessageReceiver)sender;
aReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
MessageBox.Show(e.RequestMessage );
}
private void InvokeInUIThread(Action uiMethod)
{
if (InvokeRequired )
{
Invoke(uiMethod);
}
else
{
uiMethod();
}
}
}
}
Thnx.
Hi Thabo,
DeleteI have just posted a new article: WinForm Application as Service.
http://eneter.blogspot.de/2014/05/winform-application-as-service.html
Please check that article. It is an example how to implement service as a WinForm application.
Please try to implement your service according to that article. If you have still problems I will then check your code.
Hi Ondrej
DeleteThanks a lot for this, it really helped me a lot.
Much much appreciated.
and a follow up question, how would I catch the Ondisconnect event on the android side, I want to be able to show a notification if there was a network interruption of some sort so that I can try to reconnect.
Thanks once again.
Hi Thabo,
DeleteThe easiest way to subscribe connectionClosed event. You can check the following API:
http://www.eneter.net/OnlineHelp/EneterMessagingFrameworkJava/eneter/messaging/endpoints/typedmessages/IDuplexTypedMessageSender.html
There are also more sophisticated ways but I do not want to go to details in case they are not needed.
Hi, I appreciate your work really. I need to send a string response message instead of length. MyResponse doesn't to this i think. Is there a way to do this
ReplyDeleteIf your response is a string then you also can declare the message sender and receiver like this:
DeleteIn Android client:
// Sender sending MyRequest and as a response receiving String.
private IDuplexTypedMessageSender mySender;
and then the corresponding declaration in .NET service:
private static IDuplexTypedMessageReceiver myReceiver;
Hi again Ondrej, and in the case if you wanna send an image? what would you have to declare? and how would you send the image from the android side? or the other way around?
DeleteThanks
Hi Thabo, I would recommend to declare it like byte array byte[].
DeleteHowever the problem is that if you use the default XML serializer then it convert these bytes to string (depending on size image) can be an overhead.
To avoid this I see two alternatives:
1. Using directly duplex channels
To avoid serialization/deserialization you can communicate directly via duplex channels (instead of DuplexTypedMessageSender/Receiver).
Duplex channels are able to send and receive byte[] or string without serialization.
2. Using Protocol Buffer serializer
You can still use DuplexTypedMessageSender/Recevier but then I would recommend to use Protocol Buffer serializer - the cross-platform binary serializer developed by google.
For more details how to use it with Eneter you can check:
http://www.codeproject.com/Articles/640249/Android-Fast-Communication-with-NET-Using-Protocol
Hi Ondrej,
ReplyDeleteI'm a big fan of your amazing work. I am trying this technique and unfortunately nothing is being done. I do not even get the message that the connection wasn't established. I eliminated the router to see if it was causing the problem but the problem still persists. I changed both the input and output IP's to the network IP of my computer.
Would appreciate if you help me :)
Thanks
Please help me!
ReplyDeleteWhen I run example, it work.
But I run real device, I change ip to "tcp:/192.168.1.135:8060/" on android device and application c#, it do not run.
Sorry if my English Skill is not good.
Hi,
ReplyDeletePlease advise what is the best scenario to create chat service between Android as a client and asp.net as another client?
Could you please help.
Thank you.
Hi Mohamed,
DeleteIf I understand correctly you would like to have a chat feature between your Android application and a WebPage based on ASP.NET.
Here are several advises.
The easiest way is to do it using the DuplexBroker eneter component. It would work like this. Your chat clients will subscribe in Broker for chat messages. Then when a user writes a message the client will send it to the broker. The broker will take the message and forwards it to other subscribed client.
Here is the example how to use broker from the web-page:
http://www.codeproject.com/Articles/768473/HTML-Real-Time-Push-Notifications-from-NET-Applic
Here is the example how to use broker from Android:
http://www.codeproject.com/Articles/433513/Android-How-to-Receive-Notification-Messages-from
Hello Sir , thank you for your wonderful work it really works
ReplyDeletebut do you have example on using .net as client and android as server ?
Thank you,
Bong
Hi Teofilo, Currently I do not have such example.
DeleteHowever I am currently preparing a new article which will show such scenario.
Hello sir ,i have received this Exception .when start communication. plz help
ReplyDelete"failed to send the request message because it is not attached to any duplex output channel"
You provided very little information so it is difficult to say what can be a problem.
DeleteHowever the most common problem is using incorrect IP addresses. So in case you use a real Android device please be sure your service listens to an IP address which is assigned to that machine within the network (not 127.0.0.1). And then your Android client needs to open the connection exactly to that address too.
How I can reconnect to .NET server from Android client if I loose the connection?
ReplyDeleteYou will have to monitor your connection and reconnect when is broken. better there is a sample application for communicating over unstable network in the Examples found in the offline documentation.
Delete