Android with AMQP - android

Im trying use use an AMQP message queue in one of my Android applications. I tested the code first in a java application and have no issues but when I put the same code into an Android app no error is thrown but the AMQP channel closes unexpectedly after the first message is received. I tried adding a shutdown listener to the channel but it didnt return anything. Can someone help me figure out why the Rabbitmq channel is closing?
// ------------------------------------------------------------------------
// Function to make AMQP connection and subscribe
// ------------------------------------------------------------------------
int connAmqp()
{
factory = new ConnectionFactory();
factory.setHost(PI_AMQP_BROKER_URL);
factory.setUsername(AMQP_BROKER_USERNAME);
factory.setPassword(AMQP_BROKER_PASSWORD);
factory.setPort(AMQP_BROKER_PORT);
connection=null;
connectionStatus = AMQP_CONNECTING;
try {
connection = factory.newConnection();
Log.i("log_amqp_conn","Successfully connected to AMQP broker");
connectionStatus = AMQP_CONNECTED;
channel = connection.createChannel();
channel.addShutdownListener(new ShutdownListener() {
#Override
public void shutdownCompleted(ShutdownSignalException cause) {
Log.w("log_amqp_shutdown",cause.getCause().toString());
}
});
channel.exchangeDeclare(AMQP_EXCHANGE_NAME, "topic");
Log.i("log_amqp_conn","Successfully connected to Exchange: " + AMQP_EXCHANGE_NAME);
channel.queueDeclare(RX_QUEUE_NAME, false, false, false, null);
String queueBind = RX_BINDING;
Log.i("log_amqp_conn","Successfully declared queue: " + RX_QUEUE_NAME);
channel.queueBind(RX_QUEUE_NAME, AMQP_EXCHANGE_NAME, queueBind);
Log.i("log_amqp_conn","Successfully binding to: " + queueBind);
} catch (TimeoutException e) {
Log.i("log_amqp_conn","Connection timeount - Failed to connect to AMQP broker");
Log.i("log_amqp_conn",e.toString());
connectionStatus = AMQP_NOTCONNECTED_TIMEOUT;
} catch (IOException e) {
Log.i("log_amqp_conn","Failed to connect to AMQP broker");
Log.i("log_amqp_conn",e.toString());
connectionStatus = AMQP_NOTCONNECTED_UNKNOWNREASON;
}catch (Exception e) {
Log.i("log_amqp_conn","Failed to connect to AMQP broker");
Log.i("log_amqp_conn",e.toString());
connectionStatus = AMQP_NOTCONNECTED_UNKNOWNREASON;
}
Log.i("log_amqp_conn"," [*] Waiting for messages.");
consumer = new DefaultConsumer(channel) {
#Override
public void handleDelivery(String consumerTag, Envelope envelope, AMQP.BasicProperties properties, byte[] body)
throws IOException {
Log.i("log_amqp_conn", "handleDelivery() called");
String message = new String(body, "UTF-8");
Log.i("log_amqp_conn"," [Rx] Received: " + message);
//DO SOME WORK HERE
}
};
try {
Log.i("log_amqp_conn", "basicConsume() called");
channel.basicConsume(RX_QUEUE_NAME, true, consumer);
} catch (IOException e) {
Log.e("log_amqp_consume",e.toString());
}
return 0;
}

After spending much time looking in the wrong places I found that the channel was closing due to an unhandled exception in the handleDelivery() function in the "//DO SOME WORK HERE" code. Turns out that if this method errors out that the AMQP channel will close. Thanks.

Related

Bluetooth connection problems

