Click here to Skip to main content
Click here to Skip to main content

Android: How to communicate with .NET application via TCP

By , 9 Dec 2012
 

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 bellow uses Eneter Messaging Framework making 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. More detailed technical info can be found at technical info.)

340714/CommunicationBetweenAndroidandNET.png

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!
  2. 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"/>

    An 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>
  3. The IP address 127.0.0.1 (loopback) cannot be set on the Android emulator to communicate with the .NET application!
  4. 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.

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:

340714/AndroidCommunicatesWithNetUI.jpg

License

This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)

About the Author

Ondrej_Uzovic
Architect
Slovakia Slovakia
Member
No Biography provided

Sign Up to vote   Poor Excellent
Add a reason or comment to your vote: x
Votes of 3 or less require a comment

Comments and Discussions

 
You must Sign In to use this message board.
Search this forum  
    Spacing  Noise  Layout  Per page   
AnswerRe: I use simulator,but does not work.memberOndrej_Uzovic31 Dec '12 - 23:19 
I am not sure if it is your case too, but this issue can also occur if the eneter library was not added to the project correctly.
 
Please make sure you added it this way:
Please be sure you added the library this way:

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 this will help.
GeneralMy vote of 5memberSerguei_Ko13 Dec '12 - 22:10 
Interesting article!
GeneralMy vote of 5memberchristoph brändle11 Dec '12 - 23:21 
good example of the broad usage of this framework, it is awesome, a real alternative to WCF Smile | :)
GeneralMy vote of 5memberURVISHSUTHAR9 Dec '12 - 20:29 
awesome
QuestionLaunch in Android SDKmemberBOWLINGBALL4 Dec '12 - 11:44 
The .Net side is up and running nicely.
I have all the framework, albeit it is version 4.2.0 whereas the code was written in 4.0.0
Have the latest SDK for Android and the Eneter jar referenced in the library
Checked the config xml to ensure internet access
Upon launching the code crashes Hard - critical failure in Main.
 
Any hint woudl be appreciated
AnswerRe: Launch in Android SDKmemberOndrej_Uzovic5 Dec '12 - 8:36 
Hi Bowlingball, your post does not contain details about the failure, so I could not investigate in detail.
 
But I guess the problem could be the eneter library was incorrectly added to the project and so you can build but when you execute it the application failes with errors indicating that something cannot be resolved.
 
Please be sure you added the library this way:
 
1. Right click on the android project -> New -> Folder, create folder libs
3. Right click on the android project -> Import... -> File System
4. In the section 'From directory' click 'Browse...' button and select directory with the eneter library
5. Select the eneter library in the list
6. In the section 'Into folder' click 'Browse...' and select your libs directory
7. Click 'Finish'
8. The eneter library should be now listed under 'Android Dependencies'
9. try to compile ans run your application
 
I hope this will help.
GeneralRe: Launch in Android SDKmemberBOWLINGBALL7 Dec '12 - 7:27 
I added the library per your advice. Thanks, I did not use that method prior.
 
I have no errors, just 3 warnings in the AndroidManifest.xml in regards to 'no grammar constraints (DTD or XML schema) detected for the document.
 
I run and the emulator opens on port 5554.
 
It loads the 'HOME' successfully then sits there for 5 minutes and the console returns:
 
[2012-12-07 13:23:37 - Unexpected error while launching logcat. Try reselecting the device.] device not found
com.android.ddmlib.AdbCommandRejectedException: device not found
at com.android.ddmlib.AdbHelper.setDevice(AdbHelper.java:752)
at com.android.ddmlib.AdbHelper.executeRemoteCommand(AdbHelper.java:373)
at com.android.ddmlib.Device.executeShellCommand(Device.java:462)
at com.android.ddmuilib.logcat.LogCatReceiver$1.run(LogCatReceiver.java:110)
at java.lang.Thread.run(Unknown Source)
GeneralRe: Launch in Android SDKmemberOndrej_Uzovic8 Dec '12 - 8:54 
I have not experienced this issue. I have tried to google for it and I found the following links that could be helpful:
 
