Archived

This forum has been archived. Please start a new discussion on GitHub.

Android Emulator help

I'm having some trouble getting Ice to complete execution on a callback object when running an Android Client. I've run successful tests on a physical device (Sony S Tablet), but when I attempt running this on the emulator, calling a method on the callback proxy fails to complete.

I'm trying to run some traces too, but I'm not really sure I'm doing it correctly in my development environment. For my server program, I'm running MonoDevelop on Mac OS X, I'm still pretty new to Ice and new to the MonoDevelop IDE, I'm not even sure how the default logger will handle it. Here's my server code:
public void Init ()
{
        var props = new string[] {"Ice.Trace.Network=2", "Ice.LogFile=iceTracing.txt"};
        _Communicator = Ice.Util.initialize(ref props);
        _Adapter = _Communicator.createObjectAdapterWithEndpoints("TestServerEndPoint", "default -p 9990");
        Ice.Object serverObj = new ServerIceI(this);

        _Adapter.add(serverObj, _Communicator.stringToIdentity("TestServer"));
        _Adapter.activate();
}

public override void InitializeClientConnection(TestIce.ClientRelayPrx client, Ice.Current current__)
{
        _server.ReceiveClientCallback<TestIce.ClientRelayPrx>(client, current__.con.ice_toString_());
       // This method stores the proxy sent by the client for later access
}

public void OutputToClient (string message, string clientID)
{
     var clientProxy = _ClientProxies[clientID];
     clientProxy.SendMessageToClient(new TestIce.TextMessage { Text = message });
}
I'm not able to find iceTracing.txt on my drive when I shut down the server, I'm probably doing some wrong things here...

Here's the supporting code that runs on the Android client
public RPCIceService() {
		
	_communicator = Ice.Util.initialize();
	Ice.ObjectPrx proxy = _communicator.stringToProxy("TestServer: default -h 10.0.2.2 -p 9990");
	_serverProxy =  TestIce.ServerRelayPrxHelper.checkedCast(proxy.ice_twoway().ice_timeout(-1).ice_secure(false));
		
	_adapter = _communicator.createObjectAdapterWithEndpoints("TestAndroidEndPoint", "default -p 9991;
	_adapter.add(new ClientCallbackI(), _communicator.stringToIdentity("TestAndroidClient"));
	_adapter.activate();
		
	Ice.ObjectPrx clientProxy = _adapter.createProxy(_communicator.stringToIdentity("TestAndroidClient"));
	_clientProxy = TestIce.ClientRelayPrxHelper.uncheckedCast(clientProxy.ice_twoway());
	_serverProxy.InitializeClientConnection(_clientProxy);
}

synchronized public void sendMessage(String message) {
        _serverProxy.begin_SendCommandToServer(message);
}

The basic workflow is a message is sent by the android client via the sendMessage, it's received by the server and is processed in a new thread, then output is returned to the client from the OutputToClient method. When responding to the android emulator client, the server is unable to complete execution of clientProxy.SendMessageToClient (I suspect it's because I set timeout to -1?), but responding to a physical device completes as normal.

Any tips on why this might be occurring or how I can setup tracing properly in MonoDevelop for Mac?

thanks!
Dennis