I have a client on a PC and a server on a tablet. I know the MAC addresses for both which means I do not do discoveries.
1. On the client if I use
connectString = "btspp://" + MACaddress + ":4;authenticate=false;encrypt=false;master=false";
It connects fine.
If I change the CN number (4) to anything else, it does not work. How is this number determined?
2. Everything works fine if the tablet is a Samsung with Android 5.0.2 When I use a Qunyico tablet with Android 10, it does not work. I get an error: Failed to connect; [10051] A socket operation was attempted to an unreachable network. What is the problem?
Client on PC – code taken from “Bluetooth-java-client-master”
public class IrcBluetoothClient {
private static void openConnection(String MACaddress) throws IOException {
// Tries to open the connection.
String connectString = "btspp://" + MACaddress + ":4;authenticate=false;encrypt=false;master=false";
StreamConnection connection = (StreamConnection) Connector.open(connectString);
if (connection == null) {
System.err.println("Could not open connection to address: " + MACaddress);
System.exit(1);
}
// Initializes the streams.
OutputStream output = connection.openOutputStream();
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader reader = new BufferedReader(isr);
// Starts the listening service for incoming messages.
ExecutorService service = Executors.newSingleThreadExecutor();
service.submit(new IncomingMessagesLoggingRunnable(connection));
// Main loop of the program which is not complete yet
LocalDevice localDevice = LocalDevice.getLocalDevice();
while (true) {
String toSend = reader.readLine();
byte[] toSendBytes = toSend.getBytes(StandardCharsets.US_ASCII);
output.write(toSendBytes);
System.out.println("[" + localDevice.getFriendlyName() + " - " +
localDevice.getBluetoothAddress() + "]: " + toSend);
System.exit(1);
}
Server on tablet – code taken from https://developer.android.com/guide/topics/connectivity/bluetooth
private static final UUID A_UUID = UUID.fromString("00001101-0000-1000-8000-00805F9B34FB");
public BTacceptConnections( BluetoothAdapter mBluetoothAdapter) {
// Use a temporary object that is later assigned to mmServerSocket
// because mmServerSocket is final.
BluetoothServerSocket tmp = null;
try {
// A_UUID is the app's UUID string, also used by the client code.
tmp = mBluetoothAdapter.listenUsingRfcommWithServiceRecord(NAME, A_UUID);
} catch (IOException e) {
Log.e(TAG, "Socket's listen() method failed", e);
}
mmServerSocket = tmp;
// Closes the connect socket and causes the thread to finish.
public void cancel(){
try {
mmServerSocket.close();
}catch (IOException e){
}
runFlag = 1;
}
//***********************************************************************************************
//
// This thread runs all the time listening for incoming connections.
//
public void run() {
BluetoothSocket socket = null;
// Keep listening until exception occurs or a socket is returned.
while (runFlag == 0) {
try {
socket = mmServerSocket.accept();
} catch (IOException e) {
Log.e(TAG, "Socket's accept() method failed", e);
break;
}
if (socket != null) { // If a connection was accepted
// A connection was accepted. Perform work associated with
// the connection in a separate thread.
// manageMyConnectedSocket(socket);
}else{
try {
mmServerSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
break;
}
}
I know the MAC addresses for both which means I do not do discoveries.
Official Linux Bluetooth protocol stack BlueZ uses D-BUS API to establish bluetooth communication. If you check adapter-api, scanning will create device objects that you need to establish a communication which means discovering is not only done to retrieve MAC addresses only.
Your case might be the same, I would suggest doing discovery first.

Websocket not connected - why?

I try to connected web socket in my android application for this http://192.168.0.6:8989/websocket URl but nothing get any response like error or success.
I am using stomp web-socket library but no success found.
'''// connectWebSocket();
// Create a WebSocket factory and set 5000 milliseconds as a timeout
// value for socket connection.
WebSocketFactory factory = new WebSocketFactory().setConnectionTimeout(5000);
// Create a WebSocket. The timeout value set above is used.
try {
ws =factory.createSocket("http://192.168.0.6:8989/websocket");
ws.addListener(new WebSocketAdapter() {
#Override
public void onTextMessage(WebSocket websocket, String message) throws Exception {
Log.d("TAG", "onTextMessage: " + message);
}
});
ws.connectAsynchronously();
} catch (IOException e) {
e.printStackTrace();
}'''
compile 'com.neovisionaries:nv-websocket-client:2.4'

Android Socket connects to server but doesn't write anything

I'm currently runing a server on Eclipse(local IP 192.168.1.255, listening to port 4567). A client can connect trought sockets and send messages, that will be printed on the terminal by the server.
Part of the server code is the following:
System.out.println("Client connected: " + clientName);
String line;
while (true){
line = in.nextLine();
System.out.println("STRING RECEIVED: " + line + " FROM " + clientName);
}
where in is the input stream of the client socket.
Part of client code, instead, is:
while(true) {
System.out.print("\nEnter your input: ");
line = stdin.next();
socketOut.println(line);
socketOut.flush();
}
So, in example, a possible output on server terminal with two clients connected is the following:
Client connected: Socket[addr=/192.168.1.225,port=54852,localport=4567]
STRING RECEIVED: Hello FROM Socket[addr=/192.168.1.225,port=54852,localport=4567]
STRING RECEIVED: World FROM Socket[addr=/192.168.1.225,port=54852,localport=4567]
Client connected: Socket[addr=/192.168.1.225,port=54945,localport=4567]
STRING RECEIVED: Hello2 FROM Socket[addr=/192.168.1.225,port=54945,localport=4567]
Everything works well, so i'm now trying to access server trough sockets on a simple app developed on Android Studio. The code is:
public class MainActivity extends AppCompatActivity {
#Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
setContentView(R.layout.activity_main);
new BackgroundTask().execute();
}
private class BackgroundTask extends AsyncTask {
#Override
protected Object doInBackground(Object[] params) {
try {
Socket socket = new Socket("10.0.2.2", 4567);
PrintWriter out = new PrintWriter(socket.getOutputStream());
out.println(new String("Hi from Android!"));
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
return null;
}
}
}
But the output is just
Client connected: Socket[addr=/192.168.1.225,port=55001,localport=4567]
and nothing else.
Any advice about the println doesn't send anything? The program works perfectly on Eclipse on both client/server side, so i guess the problem is on Android. Also, i enabled the Android network permissions, so the connection should work.
Thanks in advance to everybody.
EDIT: solved, i just changed Android client code to:
try {
Socket socket = new Socket("10.0.2.2", 4567);
if (socket.isConnected()) {
PrintWriter out = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(socket.getOutputStream())), true);
String line = new String("Hi from Android!");
out.println(line);
}
} catch (UnknownHostException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
You need to either flush the PrintWriter or construct it to auto-flush. It doesn't by default.

Zebra connection android

Does anyone know if BT_MULTI works on Zebra? I'm using ZebraConnection class in my android application and connection with BT:printerAddress as parameter works but with BT_MULTI:printerAddress throws "Invalid connection type".
I'm trying to use BT_MULTI to connect multiple printers in one time, but if you have other ideas of how I can do that I'll be happy to hear them.
This is the code that throws the exception:
Connection connection;
try {
connection= ConnectionBuilder.build(getConnectionStringForSdk(printerBTAddress));
connection.open();
ZebraPrinter printerdemo = ZebraPrinterFactory.getInstance(connection);
} catch (ConnectionException e) {
System.out.println("Connection could not be opened"+e);
} catch (ZebraPrinterLanguageUnknownException e) {
System.out.println("Unable to create printer"+e);
}
private String getConnectionStringForSdk(String btAddress) {
String selectedPrefix="BT_MULTI:";
final String finalConnectionString = selectedPrefix + btAddress;
return finalConnectionString;
}

Connecting Android device to multiple Bluetooth serial embedded peers

I'm trying to find a solution for this setup:
I have a single Android device, which I would like to connect to multiple serial embedded devices...
And here is the thing, using the "Normal" way to retrieve the Bluetooth socket, doesn't work on all devices, and while it does, I can connect to multiple devices, and send and receive data to and from multiple devices.
public final synchronized void connect()
throws ConnectionException {
if (socket != null)
throw new IllegalStateException("Error socket is not null!!");
connecting = true;
lastException = null;
lastPacket = null;
lastHeartBeatReceivedAt = 0;
log.setLength(0);
try {
socket = fetchBT_Socket_Normal();
connectToSocket(socket);
listenForIncomingSPP_Packets();
connecting = false;
return;
} catch (Exception e) {
socket = null;
logError(e);
}
try {
socket = fetchBT_Socket_Workaround();
connectToSocket(socket);
listenForIncomingSPP_Packets();
connecting = false;
return;
} catch (Exception e) {
socket = null;
logError(e);
}
connecting = false;
if (socket == null)
throw new ConnectionException("Error creating RFcomm socket for" + this);
}
private BluetoothSocket fetchBT_Socket_Normal()
throws Exception {
/* The getType() is a hex 0xXXXX value agreed between peers --- this is the key (in my case) to multiple connections in the "Normal" way */
String uuid = getType() + "1101-0000-1000-8000-00805F9B34FB";
try {
logDebug("Fetching BT RFcomm Socket standard for UUID: " + uuid + "...");
socket = btDevice.createRfcommSocketToServiceRecord(UUID.fromString(uuid));
return socket;
} catch (Exception e) {
logError(e);
throw e;
}
}
private BluetoothSocket fetchBT_Socket_Workaround()
throws Exception {
Method m;
int connectionIndex = 1;
try {
logDebug("Fetching BT RFcomm Socket workaround index " + connectionIndex + "...");
m = btDevice.getClass().getMethod("createRfcommSocket", new Class[]{int.class});
socket = (BluetoothSocket) m.invoke(btDevice, connectionIndex);
return socket;
} catch (Exception e1) {
logError(e1);
throw e1;
}
}
private void connectToSocket(BluetoothSocket socket)
throws ConnectionException {
try {
socket.connect();
} catch (IOException e) {
try {
socket.close();
} catch (IOException e1) {
logError("Error while closing socket", e1);
} finally {
socket = null;
}
throw new ConnectionException("Error connecting to socket with" + this, e);
}
}
And here is the thing, while on phones which the "Normal" way doesn't work, the "Workaround" way provides a solution for a single connection. I've searched far and wide, but came up with zip.
The problem with the workaround is mentioned in the last link, both connection uses the same port, which in my case, causes a block, where both of the embedded devices can actually send data, that is not been processed on the Android, while both embedded devices can receive data sent from the Android.
Did anyone handle this before?
There is a bit more reference here,
UPDATE:
Following this (that I posted earlier) I wanted to give the mPort a chance, and perhaps to see other port indices, and how other devices manage them, and I found out the the fields in the BluetoothSocket object are different while it is the same class FQN in both cases:
Detils from an HTC Vivid 2.3.4, uses the "workaround" Technic:
The Socket class type is: [android.bluetooth.BluetoothSocket]
mSocket BluetoothSocket (id=830008629928)
EADDRINUSE 98
EBADFD 77
MAX_RFCOMM_CHANNEL 30
TAG "BluetoothSocket" (id=830002722432)
TYPE_L2CAP 3
TYPE_RFCOMM 1
TYPE_SCO 2
mAddress "64:9C:8E:DC:56:9A" (id=830008516328)
mAuth true
mClosed false
mClosing AtomicBoolean (id=830007851600)
mDevice BluetoothDevice (id=830007854256)
mEncrypt true
mInputStream BluetoothInputStream (id=830008688856)
mLock ReentrantReadWriteLock (id=830008629992)
mOutputStream BluetoothOutputStream (id=830008430536)
**mPort 1**
mSdp null
mSocketData 3923880
mType 1
Detils from an LG-P925 2.2.2, uses the "normal" Technic:
The Socket class type is: [android.bluetooth.BluetoothSocket]
mSocket BluetoothSocket (id=830105532880)
EADDRINUSE 98
EBADFD 77
MAX_RFCOMM_CHANNEL 30
TAG "BluetoothSocket" (id=830002668088)
TYPE_L2CAP 3
TYPE_RFCOMM 1
TYPE_SCO 2
mAccepted false
mAddress "64:9C:8E:B9:3F:77" (id=830105544600)
mAuth true
mClosed false
mConnected ConditionVariable (id=830105533144)
mDevice BluetoothDevice (id=830105349488)
mEncrypt true
mInputStream BluetoothInputStream (id=830105532952)
mLock ReentrantReadWriteLock (id=830105532984)
mOutputStream BluetoothOutputStream (id=830105532968)
mPortName "" (id=830002606256)
mSocketData 0
mSppPort BluetoothSppPort (id=830105533160)
mType 1
mUuid ParcelUuid (id=830105714176)
Anyone have some insight...
WOW, every time this strike me down with one big WTF?
This was a race condition issue, which clearly works on one version of android, and not on another. On Android peer I was parsing the packets received from the socket:
public class SocketListener
implements Runnable {
private boolean stop;
private OnIncomingPacketListener packetListener;
#Override
public void run() {
InputStream inputStream;
try {
stop = false;
inputStream = socket.getInputStream();
while (!stop) {
Packet packet = Packet.getPacket(inputStream);
lastPacket = packet;
if (packet.getDescriptor() == Packet.HeartBeat)
lastHeartBeatReceivedAt = System.currentTimeMillis();
else if (packet.getDescriptor() == Packet.LogEntry)
log.append(((LogEntryPacket) packet).getLogEntry());
synchronized (this) {
if (packetListener != null)
packetListener.onIncomingData(EmbeddedDevice.this, packet);
}
}
} catch (IOException e) {
logError("----- BLUETOOTH IO ERROR -----\n #: " + EmbeddedDevice.this, e);
return;
} catch (RuntimeException e) {
logError("----- BLUETOOTH LISTENER ERROR -----\n #: " + EmbeddedDevice.this, e);
throw e;
} finally {
socketListeningThread = null;
}
}
}
Where the Packet.getPacket(inputStream) is:
public static synchronized Packet getPacketInstance(InputStream inputStream)
throws IOException {
int data = inputStream.read();
Packet type = null;
for (Packet packetType : values())
if (packetType.packetType == data) {
type = packetType;
break;
} // race condition here...
if (type == null)
throw new IllegalArgumentException("Unknown packet type: " + data);
try {
Packet packet = type.incomingPacketType.newInstance();
packet.setDescriptor(type);
packet.readPacketData(inputStream);
return packet;
} catch (IOException e) {
throw e;
} catch (Exception e) {
throw new IllegalStateException("Error instantiating type: " + type.incomingPacketType.getName(), e);
}
}
And every time a packet is completed, the next thread should have gone in to perform it parsing.
My guess is that there is some sort of lock on the port, that together with my implementation caused the second thread to block indefinitely, once I've removed the parsing to different instances per thread, the issue dissolved.
This insight was inspired by Daniel Knoppel, the guy from the mPort link.
Thanks Daniel!

Categories

Resources