http://spacetech.dk/eclipse-android-unexpected-error-while-launching-logcat.html
http://stackoverflow.com/questions/8075378/logcat-console-stopped-working-with-eclipse-android-emulator
http://stackoverflow.com/questions/9106659/activity-refuses-to-start
GeneralRe: Launch in Android SDKmemberBOWLINGBALL7 Dec '12 - 11:22 
I've narrowed it down to 3 things:
a) the layout was/is not compatible with the latest SDK. I rebuilt it with the same fields as your example.
b)There is one portion of the code that are failing, causing an 'unfortunately, Androidnetcommunicationclient has stopped ' error
it is:
 

private EventHandler> myOnResponseHandler

= new EventHandler>()
{
@Override
public void onEvent(Object sender,
TypedResponseReceivedEventArgs e)
{
onResponseReceived(sender, e);
}
};
GeneralRe: Launch in Android SDKmemberOndrej_Uzovic8 Dec '12 - 9:03 
It is not quite clear from your post how the failure occurs (the exception stack would be very useful here).
There are 2 small issues I am aware of:
 
1. The onDestroy() method does not call super.onDestroy() what causes 'unexpected failure' error when closing the application. (I think that maybe this could be the problem you refer to.)
2. The openConnection() method is called from the main thread what causes the problem for Android 3.1 (Honeycomb) or higher where certain IO operations are not allowed from the main thread.
 
I have corrected both issues and updated the article. Please, feel free to download updated example. I hope it could help.
GeneralRe: Launch in Android SDKmemberBOWLINGBALL10 Dec '12 - 11:44 
This version compiles to the emulator.
 
The Eneter groups sends 2 .jar files. You only need to import one of them. Importing both produces a DEX error.
 
Thanks for all the help. It is not talking to the service, but I'm sure that is an IP issue.
 
update: I set the IP address to the physical address of the machine, which is running the .net app and pay dirt. Works great.
 
Again thanks
GeneralRe: Launch in Android SDKmemberOndrej_Uzovic11 Dec '12 - 8:23 
I am glad it works for you.
If you had further questions feel free to ask.
GeneralRe: Launch in Android SDKmemberBOWLINGBALL11 Jan '13 - 11:27 
Not sure if you receive the email I just sent. Please confirm
GeneralRe: Launch in Android SDKmemberOndrej_Uzovic11 Jan '13 - 20:21 
Yes, I had received e-mail from you regarding using in VB.
I am not an expert in VB but I will try to response.
GeneralMy vote of 5memberManar Ezzadeen17 Nov '12 - 9:19 
nice article
QuestionHelp needed !! [modified]memberseanmir13 Nov '12 - 7:37 
I've copied your code but my android app won't send anything !! at least c# app won't show anything !!
what should I do ?!
 

I did put a breakpoint in onclick event but it seems that the event not firing at all , so my onclick event not working !!! why ?!!! any idea
 
thank you so much

modified 13 Nov '12 - 13:59.

AnswerRe: Help needed !!memberOndrej_Uzovic13 Nov '12 - 21:41 
Hi Seanmir,
Do you observe any exception?
 
The most common problem is related to using correct IP addresses. The example uses IP address suitable for the simulator. In case you try the example on a real device please be sure you use the real IP address of the machine where your .NET application is running.
It means, you must change the IP address in the .NET application from 127.0.0.1 to the network IP address of that machine. And then uou also must use the same IP address in your Android client application.
GeneralRe: Help needed !!memberseanmir13 Nov '12 - 23:59 
Thank you for your Reply ,
I solved my problem , the @override was the problem
 
 private OnClickListener myOnSendRequestClickHandler = new OnClickListener()
    {
        @Override
        public void onClick(View v)
        {
            onSendRequest(v);
        }
    };
I changed it to this
 
   private OnClickListener myOnSendRequestClickHandler = new OnClickListener()
    {
        public void onClick(View v)
        {
            onSendRequest(v);
        }
    };
 