Comments

  • xdm
    xdm La Coruña, Spain
    If you use a relative path for the log file, it is relative to the current working directory, when you start the server from command line, the log file should be saved in the directory from where you run the command.

    The problem with the emulator seems that the server is trying to connect to an unreachable endpoint without a timeout, when you use "default" the adapter include all available address interfaces, and some of then are not reachable from the server. You can set the PublishedEndpoints property in Android.
    TestAndroidEndPoint.PublishedEndpoints=tcp -h 10.0.2.15 -p 9991
    

    Here 10.0.2.15 is the Android emulator address , see Network Address Space in Using the Android Emulator | Android Developers

    In general will be a better approach to use bidirectional connections to communicate back with the device/emulator, your approach will not work well in presence of firewalls, and most of 3G providers block all inmcoming connections.
  • New issue?

    Thanks for the response, I'm working through the solutions you provided, but I've encountered an odd new issue. I included "Identity.ice" in my slice folder so that I could send an Identity object across to my server for the creation of a bidirectional connection. This prompted the need for me to check the "Enable ice" option in my slice2java properties->options in Eclipse. Just this change seems to have resulted in the "Conversion to Dalvik format failed with error 1" issue. I've researched this error and it seems to point to multiple copies of the Ice.jar file being referenced in the Java Build Path, but I'm not seeing where this occurs, the Build Path looks identical to when it did before I checked the "Enable ice" option.

    I can try simply passing the 'name' and 'category' properties and avoid the need for enabling the ice keyword, but I wanted to check if this is a known issue or if I'm making life more complicated than it needs to be?

    Thanks,
    Dennis
  • Properties not working?

    I think that one of the reasons I'm not seeing a trace file being created is I don't think I'm setting the properties correctly?

    The following code from the Android client has been modified with the suggestions above, but the call to ice_getConnection() always throws an Ice.CollocationOptimizationException. I've set the CollocationOptimized property to 0 and it's still happening, so I'm thinking the properties must be where I'm going wrong?
    String[] runtimeParams = new String[3];
    runtimeParams[0] = "TestAndroidEndPoint.PublishedEndpoints=tcp -h 10.0.2.15 -p 9991";
    runtimeParams[1] = "Ice.ACM.Client=0";
    runtimeParams[2] = "Ice.Default.CollocationOptimized=0";
    		
    _communicator = Ice.Util.initialize(runtimeParams);		
    
    Ice.ObjectPrx proxy = _communicator.stringToProxy("TestServer: default -h 10.0.2.2 -p 9990");
    _serverProxy = TestIce.ServerRelayPrxHelper.checkedCast(proxy.ice_twoway().ice_secure(false));
    		
    Ice.Identity callbackId = new Ice.Identity();
    callbackId.name = UUID.randomUUID().toString();
    		
    _adapter = _communicator.createObjectAdapter("");
    Ice.ObjectPrx clientProxy = _adapter.add(new ClientCallbackI(), callbackId);
    _adapter.activate();
    		
    clientProxy.ice_getConnection().setAdapter(_adapter);
    
  • xdm
    xdm La Coruña, Spain
    Hi Dennis,

    You don't need to include Identity.ice in your slice folder, the generated code for Identity.ice is already included by Ice.jar.

    If you want to use Ice::Identity in your Slice definitions, just add #include <Ice/Indetity.ice> in your Slice files.
  • xdm
    xdm La Coruña, Spain
    Hi Dennis,

    You are right, the properties are not correctly set, arguments must begin with --, that version of Ice.Util.initialize is mostly used to read the Ice command line arguments and convert it to properties.

    You can also use:
    Ice.InitializationData initData = new Ice.InitializationData();
    initData.properties = Ice.Util.createProperties();
    initData.properties.setProperty("TestAndroidEndPoint.PublishedEndpoints", "tcp -h 10.0.2.15 -p 9991");
    communicator = Ice.Util.initialize(initData);
    

    I think this second way is a bit more clear when you want to set the properties programmatically.
  • Ah, that explains where I was going wrong. I was expecting an exception if I'd entered the properties incorrectly, but I guess the Ice runtime would want to just ignore properties it didn't understand in favor of allowing the application to route them elsewhere as well.

    I followed the latter syntax above, which is definitely cleaner and I could tell the Ice runtime picked up the properties correctly as I received an UnauthorizedAccessException when it attempted to generate the log file for the server program. Guess I'm still used to the Full Trust environment developing in Windows; for the time being I just hardcoded the path to inside the app bundle. I'm still unable to kick this CollocationOptimizationException though. I even added the following code to the line before the ice_getConnection method call:
    clientProxy.ice_collocationOptimized(false);
    clientProxy.ice_getConnection().setAdapter(_adapter);
    
    ... but I still get the exception.
  • It works!

    Sorry, my mistake, I had to step back a moment and think on the code example. In the docs example written in C++, there's a "proxy" variable that isn't declared, and for some reason I just associated it to the clientProxy variable I'd created when the very thing I'm trying to do get rid of that proxy altogether. I substituted my _serverProxy variable in instead and the exception went away. Not only that, but the server is able to communicate with the Android client via the callback proxy it instantiates. It's all working now!

    Thanks!!
    Dennis
  • xdm
    xdm La Coruña, Spain
    Note that this line"
    clientProxy.ice_getConnection().setAdapter(_adapter);
    

    Should be:
    _serverProxy.ice_getConnection().setAdapter(_adapter);
    

    As you want to reuse the connection already opened to the server.

    Also note that proxy objects are immutable, when you call ice_collocationOptimized it returns a new proxy with this setting changed, so you should do:
    proxy = proxy.ice_collocationOptimized(false);
    ...
    

    See Proxy Methods - Ice 3.4 - ZeroC