Welcome!

Welcome to the official BlackBerry Support Community Forums.

This is your resource to discuss support topics with your peers, and learn from each other.

inside custom component

Java Development

Reply
New Contributor
Posts: 6
Registered: ‎10-17-2012
My Device: BB10 Dev Alpha
My Carrier: Vodacom
Accepted Solution

Completely closing SocketConnections properly

Hi,

 

I am having an issue with a persistent socket connection not closing properly (at least I think that is what the problem is). Here is my scenario:

 

I have an iPad, which has an app that listens for incomming socket connections, and responds when required (I am not in control of this app). Then I have the BB side. The general idea is, I try to open a connection, over WiFi, to a specific IP address. If this is successful, I open an InputStream and an OutputStream. A couple of messages are sent back and forth between the two devices (starting with a read on the InStream - from the BB perspective), and then we wait. Either the iPad or the BB can then initiate more communication. When not communicating, both are waiting. The streams are never closed, unless the BB or iPad exits, in which case both are closed, along with the connection.

 

My problem is this: If I close the BB app, and shut down the device (i.e. ensure the app is completely closed, and not just out of focus), then the next time I want to create a connection, it just sits forever. I get a General socket error (IOException) after about 30s. I have to reboot the iPad, and start again for it to work again. So it seems that either the BB is not completely closing the connection, or the iPad isn't cleaning up properly. As I am not in control of the iPad code, I can't confirm. However, I think it is from the BB side as there is an iOS and Android version of my BB app, and they don't have this issue.

 

I have also noticed that I get the message(s):

Detected background switch for APP_NAME(241) who has tunnel id=1mode=FG open - solomode NOT called

Detected background switch for APP_NAME(241) who has 1 tunnel(s) open - defocus called

when I close the app on the BB.

 

I am using the following code to close the connections/streams (and I make sure this is called when the app exits):

try {
				if (inStream != null) {
					inStream.close();
					inStream = null; 
				}
			} catch (Exception e) {
				System.out.println("Error closing instream: " + e.getMessage());
			}
			try {
				if (outStream != null) {
					outStream.close();
					outStream = null;
				}
			} catch (Exception e) {
				System.out.println("Error closing outstream: " + e.getMessage());
			}
			try {
				if (connection != null) {
					connection.close();
					connection = null;
				}
			} catch (Exception e) {
				System.out.println("Error closing connection: " + e.getMessage());
			}

 Another thing to note: I am doing things in synchronized blocks, when opening and closing connections. I am also doing all the networking on a separate Thread. I make sure that all exceptions related to this ensure the connections are closed. The connection, instream and outstream instances are class variables.

 

In a main loop, in the non-Main-Event-Thread, I check to see whether the connection is closed, if it is, I wait for a few seconds (Thread.sleep) and then try open the connection again. So I am continually polling the IP address.

 

If I never close the simulator/device then the connection seems to be able to connect/disconnect perfectly, with both apps open, then all closed and opened again, etc.

 

Is there something I should be aware of wrt closing the sockets out completely, cleaning up properly, using synchronized blocks, etc.?

 

I open the connection like this (all surrounded by try/catch/finally, and within a synchronized block):

				connection = (SocketConnection) Connector.open("socket://" + url + ";interface=wifi", Connector.READ_WRITE, true);
				inStream = connection.openInputStream();
				outStream = connection.openOutputStream();

 

Many thanks!

 

P.S. I have been googling/searching the forums for the past week, and haven't come any closer - hopefully I haven't missed anything.

 

Developer
Posts: 16,687
Registered: ‎07-29-2008
My Device: Z10 LE, Z30, Passport
My Carrier: O2 Germany

Re: Completely closing SocketConnections properly

welcome to the support forums.

very good first post, thank you for not just writing "I HAVE ERROR" :smileyhappy:

Unfortunately the networking framework on BB is more or less a secret to everybody. Your connection cleanup seems to be good.
Lets check some basics, if this doesn't help i'll see if i can get somebody higher up the food chain :smileywink:

Can you quote how you call your cleanup code when the application exits?
Please clarify "shut down the device": Do you do a hard off (battery pull) or a soft off (red key)?

and check if you can't switch your application to using (BIS) push, would save a lot of battery life. keeping connections open is kind of non-blackberry-y.
----------------------------------------------------------
feel free to press the like button on the right side to thank the user that helped you.
please mark posts as solved if you found a solution.
@SimonHain on twitter
New Contributor
Posts: 6
Registered: ‎10-17-2012
My Device: BB10 Dev Alpha
My Carrier: Vodacom