and now it's working perfectly , Thank you so much for your code
 
I'm trying to send string messages from android device to a .net app and .net app will sends back strings too . can you write any separate function for using in android , I mean just call a function for sending and receiving , like this :
 
private void Sendmessage(string message)
   {
    ----
    ----
    ----
   }
 

private String getmessage()
   {
    ----
    ----
    ----
   }
 
any help would be soooo helpful , thank you so much again.
GeneralRe: Help needed !!memberOndrej_Uzovic14 Nov '12 - 22:03 
Regarding the
@override
issue, please check the following link:
http://stackoverflow.com/questions/987973/why-does-eclipse-complain-about-override-on-interface-methods
 
If you want to use string messages, you can use the communication functionality from the example as it is but:
 
instead of IDuplexTypedMessagesFactory use IDuplexStringMessagesFactory,
instead of IDuplexTypedMessageSender use IDuplexStringMessageSender,
and instead of IDuplexTypedMessageReceiver use IDuplexStringMessageReceiver.
 
For more details here is the online help for Java:
http://www.eneter.net/OnlineHelp/EneterMessagingFrameworkJava/eneter/messaging/endpoints/stringmessages/package-summary.html
and here for .NET:
http://www.eneter.net/OnlineHelp/EneterMessagingFramework/html/N_Eneter_Messaging_EndPoints_StringMessages.htm
 
I hope my answer will help.
GeneralThat's what i am looking for.memberwreid16 Oct '12 - 23:52 
Hi Ondrej
 
well done, all five of my. Smile | :)
GeneralMy vote of 5mvpKanasz Robert23 Sep '12 - 3:17 
another good one
QuestionIn 20 minutes to successmemberMember 87928464 Aug '12 - 11:54 
It is beautiful and rare that a tutorial program runs without problems. Big Grin | :-D
AnswerRe: In 20 minutes to successmemberOndrej_Uzovic5 Aug '12 - 2:05 
I am really glad I found it easy to use.
QuestionError:memberIBR_BAR29 Apr '12 - 12:54 
Thank you for the article
I have tested the the example you descripe using EClipse and sdk android 2.3.3
I always get the message "The application androidNetComunicationClient (process net.client) has stopped unexpectedly.Please try again"
I have tried every thing but i still get this message.
Please help me
 
With Regards.
BugRe: Error:membermitnick90230 Apr '12 - 6:21 
I got that error too... where are we wrong?
 
I'm trying it on a Galaxy S2...
 
the compiler enforce me to remove @override in those statements
 
private void onResponseReceived(Object sender, final TypedResponseReceivedEventArgs 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> myOnResponseHandler

= new EventHandler>()
{
@Override
public void onEvent(Object sender,
TypedResponseReceivedEventArgs e)
{
onResponseReceived(sender, e);
}
};

private OnClickListener myOnSendRequestClickHandler = new OnClickListener()
{
@Override
public void onClick(View v)
{
onSendRequest(v);
}
};
}
 
Please help me...
GeneralRe: Error:memberOndrej_Uzovic30 Apr '12 - 7:34 
This problem can occur in Eclipse if the java compiler level is not set to Java 1.6.
 
Please select your android project in Eclipse and open its properties.
Then ensure, Compliance compiler level is set to 1.6.
 
More info about this can be found also here:
http://stackoverflow.com/questions/4761888/override-annotation-error-android-prefs
http://stackoverflow.com/questions/3735661/bug-with-override-annotations-in-eclipse
http://stackoverflow.com/questions/1678122/must-override-a-superclass-method-errors-after-importing-a-project-into-eclips
 
I hope this will help.
GeneralRe: Error:membermitnick9022 May '12 - 12:22 
Thank for your help... i didn't try your solution yet... but i surely do it soon! And i will post if it's successful... thank again
AnswerRe: Error:memberOndrej_Uzovic30 Apr '12 - 7:39 
I would like to ask if this is the same issue as reported by mitnick902 (see bellow)
If it is not the same problem, could you please provide me more details?
AnswerRe: Error:memberMember 896983911 Jul '12 - 6:47 
when I try to .Net via C# I got these error lines
 
