I have a Bluetooth server receiving data from a client, a mobile phone. The code I’m using looks the following
@Override
public void run() {
try {
this.localDevice = LocalDevice.getLocalDevice();
this.localDevice.setDiscoverable(DiscoveryAgent.GIAC);
this.server = (StreamConnectionNotifier) Connector.open(URL);
while(true) {
if(this.connection == null) {
this.connection = this.server.acceptAndOpen();
System.out.println("INFO: Bluetooth client connected");
BufferedReader reader = new BufferedReader(new InputStreamReader(connection.openInputStream()));
this.writer = new BufferedWriter(new OutputStreamWriter(connection.openOutputStream()));
String line;
while((line = reader.readLine()) != null) {
if(line.equals("--#do:disconnect")) {
break;
}
System.out.println("INFO: Received from Bluetooth: " + line);
}
System.out.println("INFO: Client disconnected");
}
}
} catch(BluetoothStateException ex) {
ex.printStackTrace();
} catch(IOException ex) {
ex.printStackTrace();
}
}
As you can see, I have an infinitive loop receiving messages until it is told to stop. At the moment the loop receives all the messages. There is a problem with that. The class where the code is used is a model class in MVC. In the class I also have a method called getContacts(). It is used to receive contacts from the phone over Bluetooth. The phone is told to send the contacts when the server sends --#do:getcontacts.
What I need to do is to get the contacts in an ArrayList in the getContacts() method and return it as the return value of the method so that the controller can handle the contacts.
public ArrayList<Contact> getContacts() {
ArrayList<Contact> contacts = new ArrayList<>();
// How do I get the contacts in the ArrayList?
return contacts;
}
I’ll have you some suggestions. My examples are no working code, just a working base for you.
First, I strongly suggest you to use threads in a server. Everytime a clients connects to the server, you create a new thread, with parameters containing all data needed to start it:
And in the class ServerThread you implement these lines handling the clients (non-compiled code, without exception handling!):
What is the advantage of this code? Your server is now able to handle a thousand clients at the same moment. You’ve got parallelisation, and that’s how server usually work! A server without threads is like socks without shoes…
Second, if you have a Java client and a Java server, you can use a much easier way to send your objects to the server: ObjectOutputStream/ObjectInputStream. You just send the array (I’ll use an ArraList as it would be usual) containing the contacts to the server, and then you read the array. Here is the code for the server (again uncompiled and without any exception handling):
In Java, every class is an object, including ArrayList. And since the end of the object will be regarded as the disconnection, you won’t need to do anything else.
Third: You use above server not only for bluetooth connections, but also for WLAN connections, aso. Then you could easily start different threads, like in pseudo code
if(connection.isBluetooth()){//create a thread from BluetoothThread} else if(connection.isWLAN()){//create a thread from WLANsThread}. I don’t know what your app is about, but maybe one day you would like to expand it to desktop PC, so using WLAN would be the right thing. Also because you anyway need to build in a verification in the client (“which contacts are going to be sent to which server?”), no matter if it’s bluetooth or WLAN, because the low range of buetooth can’t give you any security. 😉Fourth, finally about your question: To get something, you need to have a data source and/or a class variable. Here a short example with a file that stores the contacts (but it could also be a database…local or somewhere else!):
Now in the server you just read out the contacts array as already I described above. What you do with those contacts, remains up to you.
Hope this helps you to understand your problems and find a solution. Programming is all about trial & error..and improving your code.
EDIT:
After our discussion I finally found out what you need: You need a one-thread server called BluetoothManager that interacts with another thread called GUIController. Now since I anyway did the implementation in my head, I can post it for you, together with some explanations. Just note that in this case you don’t need to initialize another thread in the server, since the BluetoothManager is already a thread, and you anyway need only one connection at the same moment (the question remains, if that is a “server”, I would rather call it a “receiver”):
The GUIController first runs the BluetoothManager with
startBluetoothManager()and does nothing else, except showing a notification “Receiving contacts” and an “Abort Reveiving”-button. And when the BluetoothManager is finished, he just adds the new contacts into the existing contacts-array inside the GUIController by callingrefreshContacts(...). If you push the “Abort Reveiving”-button, you immediately call theabortBluetoothManager()method, which setsrunning=falsein the BluetoothManager to end the server and finish the thread.The main problem this solution solves: It’s not possible for two threads to directly communicate with each other! Once you call
thread.start(), every thread is on its own. That’s why there is no possibility for the BluetoothManager-thread to tell the GUIController-thread “I’ve finished!”. The only thing those threads can do, is share the same ressource(s), and communicate via this ressource(s). In our case, it’s thecontacts-ArrayList in the GUIController, which first I thought needs to be synchronized and can be updated by both threads (but not on the same time). And – kind of funnyness – there is a second shared ressource, it’s actually therunningflag in the class BluetoothManager which can shut it down (but there is never any synchronisation ofrunningneeded, this variable is only changed by the GUIController).Now about the synchronisation: I thought about this problem more and understood, that you can solve your problem also without any “synchronized(…)” call. So, if you don’t want to synchronize the ArrayList, you must do it like this: While the server is running, you only show the “Receiving Contacts” pop-up and the “Abort Reveiving”-button. While this happens, you just never access the contact-ArrayList inside the GUIController. This is somehow an “intrinsic synchronisation” which needs no real Java synchronisation. Still you may implement synchronisation, just to be 100% sure that nothing happens if you expand the app in the future.