Re: Completely closing SocketConnections properly

[ Edited ]

Hi Simon. Thanks for your quick reply.

 

I've overriden the close method on the screen(s) I'm showing. Within these screens, I have a class variable, which handles all the socket comms (Communicator). I initialise this when the screen appears. the Communicator class's initialisation method creates the networking thread as I mentioned above. This may seem like overkill, but I do this so that I can pass the Communicator instance around from screen to screen, as required, so that I only havea  single Socket open at any stage.

 

Anyway, it is this that I check in the close method of the screen.

public void close() {
		if (communicator != null)
			communicator.closeCommunicator();
		super.close();
	}

 the closeCommunicator method looks as follows (there may be a bit of redunancy in this):

public void closeCommunicator()
    {
		try
		{
			comms.closeSocketConnection();
		}
		catch (Exception e) {
			System.out.println("Error closing comms socket connection: " + e.getMessage());
		}
		try
		{
			Thread temp = mainThread;
			mainThread = null;
			if (temp != null)
			{
				if (temp.isAlive())
					temp.interrupt();
				try
				{
					comms.closeSocketConnection();
				}
				catch (Throwable e)
				{
					System.out.println("Error closing comms socket connection in thread: " + e.getMessage());
				}
				temp = null;
			}			
		}
		catch (Exception e) {
			System.out.println("Error closing communicator: " + e.getMessage());
		}
    }

 The comms.closeSocketConnection is the close method I mentioned in my first post.

 

As far as shutting down the device is concerned, I'm mainly working with a simulator as this is easier to debug in my current setup. So this generally means exiting the simulator. I've tried exiting before closing the app, after, after closing the iPad, before, etc. etc. Nothing seems to make a lot of difference.

 

As far as using BIS is concerned: the function of this is to create geo-location functionality, using a WiFi network. When you have connected to it, the app searches for the iPad. If it finds it, it creates the connection. It mustn't work outside of the WiFi range. I know the persistence is not generally the way to go, but if you, at any point, close any of the streams, or the connection itself, the IPad forgets about you, and you need to start the initial handshake again. So the connection needs to be persistant.

New Contributor
Posts: 6
Registered: ‎10-17-2012
My Device: BB10 Dev Alpha
My Carrier: Vodacom

Re: Completely closing SocketConnections properly

I think I might kick myself just a little bit. I can't believe I didn't check this before. I installed wireshark to check what WAS going through, etc. I noticed that very little was coming or going from the iPad (even though it could browse the web, etc.) So I tried to do a simple ping from my machine. Nothing. WHAT? So I rebooted the iPad. It worked again... and then stopped?! So I rebooted the router... it kept working. And working... And working...

 

No doubt it will stop again. But it seems there may be nothing wrong with either the iPad or the BB at all. It could just be something iffy with my router! I... Can't... Believe! :Censored:

 

I will continue to look into it, and watch what happens... but in the mean time, I'm terribly sorry for wasting your time! *so embarrased*. Thanks for your help.

 

P.S. I know this is not the place for it, but if anyone has any ideas as to why this might happen, I'd be very grateful to know them. It has cost me quite a few days of wasted dev time.

Developer
Posts: 16,687
Registered: ‎07-29-2008
My Device: Z10 LE, Z30, Passport
My Carrier: O2 Germany

Re: Completely closing SocketConnections properly

good to know that you found the error.

regarding your close overwrite:
super.close calls System.exit if the screen is the last in the UiApplication.
The cleanup should be fine, but just to be on the safe side you may use a spawned thread to clean up.
I call requestBackground on my app and start a new Thread that does the cleanup, deregisters listeners and closes connections etc, and calls System.exit when it is done, after a small sleep for good measure.
As the networking framework is a black box on BB java you don't really know if you did not sit on the losing side of a racing condition.
I guess your code works good, it would be just another layer to be extra sure :smileyhappy:
----------------------------------------------------------
feel free to press the like button on the right side to thank the user that helped you.
please mark posts as solved if you found a solution.
@SimonHain on twitter
New Contributor
Posts: 6
Registered: ‎10-17-2012
My Device: BB10 Dev Alpha
My Carrier: Vodacom

Re: Completely closing SocketConnections properly

That's good to know. I think I'll take that advice, thank you!