The type or namespace name 'TypedRequestReceivedEventArgs' could not be found (are you missing a using directive or an assembly reference?)
 
The type or namespace name 'IDuplexTypedMessageReceiver' could not be found (are you missing a using directive or an assembly reference?)
 
The type or namespace name 'Eneter' could not be found (are you missing a using directive or an assembly reference?)
 
The type or namespace name 'Eneter' could not be found (are you missing a using directive or an assembly reference?)
 
The type or namespace name 'Eneter' could not be found (are you missing a using directive or an assembly reference?)
GeneralRe: Error:memberOndrej_Uzovic11 Jul '12 - 8:53 
Hello,
To be able to build examples you must download libraries from http://www.eneter.net/ProductDownload.htm[^] and add their references into the downloaded example projects.
 
Eneter for .NET in Visual Studio:
1. open the project
2. right click on 'References' and then choose 'Add References...'
 
Eneter for Android in Eclipse:
1. right click on the project and choose 'Properties'
2. click on 'Android' and add the library to the Reference|Project table bellow.
(Note: 'Is library' must stay unchecked.)
Questionexample Project SimpleTcpmemberroberto.reff12 Apr '12 - 5:39 
Hi Ondrej.
 

We have tested your SimpleTcp example. Works well! Smile | :)
 
Of course we played with the code and have tried to add features.
Like an second service on "server" side.
 
But it seems per service a single CreateDuplexInputChannel have to created as well. Is this right?
 
(Find below our enhanced implementation.)
 

Regards
Roberto
 

 

<pre lang="c#">
    public class TestRequest
    {
        public int Id { get; set; }
        public string Name { get; set; }
    }
 
    public class TestResponse : TestRequest
    {
        public bool Done { get; set; }
    }
 
    class Program
    {
        static void Main()
        {
            // Create message receiver.
            // It receives string and responses also string.
            var aTypedMessagesFactory = new DuplexTypedMessagesFactory();
            var aMessageReceiver = aTypedMessagesFactory.CreateDuplexTypedMessageReceiver<string, string>();
            var aMessageReceiverTypedSolution = aTypedMessagesFactory.CreateDuplexTypedMessageReceiver<TestResponse, TestRequest>();
            
            // Subscribe to receive messages.
            aMessageReceiver.MessageReceived += OnMessageReceived;
            aMessageReceiverTypedSolution.MessageReceived += OnMessageReceive;
 
            // Create input channel that will listen messages via TCP.
            var aTcpMessaging = new TcpMessagingSystemFactory();
            var anInputChannel = aTcpMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8055/");
 
            // Attach the input channel to the message receiver and start listening.
            aMessageReceiver.AttachDuplexInputChannel(anInputChannel);
            aMessageReceiverTypedSolution.AttachDuplexInputChannel(anInputChannel);
 
            Console.WriteLine("TCP service is running. To stop press ENTER.");
            Console.ReadLine();
 
            // Detach the input channel and stop listening.
            aMessageReceiver.DetachDuplexInputChannel();
            aMessageReceiverTypedSolution.DetachDuplexInputChannel();
        }
 
        private static void OnMessageReceived(object sender, TypedRequestReceivedEventArgs<string> e)
        {
            // Display receive message.
            Console.WriteLine("Received message: " + e.RequestMessage);
 
            // Send back simple response.
            var aResponseMessage = "Thanks for " + e.RequestMessage;
            var aReceiver = (IDuplexTypedMessageReceiver<string, string>) sender;
 
            aReceiver.SendResponseMessage(e.ResponseReceiverId, aResponseMessage);
        }
 
        private static void OnMessageReceive(object sender, TypedRequestReceivedEventArgs<TestRequest> e)
        {
            // Display receive message.
            Console.WriteLine("Received message: " + e.RequestMessage.Name);
 
            // Send back simple response.

            var aReceiver = (IDuplexTypedMessageReceiver<TestResponse, TestRequest>)sender;
 
            aReceiver.SendResponseMessage(e.ResponseReceiverId, new TestResponse{Done = true, Id = e.RequestMessage.Id, Name = e.RequestMessage.Name});
        }
    }

AnswerRe: example Project SimpleTcpmemberOndrej_Uzovic13 Apr '12 - 3:54 
Hi Roberto,
You have two possibilities how to create a service processing multiple requests:
 
Alternative 1: Multiple channels
You will create multiple DuplexTypedMessageReceiver and to each one you will attach a different duplex input channel. Each duplex input channel must listen to a different port.
using System;
using Eneter.Messaging.EndPoints.TypedMessages;
using Eneter.Messaging.MessagingSystems.MessagingSystemBase;
using Eneter.Messaging.MessagingSystems.TcpMessagingSystem;
 
namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            // TCP messaging.
            IMessagingSystemFactory aTcpMessaging = new TcpMessagingSystemFactory();
 
            // Create factory for receivers.
            IDuplexTypedMessagesFactory aReceiverFactory = new DuplexTypedMessagesFactory();
 
            // Create 1st receiver receiving 'string' and responding 'int'.
            IDuplexTypedMessageReceiver<int, string> aReceiver1
                = aReceiverFactory.CreateDuplexTypedMessageReceiver<int, string>();
            aReceiver1.MessageReceived += OnReceiver1_MessageReceived;
 
            // Attach receiver 1 to the input channel and start listening.
            IDuplexInputChannel anInputChannel1
                = aTcpMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8055/");
            aReceiver1.AttachDuplexInputChannel(anInputChannel1);
 
            // Create 2nd receiver receiving 'int' and responding 'string'.
            IDuplexTypedMessageReceiver<string, int> aReceiver2
                = aReceiverFactory.CreateDuplexTypedMessageReceiver<string, int>();
            aReceiver2.MessageReceived += OnReceiver2_MessageReceived;
 
            // Attach receiver 2 to the input channel and start listening.
            // Note: Receiver 2 listens to different port!
            IDuplexInputChannel anInputChannel2
                = aTcpMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8056/");
            aReceiver2.AttachDuplexInputChannel(anInputChannel2);
 
            Console.WriteLine("Service is listening. Press enter to stop.");
            Console.ReadLine();
 
            // Detach input channel to stop listening.
            // Note: it releases listening threads.
            aReceiver1.DetachDuplexInputChannel();
            aReceiver2.DetachDuplexInputChannel();
        }
 
        static void OnReceiver1_MessageReceived(object sender, TypedRequestReceivedEventArgs<string> e)
        {
            // Some processing of request 1.

            // Sending response back to the client. The response is 'int'.
            IDuplexTypedMessageReceiver<int, string> aReceiver
                = (IDuplexTypedMessageReceiver<int, string>)sender;
            aReceiver.SendResponseMessage(e.ResponseReceiverId, 12345);
        }
 
        static void OnReceiver2_MessageReceived(object sender, TypedRequestReceivedEventArgs<int> e)
        {
            // Some processing of request 2.

            // Sending response back to the client. The response is 'string'.
            IDuplexTypedMessageReceiver<string, int> aReceiver
                = (IDuplexTypedMessageReceiver<string, int>)sender;
            aReceiver.SendResponseMessage(e.ResponseReceiverId, "12345");
        }
    }
}
 
Alternative 2: One channel
If you prefer to route all requests via one IP address and port you can use components DuplexChannelWrapper (on client side) and DuplexChannelUnwrapper (on server side).
So, the client would have multiple DuplexTypedMessageSender connected via channels to the DuplexChannelWrapper. And the service would have DuplexChannelUnwrapper listening to one IP address and port and routing incoming messages to matching DuplexTypedMessageReceiver.
 
I am going to write a separate article about this topic with an example for Android and .NET.
 
You also can check one of my previous articles showing this scenario (it is only for .NET but the implementation for Java (Android) will be same):
How to Implement Service Receiving Requests via Messages[^]
GeneralRe: example Project SimpleTcpmemberroberto.reff13 Apr '12 - 10:26 
Hi Ondrej.
 

Ok. I will check this ans think about.
 
Will come back later, sure with some new questions Wink | ;-)
 

Regards
Roberto
QuestionReal situationmemberjirkaM15 Mar '12 - 0:40 
How to communicate in real situation through WiFi between android mobile device and comuter (especially concerning addresses of devices) ? Thank You, jirkaM.
AnswerRe: Real situationmemberOndrej_Uzovic16 Mar '12 - 21:48 
Yes, the real situation requires using real IP addresses.
It means, the following line in the service code must be replaced with the real IP address and port the service is using.
IDuplexInputChannel anInputChannel = 
               aMessaging.CreateDuplexInputChannel("tcp://127.0.0.1:8060/");
Then you also need to use the correct IP address in your Android client application. You must replace the following line with the same real IP address and port as used in the service.
IDuplexOutputChannel anOutputChannel = 
           aMessaging.createDuplexOutputChannel("tcp://10.0.2.2:8060/");
 
The communication scenario described in this article does not require to know the IP address of the cell phone device.
 
When you have set correct addresses the communication between real Android device and service should be same as described in the article.
QuestionRe: Real situationmemberdragpre21 Aug '12 - 2:21 
I want to connect Android device to desktop via USB and without WiFi?
What IP addresses (and ports) should I set in that case in both modules?
AnswerRe: Real situationmemberOndrej_Uzovic21 Aug '12 - 10:53 
Hi Dragpre,
 
The communication via the cable is not so straight forward as using WiFi.
The problem is, the communication via the cable involves Android Bridge running on PC that must be configured and there is also a technical limitation that the android device must be a service when communicates via the cable.
 
Android Bridge
Android Bridge is the application that starts on your PC once your device is connected via the cable (There is adb.exe process in Task Manager).
On the other side of the cable (in the Android device) is running Android Bridge Daemon (process adbd).
The sequence for the communication via the cable looks like this:
  1. Your desktop application sends the message to the Android Bridge via TCP.
  2. Android Bridge (adb.exe running on PC) receives the message and using some internal protocol sends it via the cable to the Android device.
  3. Android Bridge Daemon running on the device receives the message and forwards it via TCP to the listening Android application.
  4. Android application processes the message and can send back a response message.
 
Technical Limitation
The technical limitation for communication via the cable is the Android device must be a service. It means, the android cell-phone must be a listener serving requests from the PC.
Please notice, it is exactly opposite as in the example from my article where the Android application is the client. You must use 'MessageReceiver' and 'DuplexInputChannel' in the Android application to listen to messages.
 
Example how to do it
If you want to setup the communication via the cable you must:
  1. Implement your android application as the service. It means your android application must be the listener receiving messages. Duplex input channel must listen to 127.0.0.1 (loopback in the phone) on the port you will choose e.g. 8090. Therefore the address will be: tcp://127.0.0.1:8090/
  2. You must implement your desktop application as the client sending messages to 127.0.0.1 (loopback in PC) and again you can choose your own port. E.g. you can use the same port 8090. Therefore the address the client will use for the communication will be tcp://127.0.0.1:8090/.
  3. You must configure Android Bridge to forward messages to the Android device. You can use for this the following command.
    adb forward tcp:8090 tcp:8090
    (you can find adb.exe on the following path: c:\Program Files\Android\android-sdk\platform-tools\adb.exe)
    It tells Bridge that adb.exe shell listen to the port 8090, then forward it via the cable to the device and then inside the device forward it again to the port 8090.
 
So here is the summary how the communication will look like for our example:
  1. Desktop client application sends a message to 127.0.0.1:8090.
  2. adb.exe running on PC receives the message on 127.0.0.1:8090 and forwards it via the cable to adbd.
  3. adbd running on the device receives the message and sends it to 127.0.0.1:8090.
  4. android application listening to 127.0.0.1:8090 receives the message.
 
I hope my answer will help.
(Maybe I could write another article explaining the communication scenario via the cable in detail.)
QuestionAndroid Sync'd to PC apps and viceversamemberchaq6868 Mar '12 - 10:03 
First of all let me congrats you for your article, might be useful in the future. My question is, there any way to connect an Android app to any other PC program through synchronization? If there is, what topics, books or websites should I check?
 
Thanks.
AnswerRe: Android Sync'd to PC apps and viceversamemberOndrej_Uzovic8 Mar '12 - 10:45 
Hi Chaq686, I am not sure if I understand your question. Could you please e-mail me more details about your communication scenario?
I will try to support you.
GeneralRe: Android Sync'd to PC apps and viceversamemberchaq6869 Mar '12 - 13:14 
Basically is doing the same thing, but through USB cable instead of TCP/IP.
GeneralRe: Android Sync'd to PC apps and viceversamemberOndrej_Uzovic16 Mar '12 - 21:55 
I have e-mailed with chaq686:
The following article is very close to his needs:
http://www.anothem.net/archives/2010/02/15/communicating-over-the-usb-cable/
 
And here is the code the author of the article used.
http://www.anothem.net/archives/2010/10/15/android-usb-connection-to-pc/
Questionwake locks and stuff...memberSelvin5 Mar '12 - 21:30 
first
The IP address 127.0.0.1 (loopback) cannot be used for communication between the Android emulator and the .NET application!
 
this is not true ... you can use 127.0.0.1 on PC ... but on android ... on android you should first you read documentation: Network Address Space(android emulator)[^]
 
anyway:
 
Duplex means that we can send messages from both sides, right? Ok, so it keeps TCP connection alive. And now we come to real question: should we use wake lockcs[^] to keeps this connection online(and drain battery in few hours)? Another option is: don't use this lib on Android platform at all and take advantage of C2DM and use some stateless connetion(like http/https) for communication.
...works fascinates me...i can stare it for hours...

AnswerRe: wake locks and stuff...memberOndrej_Uzovic6 Mar '12 - 10:08 
Hi Selvin, thanks for your comment regarding the IP address. It is a valid point and I will update the article.
 
Regarding the second part of your response. I think it is a matter of the application design how long the connection stays open. For many communication scenarios it is probably possible to design it the way the connection does not need to stay open for hours - eneter library allows users to open/close connections as needed.
E.g. In case of a typical request-response scenario, the client can open the connection only for necessary time ...
 
The C2DM framework is an interesting project but it is not designed to transfer a lot of user content. It is intended just to let the client know there is some content on the server. The application should then connect its server and make its own communication to get the content. It has quotas related to number of messages you can send and the maximum size of the message (I think 1024 bytes). The communication depends on the Google server. => C2DM is a different thing focusing on a certain scenario.
Questionlicensemembersmalltide5 Mar '12 - 16:57 
It's a very good article!
 
I have a question about license.
 
What is the license of "Eneter Messaging Framework"?
Can I use it in my project?
AnswerRe: licensememberOndrej_Uzovic5 Mar '12 - 20:46 
I am glad you like the article.
The framework is free for non-commercial use. For more details you can refer here.
QuestionQuestionmemberPatrick Harris5 Mar '12 - 16:36 
What did you use to create that beautiful illustration at the top of the article showing the communication channel between Android and .NET?
AnswerRe: QuestionmemberOndrej_Uzovic5 Mar '12 - 20:39 
The illustration was created in Adobe Illustrator. I am glad you like it Smile | :) .

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Rant Rant    Admin Admin   

Permalink | Advertise | Privacy | Mobile
Web03 | 2.6.130516.1 | Last Updated 9 Dec 2012
Article Copyright 2012 by Ondrej_Uzovic
Everything else Copyright © CodeProject, 1999-2013
Terms of Use
Layout: fixed | fluid